changeset 1518:2e8063097240 redmine-2.4-integration

Merge from branch redmine-2.4
author Chris Cannam
date Tue, 09 Sep 2014 09:32:11 +0100
parents 17c7ffe039b1 (current diff) b450a9d58aed (diff)
children afce8026aaeb
files .svn/pristine/00/0009a621965fc195e93ba67a7d3500cbcd38b084.svn-base .svn/pristine/01/019777b51c435b18c756e5573fde25c903195b68.svn-base .svn/pristine/01/01b21d04c9e912327dc0059ef282ceb1a603f54f.svn-base .svn/pristine/01/01cfbfdc38592dff3cbe5b1b36118aa0e1e65223.svn-base .svn/pristine/02/027410b40ae4e2d4f4be0368cf13b4cdb0164b5f.svn-base .svn/pristine/02/02fe391dd14e50d29ad45f8bf8dea30be02556c5.svn-base .svn/pristine/03/033d1080f94d03c5b655f6847c2f7606bd5d5f60.svn-base .svn/pristine/04/0490719dc3185896fb07e210967a75c0f5e40a0a.svn-base .svn/pristine/04/049234b460fae5eb30eba8a2487d0eac09c6701f.svn-base .svn/pristine/05/05d8cde4a4e9772f7dcbafb481eff20153ca4409.svn-base .svn/pristine/05/05fb4e3ebed828cf639f80e5d1d6da6095d43000.svn-base .svn/pristine/06/06906d5d51f832720062a81972796df1a81f69a3.svn-base .svn/pristine/06/06927559eed548b89dcc19d7fe7d3d26046b88c1.svn-base .svn/pristine/06/06efa9c81bf4ffa47e3211023e46fcb09d4eac0f.svn-base .svn/pristine/07/07ff3aff4af2ca5266644ab7e838820cda8c8752.svn-base .svn/pristine/08/086f4bbd984edf33971e918b1e5330fe445e9dd7.svn-base .svn/pristine/08/088eae42f08379f3106075b388f036d1754d148c.svn-base .svn/pristine/08/08c1f1410c30c4d18ef6cbcbd8954d1721fb044b.svn-base .svn/pristine/09/094f0fabb02fa5ce798642abc8745a5aba89d2d9.svn-base .svn/pristine/09/09d005add00d07aeb449a6c04ad00db8e1f72fbd.svn-base .svn/pristine/0a/0a01ef88ba34bfc6a3c1cef8891538f7504e9b0c.svn-base .svn/pristine/0b/0b7befce1d7322f245834ffc9480adf8d5c60890.svn-base .svn/pristine/0b/0b8a142f46ed608799d7faf6016772f4b1f09f42.svn-base .svn/pristine/0b/0bba8bba58df7fc70a5a93a0d2973b34736d639d.svn-base .svn/pristine/0b/0bd8b54775e82ba1bfa004993bdb8bf956e85c99.svn-base .svn/pristine/0c/0ca7bda81025c5f7a9ebad14d8b0c08f3a0b8176.svn-base .svn/pristine/0c/0cb5ab49f6fd89443044a7c2f37992f0e2874866.svn-base .svn/pristine/0c/0cc9601ec1a6e3a27ab4a946d394cf4ba82254b4.svn-base .svn/pristine/0e/0e9c8f11b3db41702079f085c94dfa01133abcd9.svn-base .svn/pristine/0f/0fc81c2978046c22ad1fddeadeabe4e288474193.svn-base .svn/pristine/11/11276ad92ab446760ef27dc63e4ad98666e8240c.svn-base .svn/pristine/12/120840d537ad68f417065b102e2763e8f985fe62.svn-base .svn/pristine/13/134ab6c377c7865f7eab83c298719a41c97ec009.svn-base .svn/pristine/13/1398acbd60647babc95a74c09ce2afa2acef1b0b.svn-base .svn/pristine/13/13e6190365f9e0ad8532e5e563cf7ad5676797a5.svn-base .svn/pristine/13/13f3f51390f5b007f8a6b4667437b3436606259a.svn-base .svn/pristine/15/1501976e33da8b363bb737aa1d51d7b528152400.svn-base .svn/pristine/15/15b7222cb6b5695205873370eda995f4170a4d8e.svn-base .svn/pristine/15/15c19f10a4e2450833d4d36fd99f66518ba44283.svn-base .svn/pristine/16/163200e35f1d8c0484dc12a3ebb2256afa7733a8.svn-base .svn/pristine/17/17aa6f42b9915157fc191f136c4be06527af6f55.svn-base .svn/pristine/17/17eeb63ea895552f87458a07894df799f570d379.svn-base .svn/pristine/18/182957517dcdfdb9bed4a7cc03f63aeef4b1c15d.svn-base .svn/pristine/18/183dca49dc870131da0c794df1c3f5f569d0e6e5.svn-base .svn/pristine/18/18aaa55b2d77150962ade434e4a8c39b73c97814.svn-base .svn/pristine/18/18af7ca4dac0c217561ab69b8406264b81adb03a.svn-base .svn/pristine/19/190e5bea2d5dc9984a86fa22ae8cc4dd749898ab.svn-base .svn/pristine/19/191c54aa364bc303830fb03453b541edfd9e5945.svn-base .svn/pristine/1a/1a3135bf503a709c26b5156223514133ddf98de3.svn-base .svn/pristine/1a/1a57484f351c2899093aa4b926665fc8327667ab.svn-base .svn/pristine/1a/1a5ac9a1d7cbc1a58738649fabccca79dc7633e5.svn-base .svn/pristine/1a/1a8020fad87f2bec2c86c62dc30a6bf033a7c796.svn-base .svn/pristine/1a/1ae3258fdcdf6aa143d4aa4fdfd79484152c6554.svn-base .svn/pristine/1b/1b56f9a09e214e641bcc7750244e8fb8e49ba7c3.svn-base .svn/pristine/1c/1c27182fa8ab48906fb7a4d556796242f651644e.svn-base .svn/pristine/1d/1d8c43c17d3233bffb7ec0f72aeb2fc2a1c616a9.svn-base .svn/pristine/1e/1e23a74057f558ab69d6074a0eabbe9696b5a8db.svn-base .svn/pristine/1e/1e54d19d4970142ec949fe4202f5ffe30b1f8dbf.svn-base .svn/pristine/1f/1f46b0be9dff718da9b5754753e6d89331b5e22e.svn-base .svn/pristine/1f/1f882abb5f1807e56ffd3445088d6c8aa33ef8e5.svn-base .svn/pristine/20/20576c20e326be9d43917cbd74b999241edc31c3.svn-base .svn/pristine/20/2087b528196b7332c8234e9ab56b21a9c4114103.svn-base .svn/pristine/20/20a6292c961b1184d69b8461d3e60b34dcd95f04.svn-base .svn/pristine/20/20aee30a3886ed67fbcf2637dc7c9a63361c83fd.svn-base .svn/pristine/21/210434ccffe59c9bbad805f6aeb0141711b6bd46.svn-base .svn/pristine/21/21b08aea1ac3dbc27c974e37d3d3c4f6952cdffd.svn-base .svn/pristine/22/2231a90d74735e9a796f1508f0e2f1bfd1774f24.svn-base .svn/pristine/22/2254c6ada14f9698b9a4320070c88983213e381b.svn-base .svn/pristine/22/22a7851f8ede366924cba144fbbe8879121ee70d.svn-base .svn/pristine/22/22e2e1f53cc1372b24c8bb03f573ceefbdb7fa57.svn-base .svn/pristine/23/23d24e0346024a68e636758e1fe724435ac78a94.svn-base .svn/pristine/23/23f046e7217770bca11bfe9989b755a158f48868.svn-base .svn/pristine/23/23ff873f0bf0f2e45a3709caf12bc84dab7be570.svn-base .svn/pristine/24/2433aef8bea3b0c55a9f7bf03a1c8b0533749f72.svn-base .svn/pristine/24/24abfa79128b2a39ef97f13bee5e153f6b122577.svn-base .svn/pristine/24/24b4bc532dbfbdbadb24d22bdcba74f2493b0b5a.svn-base .svn/pristine/24/24ebd90070f1307a8f6d2f2f35671e06e60bb2b7.svn-base .svn/pristine/25/25f1da6f66db9d07326385e2039be298e7f220f8.svn-base .svn/pristine/26/268f3cd3f61de314baeae7c147ac3b2585846bcc.svn-base .svn/pristine/26/26cd514059c01b6bbe50d8e07c103ad7d4e81104.svn-base .svn/pristine/26/26d9747ae706cea5f68ea0007e9fb7e1bf0c8d18.svn-base .svn/pristine/27/2745a50d7301c30263d5450e181481b6eeb6b406.svn-base .svn/pristine/27/27aa9063bcb916743c8adfa7af143c30c526db50.svn-base .svn/pristine/27/27ff0c8aa6059bb3d3244c9053898a1f8e9c2b1e.svn-base .svn/pristine/28/28ed7202edbfd59150a254a3d4ac24d16c42373f.svn-base .svn/pristine/29/29f1e7420f4ca87ea1757481bcca4dae405f53b6.svn-base .svn/pristine/2a/2a59baf70fb68ac9f90f4306e930088af4138a70.svn-base .svn/pristine/2b/2b29654b95c6aadbc6d9e5c8347d2c96aa39a7e1.svn-base .svn/pristine/2b/2b52b333ebdd9a328bfca27bab6d9bb1f5c45425.svn-base .svn/pristine/2c/2cb77dbabbdb76fb313ca1932dc0b27e4c8922e1.svn-base .svn/pristine/2c/2cd1e675be2a1ca2a16f8842efaf3d36d343a516.svn-base .svn/pristine/2c/2cfeab9b9366f48fd720b77fb1dc5f6f878ef869.svn-base .svn/pristine/2d/2d3d652686003e0e75f2451ee9050de946a60dda.svn-base .svn/pristine/2d/2d85d0783f59c365e1251c736bcbc44da38bc043.svn-base .svn/pristine/2d/2dbd0564d495b47bea2303b32f1609a8bf5c4b1a.svn-base .svn/pristine/2d/2dc8d26abfe6ba28f20c56a8a294830b5d124597.svn-base .svn/pristine/2d/2dfab9f6389ac98654c616cc002d4ad37cf273c9.svn-base .svn/pristine/2e/2e0a51818d267797dffec1a0e20aa3a664a20e28.svn-base .svn/pristine/2e/2e26af3877bdd2fe792449a4fd743a6ba7463f7e.svn-base .svn/pristine/2e/2e330182b29b2891c9c2bca0816fa09b38e7c57b.svn-base .svn/pristine/2e/2e9778d3950cea9aad42938a07deac546bf3beda.svn-base .svn/pristine/2e/2edea84d520ab6a5b95483c3c5399a71bdf3d4fa.svn-base .svn/pristine/2f/2f133168a880fffbd35ca248f3d226a5ea263cb4.svn-base .svn/pristine/30/301185c13f555c3833de6896f8f45895314d605b.svn-base .svn/pristine/30/30802f3b65425b8bb22f7cebacbf8ac4352f1e79.svn-base .svn/pristine/32/3223a76e70547eaec39a0a66a9b27b9eba0314ac.svn-base .svn/pristine/32/323d1bcc86907f9d5a2126f30f3d7a3ae8693252.svn-base .svn/pristine/32/326a62adc02ab48e12d9e9d717fea2e84b8c44cf.svn-base .svn/pristine/32/327b76cc374d806380bae0c4d024997da523a2a5.svn-base .svn/pristine/32/32b666007142e154714e20e7baa96c56a45356e5.svn-base .svn/pristine/33/339df18b16b4ab05fedfba76e31080e6dda3b82a.svn-base .svn/pristine/35/35e985416112eca8f5c8494cbf66a6a622c59107.svn-base .svn/pristine/37/3761b0e47a324667f29e56ceb9695ed94f68fe4d.svn-base .svn/pristine/39/390d75b45f1cb36da0ca09b41de1406635eaa338.svn-base .svn/pristine/39/391b1c790687d518fea17dcd03fc5883b7da327b.svn-base .svn/pristine/39/3942548809d01a94e378f6a25d893f1c4053354a.svn-base .svn/pristine/39/399f2a5d4375067a1c2f5abc78f9f28143ca9321.svn-base .svn/pristine/39/39a608089a590c01af61f645951f37bfe827c689.svn-base .svn/pristine/39/39e07ef2d5632f8e7ca245cda7735bd6e7674f6d.svn-base .svn/pristine/3b/3b77726a8efda3938653233bf84d8e02401c4bc3.svn-base .svn/pristine/3d/3d264827557eaf8b65d3068714787c51e68d02b2.svn-base .svn/pristine/3d/3d6522340e1723225cb18ddbafc5c9dc0b5f8799.svn-base .svn/pristine/3d/3d7003238eceffbbaba3bf34003b59ea441ffc00.svn-base .svn/pristine/3e/3e7a4b29a1b991aef04200318dd8a5df349fe39d.svn-base .svn/pristine/3f/3f7e33eb719b73cf1721b389cca78ecdef336acd.svn-base .svn/pristine/3f/3f94297661bca0411e24d438a57b40f9f718ed59.svn-base .svn/pristine/40/40689c0c3542244c3df167e6c12a7f9af9376e9b.svn-base .svn/pristine/40/407f7e2d4e08a32e78ca65cbc6b2ee007be59736.svn-base .svn/pristine/40/40b857ca7c7de72d5c1758ba52344afd6a5847fd.svn-base .svn/pristine/41/4113a8ca258eb3b9d10aacea8fe7152c8f9122c6.svn-base .svn/pristine/41/414d847bcbb5d1b481c5b6e074d2d95ff30c291d.svn-base .svn/pristine/41/41666c76b3a63b119e23476dd87dae257e309108.svn-base .svn/pristine/42/42095fdeb59e4c54c780a1fd8312c01640c1df4f.svn-base .svn/pristine/42/42f2467cb688a2f7bda7722fe0d6a10336e81f57.svn-base .svn/pristine/43/4333e2faed9865820292b92a3a8ebf203749d50e.svn-base .svn/pristine/44/4427f53bdbb62ef1eca701cca69cda8b76215c5d.svn-base .svn/pristine/44/442810adc553727c9efe816480daa7fe72b8c040.svn-base .svn/pristine/45/4537efe545b75bf585f6f1b2f82d7cbf9d1195c2.svn-base .svn/pristine/45/45b8269cf1731acb2f145d6ea43cdd52da6f4d4a.svn-base .svn/pristine/45/45d6a4c7517a59a47326ffe4aae5abf9f33149fd.svn-base .svn/pristine/45/45fedacb83fa4bf0b530842cc4c9e44d1242cd73.svn-base .svn/pristine/46/460823ad942a6dbaf3986f763002fe9ab659fb36.svn-base .svn/pristine/46/46c80cd596249868cd44c8d7343c86bdddc1eb3f.svn-base .svn/pristine/47/4753e6da278a7ff7f4570acb7cd3a1cfc5512fc7.svn-base .svn/pristine/47/476f7092547a421c5cdba23a45c9f5c323dff122.svn-base .svn/pristine/47/47a7b4898fe505591d4572ccd817f96b3fd4d27d.svn-base .svn/pristine/47/47fe92274420b778273849bcd6f771fbd1ac083b.svn-base .svn/pristine/48/4829d2fe162c5f9c318c8ff9b05ff5fc25513144.svn-base .svn/pristine/48/482dc54fc612e4f812361911050f6c949928488f.svn-base .svn/pristine/48/485c22af8fcad2b07fb5864c22ee67cc2bfd6c6f.svn-base .svn/pristine/48/4881b5ad6e4efa4165188246776dbe492c56e6df.svn-base .svn/pristine/48/48978cef54e6b0d716c9ba5b5c6c5a3e24326336.svn-base .svn/pristine/49/493a8cd26b7fa714fe78dd4274ecdc966ff8a00e.svn-base .svn/pristine/4a/4a1058fec0661c02d0fe7d4f1388a59811624904.svn-base .svn/pristine/4b/4b33122ac4316f4c1a07b0e693b6a8dd1a319fd4.svn-base .svn/pristine/4b/4ba58f8d37b5a8de881d99e50a2cc37a4cef0a15.svn-base .svn/pristine/4c/4c336c258123fb4e9b45bc7fc7cd3f56f7293d30.svn-base .svn/pristine/4c/4cf321de05d6993523d4f53f4c3078dcaf49b46c.svn-base .svn/pristine/4d/4d32c1bf128521985a7cc66ecfe319a7797f8c8c.svn-base .svn/pristine/4d/4d4d388d3654f2fbefb4fdd7c3e99a9ffa1a3eeb.svn-base .svn/pristine/4d/4dbc763764f2013267075c3f49bdd12a87fc0d1b.svn-base .svn/pristine/4d/4de18371feb9c1f0e9402b1bd393643194d5f79d.svn-base .svn/pristine/4f/4f68d76f852340754bcbaa389f8acdaba7e60be4.svn-base .svn/pristine/4f/4f8a45bde853d973a3752802f135b2f9fd445eb5.svn-base .svn/pristine/4f/4fc2ff472415472e5bc5a895e07b22fbca85faf1.svn-base .svn/pristine/4f/4fc60931645e3d4832cac83cc1c9d2c25c5df098.svn-base .svn/pristine/50/50652fe8225e67d65adfd17ea2e35e3021fb4461.svn-base .svn/pristine/51/514f8aeb54e3381fa2badbe487c0d7fd6bad2fd0.svn-base .svn/pristine/53/539b469592377fe5ec04bc7018cfe2f6bf2322bc.svn-base .svn/pristine/53/53a436ecc8b372b3e21fc3c743b6fa4cc9e4b865.svn-base .svn/pristine/53/53a91881211d028f264cd0f5ef639191d1262e38.svn-base .svn/pristine/53/53be7ecb5340425e02b87b5afa5c2fd05785f736.svn-base .svn/pristine/54/545555b790077e8ce0b627745954990d978f492e.svn-base .svn/pristine/56/56225b936777b98c482ec9e85d159d74d839691e.svn-base .svn/pristine/56/5649977123508ab2f6673a662fcdabf65b2787e2.svn-base .svn/pristine/56/565b665c10da577a12dc50053706643709a0c80a.svn-base .svn/pristine/57/570f0eb4fa534b2c22e5b144e19ab45bcea2dbda.svn-base .svn/pristine/58/58427de0be17a56a22c9ff50d1ec281682e9bdab.svn-base .svn/pristine/58/584923323e8dc0fd68ba4e96b679332b9ee9eb19.svn-base .svn/pristine/58/58ad4095c1a6118f6d53fd92a945cd194604e422.svn-base .svn/pristine/59/59560647b1b38d17ca5eda58f2c560506ef65f44.svn-base .svn/pristine/59/5957c73ec3e45b1dba5f2bd95614bcd541de4b15.svn-base .svn/pristine/5b/5b5912958e71fec54e66733c9c7981555c23902f.svn-base .svn/pristine/5b/5b67cbc43876349cb50763840008cc0544dfb9b5.svn-base .svn/pristine/5b/5bd58dbcc9700e9a0143a2bd31d516491119c122.svn-base .svn/pristine/5c/5c1734e1eca1c54bac30b17ddeecdedbc05caf30.svn-base .svn/pristine/5c/5cefc982f83157ee64c82964ccc1a3e15fc78cb5.svn-base .svn/pristine/5d/5d26bd43e6982490a87abc50362d543225e9666c.svn-base .svn/pristine/5f/5f34122110535f3ec5de210020321433576b63f3.svn-base .svn/pristine/5f/5f91c8ec766f59461497fadde2dab5afeb5e2ac6.svn-base .svn/pristine/60/60a95a1966b625bd87358ca8fc028478e501f2bb.svn-base .svn/pristine/61/61f5175c584e56d932e6fd6922f31fce1b57acd4.svn-base .svn/pristine/63/6303e4e27f22b7c0923d90722df3a66861c6f0f3.svn-base .svn/pristine/63/634ac7c9412839a15f45fce185c715e696a25baa.svn-base .svn/pristine/63/638ef428af64a93a5a54376e8e444c15761d3973.svn-base .svn/pristine/63/63f5d9f908a9cb71c1fdf7287c1a8cd3db047d81.svn-base .svn/pristine/64/6402c0873c916f8ca24a20adde0b93d3110a6089.svn-base .svn/pristine/64/6495ba1b375d76ae48a1a29718388eabb1d9a8c0.svn-base .svn/pristine/64/64c4b3023914b8e9badc4f2743e75346c30f91ab.svn-base .svn/pristine/65/6522becd35e6716c94ac60c2f3bd1780740bea87.svn-base .svn/pristine/65/6548ced1be2ac2971e9540ff4fe8979b3f03573e.svn-base .svn/pristine/65/65b88641ff8e4579cbf40b69a6bf7f5392a27740.svn-base .svn/pristine/66/662e86180d02fd07ea0b83b2c6615af46feab399.svn-base .svn/pristine/66/66834a4bdddfd399aac57e87263804a8152e50b5.svn-base .svn/pristine/67/67fb9a2c82ee9bb7b43a202b8b3be8deec0d41f4.svn-base .svn/pristine/68/68cec9b340a32b5033a24e6ea73291b5b640c745.svn-base .svn/pristine/69/69aad9646672b101f4780577efca970e899cd21a.svn-base .svn/pristine/6a/6a96b935778cbb8f7a670a2735694f941fa3d694.svn-base .svn/pristine/6a/6ad28dd349d922a2ada017eb617dd963b5950896.svn-base .svn/pristine/6b/6b2c4a778dca89a31620a55a65371a0aa4017062.svn-base .svn/pristine/6b/6b42e6adb8523e15e9ff195fc3496e5284a69b00.svn-base .svn/pristine/6b/6b4c50390f939790cfd61f918f38b017e779b22e.svn-base .svn/pristine/6c/6c32beaaa0775810013dacee7377be5689730569.svn-base .svn/pristine/6d/6d3df7e3002585d4b82d0225bf30bfb49566483a.svn-base .svn/pristine/6d/6ddb785f30a0d1233af9e71a8c3b041341c78af5.svn-base .svn/pristine/6e/6e61a701e2749bf002d37820f0ff37fbc966f8bd.svn-base .svn/pristine/6f/6f3de0785368c550e0511d7f874b1261b16e18b8.svn-base .svn/pristine/70/7005c1ac60bfaef4c1c73b8db2692b1b9a732a71.svn-base .svn/pristine/70/70c517dee606cfef8e0ccb2978ba7929048caf58.svn-base .svn/pristine/70/70e864184fd8408391ed37d61337591c474549c4.svn-base .svn/pristine/71/714859f726ef05e105f7c83270e22457a9138242.svn-base .svn/pristine/72/72607bd4ab6cb744483458ba6f765737733a7ddf.svn-base .svn/pristine/73/7309716b5db2ba64867602eae0ca0931c23991c4.svn-base .svn/pristine/73/7324b60def8b61259e4fe88d626f6df74b027500.svn-base .svn/pristine/73/73cf79b8d745cac74b4b29d58fecb04843a6f726.svn-base .svn/pristine/74/74bcc529787db769558f2ce1cd97484fa4286471.svn-base .svn/pristine/75/75cbf5c4f829621de0ddf156af2f88bad5bed475.svn-base .svn/pristine/76/760034b00a77f0a73cc21094aabb292a6e6e29ae.svn-base .svn/pristine/76/7613b919071a0b15c5315d48513bd037d7d92c4b.svn-base .svn/pristine/76/76c6293fe37375af70e9b0a4cdcbec2106159b62.svn-base .svn/pristine/76/76f5b1657c4e0eb2717b1dfffe6b49bb8cd094b8.svn-base .svn/pristine/77/771517d2f5d100730b0ffcf7efa80c42ba739a96.svn-base .svn/pristine/77/7727bb04d0abb3e8e4031848fb82a82cb998f0af.svn-base .svn/pristine/77/77b5f4fec79f0d6eb61a76e965e02cb7504641fe.svn-base .svn/pristine/78/78376d3215166c5e884949655b3cf6e5caa6e30e.svn-base .svn/pristine/78/7884d1a52f46dcfb203fc57885fb084b78063ba1.svn-base .svn/pristine/78/788c80634e0b1d20f293008ce93f6cb1d4ce218a.svn-base .svn/pristine/78/78d4b11a09b045fdd7cd2b6a434ac47f6be2b36b.svn-base .svn/pristine/79/791795b2319be82f4ccbdcd799aa17c64410dd34.svn-base .svn/pristine/79/79599156ceffeaaae36ac3fa01857d9ccf943ee2.svn-base .svn/pristine/79/79e517db7aa41460bc02061dfd2de5b4541e346b.svn-base .svn/pristine/7a/7a0c6d75615202ef4fc661b90d1880959dd6577d.svn-base .svn/pristine/7a/7ae54c43f56efaece5e4ecd309a31e0849a96145.svn-base .svn/pristine/7b/7b2768a4d4eb7647598cd0f016196785ba208ee6.svn-base .svn/pristine/7b/7b34d32f77bf4ac1a9acbab33d65a9b853c9c460.svn-base .svn/pristine/7b/7b4fab45dadc851ece3c8f70d2660b6cfb36eddc.svn-base .svn/pristine/7b/7b5e0d5bd15f4cf751b3c4e4e461784203fe4354.svn-base .svn/pristine/7b/7b79b397a58396e6741da83eb4295f4a9b8a4385.svn-base .svn/pristine/7c/7c4ad291b9dee635242d3836e9f5883b5338f41d.svn-base .svn/pristine/7d/7d062943a639ef0006481fe9e87f6780c25c226e.svn-base .svn/pristine/7d/7d347f5736383447d929cfa493b44727c73c536a.svn-base .svn/pristine/7e/7e362e9571e296e9ab312aca34fbe7dfde644cd2.svn-base .svn/pristine/7f/7f4c045aa51ecaded0b2c44282890f940876ab00.svn-base .svn/pristine/7f/7f767334e88e235349f209d5526da1c032d7d91c.svn-base .svn/pristine/80/801b8da4e3d5456a0e7124a4e9736317dd235f5b.svn-base .svn/pristine/80/803dbec2bea6411200938908113051447e1d81f1.svn-base .svn/pristine/80/805e2c5bfc6d36709102674e1adfa9d208ce9081.svn-base .svn/pristine/81/81609ac3f30763970c764d86e00b3512d937facd.svn-base .svn/pristine/82/821d4ef82eeed4cbb18ce34368856a650d31c2d8.svn-base .svn/pristine/83/83e9bc8b42104b913718f6e8799f58710545ff76.svn-base .svn/pristine/84/84091f2a3428fd01f5592918d3e84fd8efa86bdf.svn-base .svn/pristine/84/841186dcecffe41ae1f674267a63d3d2f8a4647b.svn-base .svn/pristine/84/844e1f7efcdb7d2e09fc680929a5a6cad80561f3.svn-base .svn/pristine/84/84675d4c5913f4d4787034973ce3aa888eb2ae42.svn-base .svn/pristine/84/849f87222b3ad4c6513f88d2c270ccbbefd56465.svn-base .svn/pristine/85/8519fb0f08b4338ed0712c0e2af20a32e713969e.svn-base .svn/pristine/85/854825bbe47c50aa884c3809103ed51a05bc7f14.svn-base .svn/pristine/85/856339cef1bdf5f11b116c77c2ac5a76171899ce.svn-base .svn/pristine/86/860e2f012a8a16391f9ed2054fc730df3d67d9c9.svn-base .svn/pristine/86/86143f66fe1f5d10a7a618e2496577aaa346c237.svn-base .svn/pristine/86/862a776ed4eda62592dadbb92180115063e923b2.svn-base .svn/pristine/86/868f0e4e1e397d79702a7dad295d76e1aae77f8f.svn-base .svn/pristine/87/871ab69c9430fd870a684b73b2e5c6c68ed7f0f1.svn-base .svn/pristine/89/8937afa1653ec0053686c11b0489477d9550a47d.svn-base .svn/pristine/89/89f2f1de1b0c1a744af1b4d7a2c5c156ca193d25.svn-base .svn/pristine/8a/8a339bcd7d20e6ca60eea513a81446d12d132459.svn-base .svn/pristine/8a/8ab4630ebd77e09c1eecc6ce7e00d173fda9baab.svn-base .svn/pristine/8a/8ad0e856fe663028d1a8b29da96008e903c9b16e.svn-base .svn/pristine/8b/8b54895a280a4b6be2315b819f9e36a6caaa65f2.svn-base .svn/pristine/8b/8b6b9cb4de924997fd5c8d066cf49e5fb943de93.svn-base .svn/pristine/8b/8b8a4a4fb98bb4ad97ae1d153aef221af93fc010.svn-base .svn/pristine/8b/8b8ba498cf3cdcb76cdc45e1ecf9d424b5e9b3cc.svn-base .svn/pristine/8b/8bf2ae2c5468c4bc357e9e242162af0247815ad9.svn-base .svn/pristine/8c/8c1d2e96303e1f62e53705f1a07477a847f9fb94.svn-base .svn/pristine/8c/8c56aede35efde6338d434d4d231eb2b6c6fcfdd.svn-base .svn/pristine/8c/8cbb18f9615aba75e56d4a85191eb4770033c6ee.svn-base .svn/pristine/8d/8d49dae3dcbe3c33e8ba68468bf87f82d0d0b226.svn-base .svn/pristine/8e/8e8e8287a74b0335843089c614a9c33ed22e75db.svn-base .svn/pristine/8e/8ea06d22d8f2b1998d7e2d84f7804f12208c49ad.svn-base .svn/pristine/8f/8f979a2960a289ab9a4542dc8883cce7d74526d2.svn-base .svn/pristine/8f/8f9f9a92c19e3920a1c97c78a5493f483781cbcd.svn-base .svn/pristine/90/901740a4f156c3558f585b467304885cb6b1e403.svn-base .svn/pristine/90/90614dcc50db90b38ba908659a9cd6e4367e61ab.svn-base .svn/pristine/92/9200969636fc087a7427e652c085c04fee498c33.svn-base .svn/pristine/92/92e79cf48ee767b10d559c8d0bc187ea50742a7c.svn-base .svn/pristine/93/93670bab9f61b2b691063ad9fe7c015dfa58e59c.svn-base .svn/pristine/93/939cceaf70f6f951d3ca40822110175a73d3a953.svn-base .svn/pristine/93/93a376c27a710917c3458387b07a830523557ad3.svn-base .svn/pristine/93/93f85fbfa5d1803a533dc2903452408ac582b22a.svn-base .svn/pristine/94/94765944a40a57c939e4d5db59efec674343d66e.svn-base .svn/pristine/94/94850f049cba8fd1d7b631af60e061c441dc4401.svn-base .svn/pristine/94/94b0a87688b1d61b6fb66241d11ae9e0ee65fa3e.svn-base .svn/pristine/95/954503d8b00c9c216119d7e8717102d3c9f6c727.svn-base .svn/pristine/95/9557b02b329df92601cf23c4bbe77124fa8eb394.svn-base .svn/pristine/96/96d2cda457836fbee33580894c1a138879e9a89e.svn-base .svn/pristine/97/978f900709ed8de466a8e142aefeff25cb8293df.svn-base .svn/pristine/97/9797245a3a92458105708d0f347a48be95b75b9b.svn-base .svn/pristine/97/97bd979cf7f818b35efc479635225a7f42cd4140.svn-base .svn/pristine/97/97cf218fc7442945a6c4ade29d3288030034a7d6.svn-base .svn/pristine/97/97df7b6827e22c2665eace13dd5952db27af0ff3.svn-base .svn/pristine/98/9804b3e3abfd00a58dec9be4b531677efbf34d66.svn-base .svn/pristine/99/994c6e124b87f66f87d072585f0635b097da8f7b.svn-base .svn/pristine/99/997678775f2af1af27b63a8490e45d609905f797.svn-base .svn/pristine/9a/9a40b8d61a3b252d9bf2afe70d0ed928e7cbe617.svn-base .svn/pristine/9a/9acee3f273053af6824f9d963f851333a4619eb2.svn-base .svn/pristine/9b/9b3e5b07fcd5813f8a0dc3f62a18ba58010c1bee.svn-base .svn/pristine/9c/9ccedbf66a9f47b4ce6ada31cc7d30c26f464002.svn-base .svn/pristine/9f/9f118459c4368ff4d85087a360e2fc5dc451c4fe.svn-base .svn/pristine/9f/9f1ac231e02337e90b8fc44a90ad7c28bf25d85b.svn-base .svn/pristine/9f/9fd9de5370e8b7489081f79cbc0f65cb941662d5.svn-base .svn/pristine/a0/a004869c868a2f96a8bb7c88e2f423fbf74007bc.svn-base .svn/pristine/a0/a031ba3671a49b989b6b3f05b2432855669191cf.svn-base .svn/pristine/a1/a15efc0a7b7f938a7d937205168f8739fcc6338f.svn-base .svn/pristine/a1/a17e85541ced0de37f4c279c99198e91fbe8ecd9.svn-base .svn/pristine/a2/a228c3d0b7910e4eb07f95e583bb22e9efe2f4c4.svn-base .svn/pristine/a2/a22e306fd6141198284b162f707867ef8c8e9b27.svn-base .svn/pristine/a2/a287706354ad35bfd9b7a22dc5edd1bfb0f897d3.svn-base .svn/pristine/a3/a355ad47972838f60c489f8cf36f7b28781aa191.svn-base .svn/pristine/a3/a363794048b21aea80eb83bb41f65aa9764ee31a.svn-base .svn/pristine/a5/a5ff178355e2e2f0f7b0355d9d02e0157c346174.svn-base .svn/pristine/a6/a6c2d0d0b8c42346610cefc80f58028a31c51655.svn-base .svn/pristine/a9/a913b8238cb5eb5f60c33b311ea63769c5ce7d24.svn-base .svn/pristine/a9/a9efaf1639993585b08f796d4994f7cfff12bb4e.svn-base .svn/pristine/aa/aa4319d8f7d992a29eec92a78f6cd5cf0f5f274a.svn-base .svn/pristine/aa/aa4c68d001b78663e7227468cb64b231f259e013.svn-base .svn/pristine/ab/ab38ea7d768f054184e434cc851f97e51bbb639f.svn-base .svn/pristine/ab/ab6ce3c805128861a981af4815e85be081e803b8.svn-base .svn/pristine/ab/ab970c495cc7d5cb06380124a67cbb15101f1bd6.svn-base .svn/pristine/ab/abd5fdb1f4d3a8db5bc870f482b9f0ab10c084c0.svn-base .svn/pristine/ab/abf5211d324f321533d626e49b37b34c4b19ff77.svn-base .svn/pristine/ad/ad7d965438bf3955ae38f984cef50fc157bb3a13.svn-base .svn/pristine/ad/adfb2deb75a122f46087f28c026a73e83ce67dc5.svn-base .svn/pristine/ae/ae59ba764b863f990d0884c0c55bada9eb65b729.svn-base .svn/pristine/ae/aefa10621da29d1174e5f170d627124a0e405f4e.svn-base .svn/pristine/af/af02303e44f5e8e86d7123690a664101ce5a8f66.svn-base .svn/pristine/af/afff6ebb421c46aa468f585b7d8909132a409f4d.svn-base .svn/pristine/b1/b11a4104da3bd4ac01a0f204b3deb8706ff5132c.svn-base .svn/pristine/b3/b3d91192dd0d431ce304ba9c869d32014ebbfc38.svn-base .svn/pristine/b4/b4795ced5acceb3bc06993b762ac31de2976a1c3.svn-base .svn/pristine/b4/b4b121a602e6db678b41699ec2d4ceada140049b.svn-base .svn/pristine/b4/b4cfef9e8223bd39d2080e9087f88b2607c14914.svn-base .svn/pristine/b5/b5912509c719c19cefc865fb8a655b03174ed731.svn-base .svn/pristine/b5/b5d1f708535cf3262ade1830dcd9a0a3f72b68c4.svn-base .svn/pristine/b6/b60c09f950ca3bc2a75c168cc7ffe809b3b36299.svn-base .svn/pristine/b7/b7b9cbccc43c521f9ee2bd4c48abf815b2cf5508.svn-base .svn/pristine/b8/b8c4a4f62502265603b5dac16f30aca8838956d0.svn-base .svn/pristine/b9/b90cd149441f836cbc1e4f50f6a53eb280e646a6.svn-base .svn/pristine/b9/b94e9d09ba0ad12320000d9bdc7207a4e6a55736.svn-base .svn/pristine/ba/bac21e03aae70ae56858e7065d4f49d3a53cf7d7.svn-base .svn/pristine/ba/bad7988dc8d7b98fa49d927fe46638bead208bbb.svn-base .svn/pristine/bb/bb61dbaf687876f4655cd52d6481c38fded7a21c.svn-base .svn/pristine/bd/bd14f74ff8fe3ceb6d84b4dbead570fb4b8e960a.svn-base .svn/pristine/bd/bd8a41367104b158b51a98ef53d62e3672373a68.svn-base .svn/pristine/be/be8651657bb8574f8d5bb330df4828685014b41d.svn-base .svn/pristine/bf/bfe1171346960c651d4d5f6f55c3e48b3102dcc1.svn-base .svn/pristine/c1/c13203b8c9801034c2e99e8551c74a2c3c923252.svn-base .svn/pristine/c2/c2efec7daff7304595ce1ecc0edb5b5532a60347.svn-base .svn/pristine/c3/c33e922cc9977630c5c48bda98d379ff7df6c700.svn-base .svn/pristine/c3/c359a81860a9169febc935dc31d96675ccce6f95.svn-base .svn/pristine/c3/c380a8da5e4aab76f8d0af1d1700421b9d214474.svn-base .svn/pristine/c3/c38db3d2cd80cc99b93358b91a6eeac67c486c5e.svn-base .svn/pristine/c4/c4b9bd5f0c63e69e0dff5d428931d5aa53681958.svn-base .svn/pristine/c5/c52e05a6bbf465f32cbcf511ef2e13fc1ee99956.svn-base .svn/pristine/c5/c579e1089533be72e96be9f837601901aa22b4de.svn-base .svn/pristine/c5/c58d60a26982a819fdf9b2a65688b42aae5216fc.svn-base .svn/pristine/c6/c6b59a98475e92f48670b041ca8dfc5d4a6c1a5b.svn-base .svn/pristine/c6/c6bb92835cd944a70efc7f1fadbb496a3624fce7.svn-base .svn/pristine/c7/c71c2943a1e92bfbcb19b7e4592c3d8e1f7f80fd.svn-base .svn/pristine/c7/c776d4773c045c08108bca39e768c557cd3d3f3c.svn-base .svn/pristine/c7/c7cf137c2588796a3073e5736e9e052805b1bb66.svn-base .svn/pristine/c8/c8227a12426582a67a866b9030d95a66b9f407a6.svn-base .svn/pristine/c8/c8c8b891b8b1a98cd7dec3eea46d3351c5d63dc0.svn-base .svn/pristine/c8/c8eb9218e8a7b1005bc9738485c7283ea65cf881.svn-base .svn/pristine/c9/c94378ba0f927a1812044bbae32975e1c8d9db8b.svn-base .svn/pristine/c9/c95a845f51d0458457322e070bfabbc6737ef1a1.svn-base .svn/pristine/c9/c9e7983f17ebbef596f0d988a11845f2f8e0840f.svn-base .svn/pristine/ca/ca2690f201462335a7ca37a385b267b1298dce63.svn-base .svn/pristine/ca/ca5fec371cca9a83b040c882b835088a92221cb9.svn-base .svn/pristine/cb/cbbbbf51cf00f3931cd57d857e449b95b77320ca.svn-base .svn/pristine/cd/cd13f3dd427937eb092253330df74831980a985d.svn-base .svn/pristine/cf/cf88629896a4d2bfd151981d52eb19dc48c7487b.svn-base .svn/pristine/cf/cf95716aca909d9dc04cf88a70448176a0b10143.svn-base .svn/pristine/cf/cf99c613decbc54df4a99c63e23764d371ea8fbc.svn-base .svn/pristine/cf/cfa38091d70dac5ed0710a8ebb3ecb812073f2f5.svn-base .svn/pristine/d0/d009627e726f03a1c296b163bb2546a76eb0de0f.svn-base .svn/pristine/d0/d06e7cefb510a385899794a94c740218a4fb9cd9.svn-base .svn/pristine/d0/d0bea3c38e05e7624a7186faf67962c248869550.svn-base .svn/pristine/d0/d0ce7856bd86e4cf6960ce56a6e054a535f90e1e.svn-base .svn/pristine/d1/d102e2042fa5903bbabfc16fdf04c8a155faa793.svn-base .svn/pristine/d1/d16034fcce26ab77343a09774e57112c6aad2670.svn-base .svn/pristine/d3/d33d3be542af530a2b59368ea55c980fec7e5ab9.svn-base .svn/pristine/d3/d36525152d9efe5f33a9df496757a5193831f75b.svn-base .svn/pristine/d5/d50fa731af4ebca2aab740b7c23ce3cd606c5836.svn-base .svn/pristine/d5/d56bb30205e35d46995a303698017ed24f7ce040.svn-base .svn/pristine/d5/d5c99af330410b19fab22c939293b2b8a8b960e8.svn-base .svn/pristine/d6/d6dba1cf7d52d25c0fa5bfc624e064b5ba2087ba.svn-base .svn/pristine/d7/d70fd8a8adbbd6e7c06cc19c2775e3cc0289e1f1.svn-base .svn/pristine/d7/d7610ec8c096fad5d592071757d4c3415e6a2e6a.svn-base .svn/pristine/d7/d7993eab0e03bf713eaae4e70ad89bacc08a8657.svn-base .svn/pristine/d8/d8da15b6a8a2fb05e57342be295616d42903caef.svn-base .svn/pristine/d9/d9247e732a56dd9b3466a2d481b475b595b379f2.svn-base .svn/pristine/d9/d98764f99d236520bd5f6ca42381f61878a79847.svn-base .svn/pristine/d9/d9ae3cb5600a5eb2525edf835bf114f2fc4ccc54.svn-base .svn/pristine/da/da12c9756273b44fbd8170e245294f84a463055c.svn-base .svn/pristine/da/da391cc28994d066c2bbb55ae6f4853a48f37175.svn-base .svn/pristine/da/dabffc2fc4a60cc2c87340311e04fc75053c2695.svn-base .svn/pristine/da/dad3a3fd832f92aba5ee807842c8f128fb126df0.svn-base .svn/pristine/db/db3e656f6a1b8b9454d5de84d641938d6207efc9.svn-base .svn/pristine/db/dbc74bfb5d695fe0fd5ec63c1a42442c480292e2.svn-base .svn/pristine/dc/dc4a8b889fb60778bdec8c2aea4b6206a1ffbc41.svn-base .svn/pristine/dc/dcf80e81fd95a42105f66a0a6dd9f6b600306b78.svn-base .svn/pristine/dd/dd03dd82c04080c4766fa34cc74013a6e6a961c3.svn-base .svn/pristine/dd/dd4d40b7c92af3319303c89259cc7a21a900ab6b.svn-base .svn/pristine/dd/dd9453d0bf7ef7086f723475ae286725a241d719.svn-base .svn/pristine/de/de33a6eb951226489a34da09937a4a47913b07fb.svn-base .svn/pristine/df/df9bbf954b4f906004aaa967b48274754ad6dcd0.svn-base .svn/pristine/df/dfa4eb7ba7d6caceff9151c99aedb512ffa84738.svn-base .svn/pristine/e0/e0146f52672bac410fabc231692b8f39edc8e101.svn-base .svn/pristine/e0/e08b9f438981155ffc0c3a70e9b878dc891b06d2.svn-base .svn/pristine/e0/e09af230a1244dd904e00eb402f9ad5ad77a9fd1.svn-base .svn/pristine/e1/e14ce008ab63fe1ed2c0583cdc8dd554192dcfe1.svn-base .svn/pristine/e1/e170cc478b88d5ba7f1f49c3d7b9996c36309faf.svn-base .svn/pristine/e1/e18719fcaad4f02ac25c73385c2559b70312719c.svn-base .svn/pristine/e2/e20c66ea78669a9f640a596d6292e35c469be33c.svn-base .svn/pristine/e3/e3ea2cb6450687eb1d61c512debbaf9478178a88.svn-base .svn/pristine/e4/e4897735528df3f63a14478e29488229fe020925.svn-base .svn/pristine/e4/e4ed3df6bca9bcd2f1e4eae777c4852f4adf1c6c.svn-base .svn/pristine/e5/e57e448ff5e398f985d2656f35e0c4f0db003780.svn-base .svn/pristine/e5/e58ec86b245f3ac57a759399f47d3d6b2bb03a42.svn-base .svn/pristine/e5/e5e737cf1acef41f150245d1f3e14b3ec1313b84.svn-base .svn/pristine/e6/e69e1b12c742c2fed3eb747a9348573816cd63d1.svn-base .svn/pristine/e7/e782c41b495cdac1921cd58d5fd63f6ce30f9f15.svn-base .svn/pristine/e8/e8aa327e67355ce663b09a685e02ede1d8c6edd6.svn-base .svn/pristine/e8/e8f5719ac8290bf42290de6a5ad4ab322d08803d.svn-base .svn/pristine/e9/e9895d42866e8fe662252fd7f421c7dd0505d9a5.svn-base .svn/pristine/ea/ea992c47f8d2112ec52008294e35e2cd3e7c1b5f.svn-base .svn/pristine/ea/eab1cd7b12156ed469f5471880818f7528dfed63.svn-base .svn/pristine/eb/eb6cb0f6889f62dec8dd9c85a7fb5ed905af22c8.svn-base .svn/pristine/ec/ec7c0d826b7228b3557fac4fa00ebff6a515cfda.svn-base .svn/pristine/ec/ecefbcb550b756f6256573a28f797d89d864d36f.svn-base .svn/pristine/ec/ecf9241c1e6ccd1ccee3ece4b5568fb173ad0940.svn-base .svn/pristine/ed/edfff204737c4c393e698de5497cb166b80631df.svn-base .svn/pristine/ef/ef01ace269b8f950664d9b52e99400c8a56e9cdf.svn-base .svn/pristine/f0/f0263c221f5ea74d2c30c55c3240a08d7cddc2f4.svn-base .svn/pristine/f0/f0fa25d2662f25ee7e3a4a54f9fb5b50422d6b41.svn-base .svn/pristine/f1/f11f6b57f7e2388c7777d4dc34576404ddd5230b.svn-base .svn/pristine/f1/f1cdf29a721cc514cb39f1d1983090024969bffe.svn-base .svn/pristine/f1/f1e462b67d8967f5d1fe2af96802c244faffb89d.svn-base .svn/pristine/f2/f2015be9c3b679bedb2c24e4bc1e2d51751badea.svn-base .svn/pristine/f2/f2726ad84a3873a4a39cbceb7b5b654ff347068a.svn-base .svn/pristine/f3/f3202e275b36fcaa2493cbc5897c69215e65214b.svn-base .svn/pristine/f3/f3937f219362099cca8dc63d36f1da6d0e5c4f05.svn-base .svn/pristine/f4/f43305298989567d96f5b7cd3fec323aa70a3dd0.svn-base .svn/pristine/f4/f45cadd45e22c8df0a53045d3c2f398d9f064ea9.svn-base .svn/pristine/f4/f4bd9cf8c7227a2836ae6369246ebcb1a93c4265.svn-base .svn/pristine/f4/f4f821cd00b02aca16ddb8be972d9bda8452365e.svn-base .svn/pristine/f5/f57965ef8e80be257ec5fce2399cf84a7480d6c4.svn-base .svn/pristine/f5/f57cb4b2fd4e8b282707982829017761e21ff080.svn-base .svn/pristine/f5/f593ea5869b339d3716433b9f9c8cbcd53fdd758.svn-base .svn/pristine/f6/f60338f68ffe02f90e6ab9b5d825ff71b8197897.svn-base .svn/pristine/f6/f6ef1fd188a246198832677eccb65f1bec39a729.svn-base .svn/pristine/f7/f75cc0973adb64fe86bec853f1ce941fdd75f24d.svn-base .svn/pristine/f7/f78ddc144c31f10580290509649e50dda2f4e570.svn-base .svn/pristine/f8/f846004b3958b5cdd097fb7a9fa2ca8d32fef589.svn-base .svn/pristine/f8/f868e11e49aa1ebab883f07d048bd42ffcb7e3b1.svn-base .svn/pristine/f8/f8e3393c3af527d599685daf189e7b5311a95a64.svn-base .svn/pristine/f9/f992af412d2338b0910671c99f9c86c6772cdf7c.svn-base .svn/pristine/fa/faa06e26aeea9f7627ae814543492f9d35051460.svn-base .svn/pristine/fa/fab553c0a3c9a998f2e8320cf6ed96e7fb3e898d.svn-base .svn/pristine/fa/fae6aa29a415564c269ced790046953485df6633.svn-base .svn/pristine/fb/fb0370610c36e942e95f18248151b66c8bb1d28d.svn-base .svn/pristine/fc/fc770db4db5a22614ed5ce3040fd496687aca860.svn-base .svn/pristine/fc/fc954db436a100775650d80a4eca7f8ba87c8867.svn-base .svn/pristine/fd/fde74b3b9d30225e1a58fe5d703e35242b069eea.svn-base .svn/pristine/fe/fe48a02cf4f3380a268baa6d0b7204b03f3af240.svn-base .svn/pristine/fe/fe616c1a4677a1989f6035ef3d43e4954fce98ea.svn-base .svn/pristine/fe/fe7d0011c363388fa41294d974753444295841f2.svn-base .svn/pristine/ff/ff099fd1cfab1c76b1d3707b9f9509ca80e11c2a.svn-base .svn/pristine/ff/ff1c47ab3a4a85cdc878d408e530d4ba3db0f578.svn-base .svn/pristine/ff/ffd51ba3b4736e466b3394ff29f5bd178dfb6f31.svn-base Gemfile app/controllers/application_controller.rb app/views/attachments/_form.html.erb
diffstat 523 files changed, 5444 insertions(+), 92285 deletions(-) [+]
line wrap: on
line diff
--- a/.svn/pristine/00/0009a621965fc195e93ba67a7d3500cbcd38b084.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class DocumentsController < ApplicationController
-  default_search_scope :documents
-  model_object Document
-  before_filter :find_project_by_project_id, :only => [:index, :new, :create]
-  before_filter :find_model_object, :except => [:index, :new, :create]
-  before_filter :find_project_from_association, :except => [:index, :new, :create]
-  before_filter :authorize
-
-  helper :attachments
-
-  def index
-    @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
-    documents = @project.documents.includes(:attachments, :category).all
-    case @sort_by
-    when 'date'
-      @grouped = documents.group_by {|d| d.updated_on.to_date }
-    when 'title'
-      @grouped = documents.group_by {|d| d.title.first.upcase}
-    when 'author'
-      @grouped = documents.select{|d| d.attachments.any?}.group_by {|d| d.attachments.last.author}
-    else
-      @grouped = documents.group_by(&:category)
-    end
-    @document = @project.documents.build
-    render :layout => false if request.xhr?
-  end
-
-  def show
-    @attachments = @document.attachments.all
-  end
-
-  def new
-    @document = @project.documents.build
-    @document.safe_attributes = params[:document]
-  end
-
-  def create
-    @document = @project.documents.build
-    @document.safe_attributes = params[:document]
-    @document.save_attachments(params[:attachments])
-    if @document.save
-      render_attachment_warning_if_needed(@document)
-      flash[:notice] = l(:notice_successful_create)
-      redirect_to project_documents_path(@project)
-    else
-      render :action => 'new'
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    @document.safe_attributes = params[:document]
-    if request.put? and @document.save
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to document_path(@document)
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def destroy
-    @document.destroy if request.delete?
-    redirect_to project_documents_path(@project)
-  end
-
-  def add_attachment
-    attachments = Attachment.attach_files(@document, params[:attachments])
-    render_attachment_warning_if_needed(@document)
-
-    if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added')
-      Mailer.attachments_added(attachments[:files]).deliver
-    end
-    redirect_to document_path(@document)
-  end
-end
--- a/.svn/pristine/01/019777b51c435b18c756e5573fde25c903195b68.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-require 'rexml/document'
-
-module Redmine
-  module VERSION #:nodoc:
-    MAJOR = 2
-    MINOR = 4
-    TINY  = 2
-
-    # Branch values:
-    # * official release: nil
-    # * stable branch:    stable
-    # * trunk:            devel
-    BRANCH = 'stable'
-
-    # Retrieves the revision from the working copy
-    def self.revision
-      if File.directory?(File.join(Rails.root, '.svn'))
-        begin
-          path = Redmine::Scm::Adapters::AbstractAdapter.shell_quote(Rails.root.to_s)
-          if `svn info --xml #{path}` =~ /revision="(\d+)"/
-            return $1.to_i
-          end
-        rescue
-          # Could not find the current revision
-        end
-      end
-      nil
-    end
-
-    REVISION = self.revision
-    ARRAY    = [MAJOR, MINOR, TINY, BRANCH, REVISION].compact
-    STRING   = ARRAY.join('.')
-
-    def self.to_a; ARRAY  end
-    def self.to_s; STRING end
-  end
-end
--- a/.svn/pristine/01/01b21d04c9e912327dc0059ef282ceb1a603f54f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AutoCompletesControllerTest < ActionController::TestCase
-  fixtures :projects, :issues, :issue_statuses,
-           :enumerations, :users, :issue_categories,
-           :trackers,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :journals, :journal_details
-
-  def test_issues_should_not_be_case_sensitive
-    get :issues, :project_id => 'ecookbook', :q => 'ReCiPe'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert assigns(:issues).detect {|issue| issue.subject.match /recipe/}
-  end
-
-  def test_issues_should_accept_term_param
-    get :issues, :project_id => 'ecookbook', :term => 'ReCiPe'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert assigns(:issues).detect {|issue| issue.subject.match /recipe/}
-  end
-
-  def test_issues_should_return_issue_with_given_id
-    get :issues, :project_id => 'subproject1', :q => '13'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert assigns(:issues).include?(Issue.find(13))
-  end
-
-  def test_issues_should_return_issue_with_given_id_preceded_with_hash
-    get :issues, :project_id => 'subproject1', :q => '#13'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert assigns(:issues).include?(Issue.find(13))
-  end
-
-  def test_auto_complete_with_scope_all_should_search_other_projects
-    get :issues, :project_id => 'ecookbook', :q => '13', :scope => 'all'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert assigns(:issues).include?(Issue.find(13))
-  end
-
-  def test_auto_complete_without_project_should_search_all_projects
-    get :issues, :q => '13'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert assigns(:issues).include?(Issue.find(13))
-  end
-
-  def test_auto_complete_without_scope_all_should_not_search_other_projects
-    get :issues, :project_id => 'ecookbook', :q => '13'
-    assert_response :success
-    assert_equal [], assigns(:issues)
-  end
-
-  def test_issues_should_return_json
-    get :issues, :project_id => 'subproject1', :q => '13'
-    assert_response :success
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Array, json
-    issue = json.first
-    assert_kind_of Hash, issue
-    assert_equal 13, issue['id']
-    assert_equal 13, issue['value']
-    assert_equal 'Bug #13: Subproject issue two', issue['label']
-  end
-end
--- a/.svn/pristine/01/01cfbfdc38592dff3cbe5b1b36118aa0e1e65223.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class GanttsControllerTest < ActionController::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :versions
-
-  def test_gantt_should_work
-    i2 = Issue.find(2)
-    i2.update_attribute(:due_date, 1.month.from_now)
-    get :show, :project_id => 1
-    assert_response :success
-    assert_template 'gantts/show'
-    assert_not_nil assigns(:gantt)
-    # Issue with start and due dates
-    i = Issue.find(1)
-    assert_not_nil i.due_date
-    assert_select "div a.issue", /##{i.id}/
-    # Issue with on a targeted version should not be in the events but loaded in the html
-    i = Issue.find(2)
-    assert_select "div a.issue", /##{i.id}/
-  end
-
-  def test_gantt_should_work_without_issue_due_dates
-    Issue.update_all("due_date = NULL")
-    get :show, :project_id => 1
-    assert_response :success
-    assert_template 'gantts/show'
-    assert_not_nil assigns(:gantt)
-  end
-
-  def test_gantt_should_work_without_issue_and_version_due_dates
-    Issue.update_all("due_date = NULL")
-    Version.update_all("effective_date = NULL")
-    get :show, :project_id => 1
-    assert_response :success
-    assert_template 'gantts/show'
-    assert_not_nil assigns(:gantt)
-  end
-
-  def test_gantt_should_work_cross_project
-    get :show
-    assert_response :success
-    assert_template 'gantts/show'
-    assert_not_nil assigns(:gantt)
-    assert_not_nil assigns(:gantt).query
-    assert_nil assigns(:gantt).project
-  end
-
-  def test_gantt_should_not_disclose_private_projects
-    get :show
-    assert_response :success
-    assert_template 'gantts/show'
-    assert_tag 'a', :content => /eCookbook/
-    # Root private project
-    assert_no_tag 'a', {:content => /OnlineStore/}
-    # Private children of a public project
-    assert_no_tag 'a', :content => /Private child of eCookbook/
-  end
-
-  def test_gantt_should_display_relations
-    IssueRelation.delete_all
-    issue1 = Issue.generate!(:start_date => 1.day.from_now.to_date, :due_date => 3.day.from_now.to_date)
-    issue2 = Issue.generate!(:start_date => 1.day.from_now.to_date, :due_date => 3.day.from_now.to_date)
-    IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => 'precedes')
-
-    get :show
-    assert_response :success
-
-    relations = assigns(:gantt).relations
-    assert_kind_of Hash, relations
-    assert relations.present?
-    assert_select 'div.task_todo[id=?][data-rels*=?]', "task-todo-issue-#{issue1.id}", issue2.id.to_s
-    assert_select 'div.task_todo[id=?]:not([data-rels])', "task-todo-issue-#{issue2.id}"
-  end
-
-  def test_gantt_should_export_to_pdf
-    get :show, :project_id => 1, :format => 'pdf'
-    assert_response :success
-    assert_equal 'application/pdf', @response.content_type
-    assert @response.body.starts_with?('%PDF')
-    assert_not_nil assigns(:gantt)
-  end
-
-  def test_gantt_should_export_to_pdf_cross_project
-    get :show, :format => 'pdf'
-    assert_response :success
-    assert_equal 'application/pdf', @response.content_type
-    assert @response.body.starts_with?('%PDF')
-    assert_not_nil assigns(:gantt)
-  end
-
-  if Object.const_defined?(:Magick)
-    def test_gantt_should_export_to_png
-      get :show, :project_id => 1, :format => 'png'
-      assert_response :success
-      assert_equal 'image/png', @response.content_type
-    end
-  end
-end
--- a/.svn/pristine/02/027410b40ae4e2d4f4be0368cf13b4cdb0164b5f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RoleTest < ActiveSupport::TestCase
-  fixtures :roles, :workflows, :trackers
-
-  def test_sorted_scope
-    assert_equal Role.all.sort, Role.sorted.all
-  end
-
-  def test_givable_scope
-    assert_equal Role.all.reject(&:builtin?).sort, Role.givable.all
-  end
-
-  def test_builtin_scope
-    assert_equal Role.all.select(&:builtin?).sort, Role.builtin(true).all.sort
-    assert_equal Role.all.reject(&:builtin?).sort, Role.builtin(false).all.sort
-  end
-
-  def test_copy_from
-    role = Role.find(1)
-    copy = Role.new.copy_from(role)
-
-    assert_nil copy.id
-    assert_equal '', copy.name
-    assert_equal role.permissions, copy.permissions
-
-    copy.name = 'Copy'
-    assert copy.save
-  end
-
-  def test_copy_workflows
-    source = Role.find(1)
-    assert_equal 90, source.workflow_rules.size
-
-    target = Role.new(:name => 'Target')
-    assert target.save
-    target.workflow_rules.copy(source)
-    target.reload
-    assert_equal 90, target.workflow_rules.size
-  end
-
-  def test_permissions_should_be_unserialized_with_its_coder
-    Role::PermissionsAttributeCoder.expects(:load).once
-    Role.find(1).permissions
-  end
-
-  def test_add_permission
-    role = Role.find(1)
-    size = role.permissions.size
-    role.add_permission!("apermission", "anotherpermission")
-    role.reload
-    assert role.permissions.include?(:anotherpermission)
-    assert_equal size + 2, role.permissions.size
-  end
-
-  def test_remove_permission
-    role = Role.find(1)
-    size = role.permissions.size
-    perm = role.permissions[0..1]
-    role.remove_permission!(*perm)
-    role.reload
-    assert ! role.permissions.include?(perm[0])
-    assert_equal size - 2, role.permissions.size
-  end
-
-  def test_name
-    I18n.locale = 'fr'
-    assert_equal 'Manager', Role.find(1).name
-    assert_equal 'Anonyme', Role.anonymous.name
-    assert_equal 'Non membre', Role.non_member.name
-  end
-
-  def test_find_all_givable
-    assert_equal Role.all.reject(&:builtin?).sort, Role.find_all_givable
-  end
-
-  def test_anonymous_should_return_the_anonymous_role
-    assert_no_difference('Role.count') do
-      role = Role.anonymous
-      assert role.builtin?
-      assert_equal Role::BUILTIN_ANONYMOUS, role.builtin
-    end
-  end
-
-  def test_anonymous_with_a_missing_anonymous_role_should_return_the_anonymous_role
-    Role.where(:builtin => Role::BUILTIN_ANONYMOUS).delete_all
-
-    assert_difference('Role.count') do
-      role = Role.anonymous
-      assert role.builtin?
-      assert_equal Role::BUILTIN_ANONYMOUS, role.builtin
-    end
-  end
-
-  def test_non_member_should_return_the_non_member_role
-    assert_no_difference('Role.count') do
-      role = Role.non_member
-      assert role.builtin?
-      assert_equal Role::BUILTIN_NON_MEMBER, role.builtin
-    end
-  end
-
-  def test_non_member_with_a_missing_non_member_role_should_return_the_non_member_role
-    Role.where(:builtin => Role::BUILTIN_NON_MEMBER).delete_all
-
-    assert_difference('Role.count') do
-      role = Role.non_member
-      assert role.builtin?
-      assert_equal Role::BUILTIN_NON_MEMBER, role.builtin
-    end
-  end
-end
--- a/.svn/pristine/02/02fe391dd14e50d29ad45f8bf8dea30be02556c5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Themes
-
-    # Return an array of installed themes
-    def self.themes
-      @@installed_themes ||= scan_themes
-    end
-
-    # Rescan themes directory
-    def self.rescan
-      @@installed_themes = scan_themes
-    end
-
-    # Return theme for given id, or nil if it's not found
-    def self.theme(id, options={})
-      return nil if id.blank?
-
-      found = themes.find {|t| t.id == id}
-      if found.nil? && options[:rescan] != false
-        rescan
-        found = theme(id, :rescan => false)
-      end
-      found
-    end
-
-    # Class used to represent a theme
-    class Theme
-      attr_reader :path, :name, :dir
-
-      def initialize(path)
-        @path = path
-        @dir = File.basename(path)
-        @name = @dir.humanize
-        @stylesheets = nil
-        @javascripts = nil
-      end
-
-      # Directory name used as the theme id
-      def id; dir end
-
-      def ==(theme)
-        theme.is_a?(Theme) && theme.dir == dir
-      end
-
-      def <=>(theme)
-        name <=> theme.name
-      end
-
-      def stylesheets
-        @stylesheets ||= assets("stylesheets", "css")
-      end
-
-      def images
-        @images ||= assets("images")
-      end
-
-      def javascripts
-        @javascripts ||= assets("javascripts", "js")
-      end
-
-      def stylesheet_path(source)
-        "/themes/#{dir}/stylesheets/#{source}"
-      end
-
-      def image_path(source)
-        "/themes/#{dir}/images/#{source}"
-      end
-
-      def javascript_path(source)
-        "/themes/#{dir}/javascripts/#{source}"
-      end
-
-      private
-
-      def assets(dir, ext=nil)
-        if ext
-          Dir.glob("#{path}/#{dir}/*.#{ext}").collect {|f| File.basename(f).gsub(/\.#{ext}$/, '')}
-        else
-          Dir.glob("#{path}/#{dir}/*").collect {|f| File.basename(f)}
-        end
-      end
-    end
-
-    private
-
-    def self.scan_themes
-      dirs = Dir.glob("#{Rails.public_path}/themes/*").select do |f|
-        # A theme should at least override application.css
-        File.directory?(f) && File.exist?("#{f}/stylesheets/application.css")
-      end
-      dirs.collect {|dir| Theme.new(dir)}.sort
-    end
-  end
-end
-
-module ApplicationHelper
-  def current_theme
-    unless instance_variable_defined?(:@current_theme)
-      @current_theme = Redmine::Themes.theme(Setting.ui_theme)
-    end
-    @current_theme
-  end
-
-  # Returns the header tags for the current theme
-  def heads_for_theme
-    if current_theme && current_theme.javascripts.include?('theme')
-      javascript_include_tag current_theme.javascript_path('theme')
-    end
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/03/0335a712dd5fb2c44f8cb6daaf182ac72aee4c7f.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,287 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<title>RedmineWikiFormatting</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<style type="text/css">
+    body { font:80% Verdana,Tahoma,Arial,sans-serif; }
+    h1, h2, h3, h4 {  font-family: Trebuchet MS,Georgia,"Times New Roman",serif; }
+    pre, code { font-size:120%; }
+    pre code { font-size:100%; }
+    pre {
+        margin: 1em 1em 1em 1.6em;
+        padding: 2px;
+        background-color: #fafafa;
+        border: 1px solid #dadada;
+        width:95%;
+        overflow-x: auto;
+    }
+    a.new { color: #b73535; }
+
+    .syntaxhl .line-numbers { padding: 2px 4px 2px 4px; background-color: #eee; margin:0 }
+    .syntaxhl .comment  { color:#666; }
+
+    .syntaxhl .class { color:#B06; font-weight:bold }
+    .syntaxhl .delimiter { color:black }
+    .syntaxhl .function { color:#06B; font-weight:bold }
+
+    .syntaxhl .inline { background: #eee }
+    .syntaxhl .inline .inline-delimiter { font-weight: bold; color: #888 }
+
+    .syntaxhl .instance-variable { color:#33B }
+    .syntaxhl .reserved { color:#080; font-weight:bold }
+
+    .syntaxhl .string { background-color:#fff0f0; color: #D20; }
+    .syntaxhl .string .delimiter { color:#710 }
+
+</style>
+</head>
+
+<body>
+<h1><a name="1" class="wiki-page"></a>Wiki 格式設定</h1>
+
+    <h2><a name="2" class="wiki-page"></a>連結</h2>
+
+        <h3><a name="3" class="wiki-page"></a>Redmine 連結</h3>
+
+        <p>在任何可以使用 Wiki 格式設定的地方, Redmine 都允許在資源(問題、變更集、 Wiki 頁面...)間建立超連結。</p>
+        <ul>
+            <li>連結至一個問題: <strong>#124</strong> (若該問題已經結束,則使用刪除線顯示連結: <del><a href="#" class="issue" title="bulk edit doesn't change the category or fixed version properties (Closed)">#124</a></del>)</li>
+            <li>連結至一個問題的筆記: <strong>#124-6</strong>, or <strong>#124#note-6</strong></li>
+        </ul>
+
+        <p>Wiki 連結:</p>
+
+        <ul>
+            <li><strong>[[Guide]]</strong> 顯示一個頁面名稱為 'Guide' 的連結: <a href="#" class="wiki-page">Guide</a></li>
+            <li><strong>[[Guide#further-reading]]</strong> 會連結至一個 "further-reading" 的 HTML 錨定 (anchor) 。每個標題文字都會被自動指定一個 HTML 錨定,以便您可以用來連結它們: <a href="#" class="wiki-page">Guide</a></li>
+            <li><strong>[[Guide|User manual]]</strong> 使用不同的文字來顯示一個頁面名稱為 'Guide' 的連結: <a href="#" class="wiki-page">User manual</a></li>
+        </ul>
+
+        <p>您也可以連結至其他專案的 Wiki 頁面:</p>
+
+        <ul>
+            <li><strong>[[sandbox:some page]]</strong> 顯示一個 Sanbox wiki 中頁面名稱為 'Some page' 的連結</li>
+            <li><strong>[[sandbox:]]</strong> 顯示 Sandbox wiki 首頁頁面的連結</li>
+        </ul>
+
+        <p>當頁面不存在的時候, Wiki 連結會以紅色的方式顯示,例如: <a href="#" class="wiki-page new">Nonexistent page</a>.</p>
+
+        <p>連結至其他資源:</p>
+
+        <ul>
+            <li>文件:
+                <ul>
+                    <li><strong>document#17</strong> (連結到編號為 17 的文件)</li>
+                    <li><strong>document:Greetings</strong> (連結至文件標題為 "Greetings" 的文件)</li>
+                    <li><strong>document:"Some document"</strong> (文件標題包含空白字元時可以使用雙引號來標示)</li>
+                    <li><strong>sandbox:document:"Some document"</strong> (連結至另外一個 "sandbox" 專案中,文件標題為 "Some document" 的文件)</li>
+                </ul></li>
+        </ul>
+
+        <ul>
+            <li>版本:
+                <ul>
+                    <li><strong>version#3</strong> (連結至編號為 3 的版本)</li>
+                    <li><strong>version:1.0.0</strong> (連結至名稱為 "1.0.0" 的版本)</li>
+                    <li><strong>version:"1.0 beta 2"</strong> (版本名稱包含空白字元時可以使用雙引號來標示)</li>
+                    <li><strong>sandbox:version:1.0.0</strong> (連結至 "sandbox" 專案中,名稱為 "1.0.0" 的版本)</li>
+                </ul></li>
+        </ul>
+
+        <ul>
+            <li>附加檔案:
+                <ul>
+                    <li><strong>attachment:file.zip</strong> (連結至目前物件中,名稱為 file.zip 的附加檔案)</li>
+                    <li>目前僅提供參考到目前物件中的附加檔案 (若您正位於一個問題中,僅可參考位於此問題中之附加檔案)</li>
+                </ul></li>
+        </ul>
+
+        <ul>
+            <li>變更集:
+                <ul>
+                    <li><strong>r758</strong>                       (連結至一個變更集)</li>
+                    <li><strong>commit:c6f4d0fd</strong>            (連結至一個使用非數字雜湊的變更集)</li>
+                    <li><strong>svn1|r758</strong>                  (連結至指定儲存機制中之變更集,用於專案使用多個儲存機制時之情況)</li>
+                    <li><strong>commit:hg|c6f4d0fd</strong>         (連結至指定儲存機制中,使用非數字雜湊的變更集)</li>
+                    <li><strong>sandbox:r758</strong>               (連結至其他專案的變更集)</li>
+                    <li><strong>sandbox:commit:c6f4d0fd</strong>    (連結至其他專案中,使用非數字雜湊的變更集)</li>
+                </ul></li>
+        </ul>
+
+        <ul>
+             <li>儲存機制中之檔案:
+                <ul>
+                    <li><strong>source:some/file</strong>           (連結至專案儲存機制中,位於 /some/file 的檔案)</li>
+                    <li><strong>source:some/file@52</strong>        (連結至此檔案的 52 版次)</li>
+                    <li><strong>source:some/file#L120</strong>      (連結至此檔案的第 120 行)</li>
+                    <li><strong>source:some/file@52#L120</strong>   (連結至此檔案的 52 版刺中之第 120 行)</li>
+                    <li><strong>source:"some file@52#L120"</strong> (當 URL 中包含空白字元時,使用雙引號來標示)</li>
+                    <li><strong>export:some/file</strong>           (強制下載此檔案)</li>
+                    <li><strong>source:svn1|some/file</strong>      (連結至指定儲存機制中的此檔案,用於專案使用多個儲存機制時之情況)</li>
+                    <li><strong>sandbox:source:some/file</strong>   (連結至 "sandbox" 專案的儲存機制中,位於 /some/file 的檔案)</li>
+                    <li><strong>sandbox:export:some/file</strong>   (強迫下載該檔案)</li>
+                </ul></li>
+        </ul>
+
+        <ul>
+            <li>論壇訊息:
+                <ul>
+                    <li><strong>message#1218</strong> (連結至編號 1218 的訊息)</li>
+                </ul></li>
+        </ul>
+
+        <ul>
+            <li>專案:
+                <ul>
+                    <li><strong>project#3</strong> (連結至編號為 3 的專案)</li>
+                    <li><strong>project:someproject</strong> (連結至名稱為 "someproject" 的專案)</li>
+                </ul></li>
+        </ul>
+
+
+        <p>逸出字元:</p>
+
+        <ul>
+            <li>您可以在文字的前面加上驚嘆號 (!) 來避免該文字被剖析成 Redmine 連結</li>
+        </ul>
+
+
+        <h3><a name="4" class="wiki-page"></a>外部連結</h3>
+
+        <p>HTTP URLs 與電子郵件地址會自動被轉換成可被點擊的連結:</p>
+
+<pre>
+http://www.redmine.org, someone@foo.bar
+</pre>
+
+        <p>顯示為: <a class="external" href="http://www.redmine.org">http://www.redmine.org</a>, <a href="mailto:someone@foo.bar" class="email">someone@foo.bar</a></p>
+
+        <p>若您想要顯示指定的文字而非該 URL ,您可以使用下列標準的 textile 語法:</p>
+
+<pre>
+"Redmine web site":http://www.redmine.org
+</pre>
+
+        <p>顯示為: <a href="http://www.redmine.org" class="external">Redmine web site</a></p>
+
+
+    <h2><a name="5" class="wiki-page"></a>文字格式設定</h2>
+
+
+    <p>對於諸如標題、粗體、表格、清單等項目, Redmine 支援使用 Textile 語法。可參考 <a class="external" href="http://en.wikipedia.org/wiki/Textile_%28markup_language%29">http://en.wikipedia.org/wiki/Textile_(markup_language)</a> 中關於使用這些格式化功能的說明資訊。 下面包含了一些使用範例,但格式化引擎的處理能力遠多於這些簡單的使用範例。</p>
+
+        <h3><a name="6" class="wiki-page"></a>字型樣式</h3>
+
+<pre>
+* *粗體*
+* _斜體_
+* _*粗斜體*_
+* +底線+
+* -刪除線-
+</pre>
+
+        <p>顯示為:</p>
+
+        <ul>
+            <li><strong>粗體</strong></li>
+            <li><em>斜體</em></li>
+            <li><em><strong>粗斜體</strong></em></li>
+            <li><ins>底線</ins></li>
+            <li><del>刪除線</del></li>
+        </ul>
+
+        <h3><a name="7" class="wiki-page"></a>內置圖像</h3>
+
+        <ul>
+            <li><strong>!圖像_url!</strong> 顯示一個位於 圖像_url 位址的圖像(textile 語法)</li>
+            <li><strong>!&gt;image_url!</strong> 右側浮動圖像</li>
+            <li>若您附加了一個圖像到 Wiki 頁面中,可以使用他的檔案名稱來顯示成內置圖像: <strong>!attached_image.png!</strong></li>
+        </ul>
+
+        <h3><a name="8" class="wiki-page"></a>標題</h3>
+
+<pre>
+h1. 標題
+h2. 次標題
+h3. 次次標題
+</pre>
+
+        <p>Redmine 為每一種標題指定一個 HTML 錨定 (anchor) ,因此您可使用 "#Heading" 、 "#Subheading" 等方式連結至這些標題。</p>
+
+
+        <h3><a name="9" class="wiki-page"></a>段落</h3>
+
+<pre>
+p&gt;. 靠右對齊
+p=. 置中對齊
+</pre>
+
+        <p style="text-align:center;">這是一個置中對齊的段落。</p>
+
+
+        <h3><a name="10" class="wiki-page"></a>引用文字</h3>
+
+        <p>使用 <strong>bq.</strong> 開始一個引文的段落</p>
+
+<pre>
+bq. Rails is a full-stack framework for developing database-backed web applications according to the Model-View-Control pattern.
+To go live, all you need to add is a database and a web server.
+</pre>
+
+        <p>顯示為:</p>
+
+        <blockquote>
+                <p>Rails is a full-stack framework for developing database-backed web applications according to the Model-View-Control pattern.<br />To go live, all you need to add is a database and a web server.</p>
+        </blockquote>
+
+
+        <h3><a name="11" class="wiki-page"></a>目錄</h3>
+
+<pre>
+{{toc}} =&gt; 靠左對齊目錄
+{{&gt;toc}} =&gt; 靠右對齊目錄
+</pre>
+
+        <h3><a name="14" class="wiki-page"></a>水平線</h3>
+
+<pre>
+---
+</pre>
+
+    <h2><a name="12" class="wiki-page"></a>巨集</h2>
+
+    <p>Redmine 內建下列巨集:</p>
+
+    <p><dl><dt><code>hello_world</code></dt><dd><p>範例巨集。</p></dd><dt><code>include</code></dt><dd><p>引入一個 wiki 頁面。例子:</p>
+
+    <pre><code>{{include(Foo)}}</code></pre></dd><dt><code>macro_list</code></dt><dd><p>顯示所有可用巨集的清單,若巨集有提供說明也會一併顯示。</p></dd></dl></p>
+
+
+    <h2><a name="13" class="wiki-page"></a>程式碼醒目提示</h2>
+
+    <p>預設使用 <a href="http://coderay.rubychan.de/" class="external">CodeRay</a> 作為程式碼醒目提示的機制,它是一個使用 Ruby 撰寫的語法醒目提示函式庫。它目前支援 c 、 cpp 、 css 、 delphi 、 groovy 、 html 、 java 、 javascript 、 json 、 php 、 python 、 rhtml 、 ruby 、 scheme 、 sql 、 xml 與 yaml 等程式語言。</p>
+
+    <p>您可以使用下列語法,在 Wiki 頁面中將程式碼標示為醒目提示:</p>
+
+<pre>
+&lt;pre&gt;&lt;code class="ruby"&gt;
+  將程式碼放在這裡。
+&lt;/code&gt;&lt;/pre&gt;
+</pre>
+
+    <p>例子:</p>
+
+<pre><code class="ruby syntaxhl"><span class="line-numbers"> 1</span> <span class="comment"># The Greeter class</span>
+<span class="line-numbers"> 2</span> <span class="reserved">class</span> <span class="class">Greeter</span>
+<span class="line-numbers"> 3</span>   <span class="reserved">def</span> <span class="function">initialize</span>(name)
+<span class="line-numbers"> 4</span>     <span class="instance-variable">@name</span> = name.capitalize
+<span class="line-numbers"> 5</span>   <span class="reserved">end</span>
+<span class="line-numbers"> 6</span>
+<span class="line-numbers"> 7</span>   <span class="reserved">def</span> <span class="function">salute</span>
+<span class="line-numbers"> 8</span>     puts <span class="string"><span class="delimiter">"</span><span class="content">Hello </span><span class="inline"><span class="inline-delimiter">#{</span><span class="instance-variable">@name</span><span class="inline-delimiter">}</span></span><span class="content">!</span><span class="delimiter">"</span></span>
+<span class="line-numbers"> 9</span>   <span class="reserved">end</span>
+<span class="line-numbers"><strong>10</strong></span> <span class="reserved">end</span></code>
+</pre>
+</body>
+</html>
--- a/.svn/pristine/03/033d1080f94d03c5b655f6847c2f7606bd5d5f60.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module UsersHelper
-  def users_status_options_for_select(selected)
-    user_count_by_status = User.count(:group => 'status').to_hash
-    options_for_select([[l(:label_all), ''],
-                        ["#{l(:status_active)} (#{user_count_by_status[1].to_i})", '1'],
-                        ["#{l(:status_registered)} (#{user_count_by_status[2].to_i})", '2'],
-                        ["#{l(:status_locked)} (#{user_count_by_status[3].to_i})", '3']], selected.to_s)
-  end
-
-  def user_mail_notification_options(user)
-    user.valid_notification_options.collect {|o| [l(o.last), o.first]}
-  end
-
-  def change_status_link(user)
-    url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil}
-
-    if user.locked?
-      link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock'
-    elsif user.registered?
-      link_to l(:button_activate), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock'
-    elsif user != User.current
-      link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :put, :class => 'icon icon-lock'
-    end
-  end
-
-  def user_settings_tabs
-    tabs = [{:name => 'general', :partial => 'users/general', :label => :label_general},
-            {:name => 'memberships', :partial => 'users/memberships', :label => :label_project_plural}
-            ]
-    if Group.all.any?
-      tabs.insert 1, {:name => 'groups', :partial => 'users/groups', :label => :label_group_plural}
-    end
-    tabs
-  end
-end
--- a/.svn/pristine/04/0490719dc3185896fb07e210967a75c0f5e40a0a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueTransactionTest < ActiveSupport::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles,
-           :trackers, :projects_trackers,
-           :versions,
-           :issue_statuses, :issue_categories, :issue_relations, :workflows,
-           :enumerations,
-           :issues,
-           :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
-           :time_entries
-
-  self.use_transactional_fixtures = false
-
-  def test_invalid_move_to_another_project
-    parent1 = Issue.generate!
-    child =   Issue.generate!(:parent_issue_id => parent1.id)
-    grandchild = Issue.generate!(:parent_issue_id => child.id, :tracker_id => 2)
-    Project.find(2).tracker_ids = [1]
-
-    parent1.reload
-    assert_equal [1, parent1.id, 1, 6], [parent1.project_id, parent1.root_id, parent1.lft, parent1.rgt]
-
-    # child can not be moved to Project 2 because its child is on a disabled tracker
-    child = Issue.find(child.id)
-    child.project = Project.find(2)
-    assert !child.save
-    child.reload
-    grandchild.reload
-    parent1.reload
-
-    # no change
-    assert_equal [1, parent1.id, 1, 6], [parent1.project_id, parent1.root_id, parent1.lft, parent1.rgt]
-    assert_equal [1, parent1.id, 2, 5], [child.project_id, child.root_id, child.lft, child.rgt]
-    assert_equal [1, parent1.id, 3, 4], [grandchild.project_id, grandchild.root_id, grandchild.lft, grandchild.rgt]
-  end
-end
--- a/.svn/pristine/04/049234b460fae5eb30eba8a2487d0eac09c6701f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-namespace :redmine do
-  namespace :email do
-
-    desc <<-END_DESC
-Read an email from standard input.
-
-General options:
-  unknown_user=ACTION      how to handle emails from an unknown user
-                           ACTION can be one of the following values:
-                           ignore: email is ignored (default)
-                           accept: accept as anonymous user
-                           create: create a user account
-  no_permission_check=1    disable permission checking when receiving
-                           the email
-  no_account_notice=1      disable new user account notification
-  default_group=foo,bar    adds created user to foo and bar groups
-
-Issue attributes control options:
-  project=PROJECT          identifier of the target project
-  status=STATUS            name of the target status
-  tracker=TRACKER          name of the target tracker
-  category=CATEGORY        name of the target category
-  priority=PRIORITY        name of the target priority
-  allow_override=ATTRS     allow email content to override attributes
-                           specified by previous options
-                           ATTRS is a comma separated list of attributes
-
-Examples:
-  # No project specified. Emails MUST contain the 'Project' keyword:
-  rake redmine:email:read RAILS_ENV="production" < raw_email
-
-  # Fixed project and default tracker specified, but emails can override
-  # both tracker and priority attributes:
-  rake redmine:email:read RAILS_ENV="production" \\
-                  project=foo \\
-                  tracker=bug \\
-                  allow_override=tracker,priority < raw_email
-END_DESC
-
-    task :read => :environment do
-      MailHandler.receive(STDIN.read, MailHandler.extract_options_from_env(ENV))
-    end
-
-    desc <<-END_DESC
-Read emails from an IMAP server.
-
-General options:
-  unknown_user=ACTION      how to handle emails from an unknown user
-                           ACTION can be one of the following values:
-                           ignore: email is ignored (default)
-                           accept: accept as anonymous user
-                           create: create a user account
-  no_permission_check=1    disable permission checking when receiving
-                           the email
-  no_account_notice=1      disable new user account notification
-  default_group=foo,bar    adds created user to foo and bar groups
-
-Available IMAP options:
-  host=HOST                IMAP server host (default: 127.0.0.1)
-  port=PORT                IMAP server port (default: 143)
-  ssl=SSL                  Use SSL? (default: false)
-  username=USERNAME        IMAP account
-  password=PASSWORD        IMAP password
-  folder=FOLDER            IMAP folder to read (default: INBOX)
-
-Issue attributes control options:
-  project=PROJECT          identifier of the target project
-  status=STATUS            name of the target status
-  tracker=TRACKER          name of the target tracker
-  category=CATEGORY        name of the target category
-  priority=PRIORITY        name of the target priority
-  allow_override=ATTRS     allow email content to override attributes
-                           specified by previous options
-                           ATTRS is a comma separated list of attributes
-
-Processed emails control options:
-  move_on_success=MAILBOX  move emails that were successfully received
-                           to MAILBOX instead of deleting them
-  move_on_failure=MAILBOX  move emails that were ignored to MAILBOX
-
-Examples:
-  # No project specified. Emails MUST contain the 'Project' keyword:
-
-  rake redmine:email:receive_imap RAILS_ENV="production" \\
-    host=imap.foo.bar username=redmine@example.net password=xxx
-
-
-  # Fixed project and default tracker specified, but emails can override
-  # both tracker and priority attributes:
-
-  rake redmine:email:receive_imap RAILS_ENV="production" \\
-    host=imap.foo.bar username=redmine@example.net password=xxx ssl=1 \\
-    project=foo \\
-    tracker=bug \\
-    allow_override=tracker,priority
-END_DESC
-
-    task :receive_imap => :environment do
-      imap_options = {:host => ENV['host'],
-                      :port => ENV['port'],
-                      :ssl => ENV['ssl'],
-                      :username => ENV['username'],
-                      :password => ENV['password'],
-                      :folder => ENV['folder'],
-                      :move_on_success => ENV['move_on_success'],
-                      :move_on_failure => ENV['move_on_failure']}
-
-      Redmine::IMAP.check(imap_options, MailHandler.extract_options_from_env(ENV))
-    end
-
-    desc <<-END_DESC
-Read emails from an POP3 server.
-
-Available POP3 options:
-  host=HOST                POP3 server host (default: 127.0.0.1)
-  port=PORT                POP3 server port (default: 110)
-  username=USERNAME        POP3 account
-  password=PASSWORD        POP3 password
-  apop=1                   use APOP authentication (default: false)
-  delete_unprocessed=1     delete messages that could not be processed
-                           successfully from the server (default
-                           behaviour is to leave them on the server)
-
-See redmine:email:receive_imap for more options and examples.
-END_DESC
-
-    task :receive_pop3 => :environment do
-      pop_options  = {:host => ENV['host'],
-                      :port => ENV['port'],
-                      :apop => ENV['apop'],
-                      :username => ENV['username'],
-                      :password => ENV['password'],
-                      :delete_unprocessed => ENV['delete_unprocessed']}
-
-      Redmine::POP3.check(pop_options, MailHandler.extract_options_from_env(ENV))
-    end
-
-    desc "Send a test email to the user with the provided login name"
-    task :test, [:login] => :environment do |task, args|
-      include Redmine::I18n
-      abort l(:notice_email_error, "Please include the user login to test with. Example: rake redmine:email:test[login]") if args[:login].blank?
-
-      user = User.find_by_login(args[:login])
-      abort l(:notice_email_error, "User #{args[:login]} not found") unless user && user.logged?
-
-      ActionMailer::Base.raise_delivery_errors = true
-      begin
-        Mailer.with_synched_deliveries do
-          Mailer.test_email(user).deliver
-        end
-        puts l(:notice_email_sent, user.mail)
-      rescue Exception => e
-        abort l(:notice_email_error, e.message)
-      end
-    end
-  end
-end
--- a/.svn/pristine/05/05d8cde4a4e9772f7dcbafb481eff20153ca4409.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module MimeType
-
-    MIME_TYPES = {
-      'text/plain' => 'txt,tpl,properties,patch,diff,ini,readme,install,upgrade',
-      'text/css' => 'css',
-      'text/html' => 'html,htm,xhtml',
-      'text/jsp' => 'jsp',
-      'text/x-c' => 'c,cpp,cc,h,hh',
-      'text/x-csharp' => 'cs',
-      'text/x-java' => 'java',
-      'text/x-html-template' => 'rhtml',
-      'text/x-perl' => 'pl,pm',
-      'text/x-php' => 'php,php3,php4,php5',
-      'text/x-python' => 'py',
-      'text/x-ruby' => 'rb,rbw,ruby,rake,erb',
-      'text/x-csh' => 'csh',
-      'text/x-sh' => 'sh',
-      'text/xml' => 'xml,xsd,mxml',
-      'text/yaml' => 'yml,yaml',
-      'text/csv' => 'csv',
-      'text/x-po' => 'po',
-      'image/gif' => 'gif',
-      'image/jpeg' => 'jpg,jpeg,jpe',
-      'image/png' => 'png',
-      'image/tiff' => 'tiff,tif',
-      'image/x-ms-bmp' => 'bmp',
-      'image/x-xpixmap' => 'xpm',
-      'image/svg+xml'=> 'svg',
-      'application/javascript' => 'js',
-      'application/pdf' => 'pdf',
-      'application/rtf' => 'rtf',
-      'application/msword' => 'doc',
-      'application/vnd.ms-excel' => 'xls',
-      'application/vnd.ms-powerpoint' => 'ppt,pps',
-      'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
-      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
-      'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
-      'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
-      'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
-      'application/vnd.oasis.opendocument.text' => 'odt',
-      'application/vnd.oasis.opendocument.presentation' => 'odp',
-      'application/x-7z-compressed' => '7z',
-      'application/x-rar-compressed' => 'rar',
-      'application/x-tar' => 'tar',
-      'application/zip' => 'zip',
-      'application/x-gzip' => 'gz',
-    }.freeze
-
-    EXTENSIONS = MIME_TYPES.inject({}) do |map, (type, exts)|
-      exts.split(',').each {|ext| map[ext.strip] = type}
-      map
-    end
-
-    # returns mime type for name or nil if unknown
-    def self.of(name)
-      return nil unless name
-      m = name.to_s.match(/(^|\.)([^\.]+)$/)
-      EXTENSIONS[m[2].downcase] if m
-    end
-
-    # Returns the css class associated to
-    # the mime type of name
-    def self.css_class_of(name)
-      mime = of(name)
-      mime && mime.gsub('/', '-')
-    end
-
-    def self.main_mimetype_of(name)
-      mimetype = of(name)
-      mimetype.split('/').first if mimetype
-    end
-
-    # return true if mime-type for name is type/*
-    # otherwise false
-    def self.is_type?(type, name)
-      main_mimetype = main_mimetype_of(name)
-      type.to_s == main_mimetype
-    end
-  end
-end
--- a/.svn/pristine/05/05fb4e3ebed828cf639f80e5d1d6da6095d43000.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class ProjectEnumerationsController < ApplicationController
-  before_filter :find_project_by_project_id
-  before_filter :authorize
-
-  def update
-    if request.put? && params[:enumerations]
-      Project.transaction do
-        params[:enumerations].each do |id, activity|
-          @project.update_or_create_time_entry_activity(id, activity)
-        end
-      end
-      flash[:notice] = l(:notice_successful_update)
-    end
-
-    redirect_to settings_project_path(@project, :tab => 'activities')
-  end
-
-  def destroy
-    @project.time_entry_activities.each do |time_entry_activity|
-      time_entry_activity.destroy(time_entry_activity.parent)
-    end
-    flash[:notice] = l(:notice_successful_update)
-    redirect_to settings_project_path(@project, :tab => 'activities')
-  end
-end
--- a/.svn/pristine/06/06906d5d51f832720062a81972796df1a81f69a3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AdminControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :roles
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 1 # admin
-  end
-
-  def test_index
-    get :index
-    assert_select 'div.nodata', 0
-  end
-
-  def test_index_with_no_configuration_data
-    delete_configuration_data
-    get :index
-    assert_select 'div.nodata'
-  end
-
-  def test_projects
-    get :projects
-    assert_response :success
-    assert_template 'projects'
-    assert_not_nil assigns(:projects)
-    # active projects only
-    assert_nil assigns(:projects).detect {|u| !u.active?}
-  end
-
-  def test_projects_with_status_filter
-    get :projects, :status => 1
-    assert_response :success
-    assert_template 'projects'
-    assert_not_nil assigns(:projects)
-    # active projects only
-    assert_nil assigns(:projects).detect {|u| !u.active?}
-  end
-
-  def test_projects_with_name_filter
-    get :projects, :name => 'store', :status => ''
-    assert_response :success
-    assert_template 'projects'
-    projects = assigns(:projects)
-    assert_not_nil projects
-    assert_equal 1, projects.size
-    assert_equal 'OnlineStore', projects.first.name
-  end
-
-  def test_load_default_configuration_data
-    delete_configuration_data
-    post :default_configuration, :lang => 'fr'
-    assert_response :redirect
-    assert_nil flash[:error]
-    assert IssueStatus.find_by_name('Nouveau')
-  end
-
-  def test_load_default_configuration_data_should_rescue_error
-    delete_configuration_data
-    Redmine::DefaultData::Loader.stubs(:load).raises(Exception.new("Something went wrong"))
-    post :default_configuration, :lang => 'fr'
-    assert_response :redirect
-    assert_not_nil flash[:error]
-    assert_match /Something went wrong/, flash[:error]
-  end
-
-  def test_test_email
-    user = User.find(1)
-    user.pref.no_self_notified = '1'
-    user.pref.save!
-    ActionMailer::Base.deliveries.clear
-
-    get :test_email
-    assert_redirected_to '/settings?tab=notifications'
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    user = User.find(1)
-    assert_equal [user.mail], mail.bcc
-  end
-
-  def test_test_email_failure_should_display_the_error
-    Mailer.stubs(:test_email).raises(Exception, 'Some error message')
-    get :test_email
-    assert_redirected_to '/settings?tab=notifications'
-    assert_match /Some error message/, flash[:error]
-  end
-
-  def test_no_plugins
-    Redmine::Plugin.clear
-
-    get :plugins
-    assert_response :success
-    assert_template 'plugins'
-  end
-
-  def test_plugins
-    # Register a few plugins
-    Redmine::Plugin.register :foo do
-      name 'Foo plugin'
-      author 'John Smith'
-      description 'This is a test plugin'
-      version '0.0.1'
-      settings :default => {'sample_setting' => 'value', 'foo'=>'bar'}, :partial => 'foo/settings'
-    end
-    Redmine::Plugin.register :bar do
-    end
-
-    get :plugins
-    assert_response :success
-    assert_template 'plugins'
-
-    assert_select 'tr#plugin-foo' do
-      assert_select 'td span.name', :text => 'Foo plugin'
-      assert_select 'td.configure a[href=/settings/plugin/foo]'
-    end
-    assert_select 'tr#plugin-bar' do
-      assert_select 'td span.name', :text => 'Bar'
-      assert_select 'td.configure a', 0
-    end
-  end
-
-  def test_info
-    get :info
-    assert_response :success
-    assert_template 'info'
-  end
-
-  def test_admin_menu_plugin_extension
-    Redmine::MenuManager.map :admin_menu do |menu|
-      menu.push :test_admin_menu_plugin_extension, '/foo/bar', :caption => 'Test'
-    end
-
-    get :index
-    assert_response :success
-    assert_select 'div#admin-menu a[href=/foo/bar]', :text => 'Test'
-
-    Redmine::MenuManager.map :admin_menu do |menu|
-      menu.delete :test_admin_menu_plugin_extension
-    end
-  end
-
-  private
-
-  def delete_configuration_data
-    Role.delete_all('builtin = 0')
-    Tracker.delete_all
-    IssueStatus.delete_all
-    Enumeration.delete_all
-  end
-end
--- a/.svn/pristine/06/06927559eed548b89dcc19d7fe7d3d26046b88c1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,428 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module IssuesHelper
-  include ApplicationHelper
-
-  def issue_list(issues, &block)
-    ancestors = []
-    issues.each do |issue|
-      while (ancestors.any? && !issue.is_descendant_of?(ancestors.last))
-        ancestors.pop
-      end
-      yield issue, ancestors.size
-      ancestors << issue unless issue.leaf?
-    end
-  end
-
-  # Renders a HTML/CSS tooltip
-  #
-  # To use, a trigger div is needed.  This is a div with the class of "tooltip"
-  # that contains this method wrapped in a span with the class of "tip"
-  #
-  #    <div class="tooltip"><%= link_to_issue(issue) %>
-  #      <span class="tip"><%= render_issue_tooltip(issue) %></span>
-  #    </div>
-  #
-  def render_issue_tooltip(issue)
-    @cached_label_status ||= l(:field_status)
-    @cached_label_start_date ||= l(:field_start_date)
-    @cached_label_due_date ||= l(:field_due_date)
-    @cached_label_assigned_to ||= l(:field_assigned_to)
-    @cached_label_priority ||= l(:field_priority)
-    @cached_label_project ||= l(:field_project)
-
-    link_to_issue(issue) + "<br /><br />".html_safe +
-      "<strong>#{@cached_label_project}</strong>: #{link_to_project(issue.project)}<br />".html_safe +
-      "<strong>#{@cached_label_status}</strong>: #{h(issue.status.name)}<br />".html_safe +
-      "<strong>#{@cached_label_start_date}</strong>: #{format_date(issue.start_date)}<br />".html_safe +
-      "<strong>#{@cached_label_due_date}</strong>: #{format_date(issue.due_date)}<br />".html_safe +
-      "<strong>#{@cached_label_assigned_to}</strong>: #{h(issue.assigned_to)}<br />".html_safe +
-      "<strong>#{@cached_label_priority}</strong>: #{h(issue.priority.name)}".html_safe
-  end
-
-  def issue_heading(issue)
-    h("#{issue.tracker} ##{issue.id}")
-  end
-
-  def render_issue_subject_with_tree(issue)
-    s = ''
-    ancestors = issue.root? ? [] : issue.ancestors.visible.all
-    ancestors.each do |ancestor|
-      s << '<div>' + content_tag('p', link_to_issue(ancestor, :project => (issue.project_id != ancestor.project_id)))
-    end
-    s << '<div>'
-    subject = h(issue.subject)
-    if issue.is_private?
-      subject = content_tag('span', l(:field_is_private), :class => 'private') + ' ' + subject
-    end
-    s << content_tag('h3', subject)
-    s << '</div>' * (ancestors.size + 1)
-    s.html_safe
-  end
-
-  def render_descendants_tree(issue)
-    s = '<form><table class="list issues">'
-    issue_list(issue.descendants.visible.sort_by(&:lft)) do |child, level|
-      css = "issue issue-#{child.id} hascontextmenu"
-      css << " idnt idnt-#{level}" if level > 0
-      s << content_tag('tr',
-             content_tag('td', check_box_tag("ids[]", child.id, false, :id => nil), :class => 'checkbox') +
-             content_tag('td', link_to_issue(child, :truncate => 60, :project => (issue.project_id != child.project_id)), :class => 'subject') +
-             content_tag('td', h(child.status)) +
-             content_tag('td', link_to_user(child.assigned_to)) +
-             content_tag('td', progress_bar(child.done_ratio, :width => '80px')),
-             :class => css)
-    end
-    s << '</table></form>'
-    s.html_safe
-  end
-
-  # Returns an array of error messages for bulk edited issues
-  def bulk_edit_error_messages(issues)
-    messages = {}
-    issues.each do |issue|
-      issue.errors.full_messages.each do |message|
-        messages[message] ||= []
-        messages[message] << issue
-      end
-    end
-    messages.map { |message, issues|
-      "#{message}: " + issues.map {|i| "##{i.id}"}.join(', ')
-    }
- end
-
-  # Returns a link for adding a new subtask to the given issue
-  def link_to_new_subtask(issue)
-    attrs = {
-      :tracker_id => issue.tracker,
-      :parent_issue_id => issue
-    }
-    link_to(l(:button_add), new_project_issue_path(issue.project, :issue => attrs))
-  end
-
-  class IssueFieldsRows
-    include ActionView::Helpers::TagHelper
-
-    def initialize
-      @left = []
-      @right = []
-    end
-
-    def left(*args)
-      args.any? ? @left << cells(*args) : @left
-    end
-
-    def right(*args)
-      args.any? ? @right << cells(*args) : @right
-    end
-
-    def size
-      @left.size > @right.size ? @left.size : @right.size
-    end
-
-    def to_html
-      html = ''.html_safe
-      blank = content_tag('th', '') + content_tag('td', '')
-      size.times do |i|
-        left = @left[i] || blank
-        right = @right[i] || blank
-        html << content_tag('tr', left + right)
-      end
-      html
-    end
-
-    def cells(label, text, options={})
-      content_tag('th', "#{label}:", options) + content_tag('td', text, options)
-    end
-  end
-
-  def issue_fields_rows
-    r = IssueFieldsRows.new
-    yield r
-    r.to_html
-  end
-
-  def render_custom_fields_rows(issue)
-    values = issue.visible_custom_field_values
-    return if values.empty?
-    ordered_values = []
-    half = (values.size / 2.0).ceil
-    half.times do |i|
-      ordered_values << values[i]
-      ordered_values << values[i + half]
-    end
-    s = "<tr>\n"
-    n = 0
-    ordered_values.compact.each do |value|
-      s << "</tr>\n<tr>\n" if n > 0 && (n % 2) == 0
-      s << "\t<th>#{ h(value.custom_field.name) }:</th><td>#{ simple_format_without_paragraph(h(show_value(value))) }</td>\n"
-      n += 1
-    end
-    s << "</tr>\n"
-    s.html_safe
-  end
-
-  def issues_destroy_confirmation_message(issues)
-    issues = [issues] unless issues.is_a?(Array)
-    message = l(:text_issues_destroy_confirmation)
-    descendant_count = issues.inject(0) {|memo, i| memo += (i.right - i.left - 1)/2}
-    if descendant_count > 0
-      issues.each do |issue|
-        next if issue.root?
-        issues.each do |other_issue|
-          descendant_count -= 1 if issue.is_descendant_of?(other_issue)
-        end
-      end
-      if descendant_count > 0
-        message << "\n" + l(:text_issues_destroy_descendants_confirmation, :count => descendant_count)
-      end
-    end
-    message
-  end
-
-  def sidebar_queries
-    unless @sidebar_queries
-      @sidebar_queries = IssueQuery.visible.
-        order("#{Query.table_name}.name ASC").
-        # Project specific queries and global queries
-        where(@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id]).
-        all
-    end
-    @sidebar_queries
-  end
-
-  def query_links(title, queries)
-    return '' if queries.empty?
-    # links to #index on issues/show
-    url_params = controller_name == 'issues' ? {:controller => 'issues', :action => 'index', :project_id => @project} : params
-
-    content_tag('h3', title) + "\n" +
-      content_tag('ul',
-        queries.collect {|query|
-            css = 'query'
-            css << ' selected' if query == @query
-            content_tag('li', link_to(query.name, url_params.merge(:query_id => query), :class => css))
-          }.join("\n").html_safe,
-        :class => 'queries'
-      ) + "\n"
-  end
-
-  def render_sidebar_queries
-    out = ''.html_safe
-    out << query_links(l(:label_my_queries), sidebar_queries.select(&:is_private?))
-    out << query_links(l(:label_query_plural), sidebar_queries.reject(&:is_private?))
-    out
-  end
-
-  def email_issue_attributes(issue, user)
-    items = []
-    %w(author status priority assigned_to category fixed_version).each do |attribute|
-      unless issue.disabled_core_fields.include?(attribute+"_id")
-        items << "#{l("field_#{attribute}")}: #{issue.send attribute}"
-      end
-    end
-    issue.visible_custom_field_values(user).each do |value|
-      items << "#{value.custom_field.name}: #{show_value(value)}"
-    end
-    items
-  end
-
-  def render_email_issue_attributes(issue, user, html=false)
-    items = email_issue_attributes(issue, user)
-    if html
-      content_tag('ul', items.map{|s| content_tag('li', s)}.join("\n").html_safe)
-    else
-      items.map{|s| "* #{s}"}.join("\n")
-    end
-  end
-
-  # Returns the textual representation of a journal details
-  # as an array of strings
-  def details_to_strings(details, no_html=false, options={})
-    options[:only_path] = (options[:only_path] == false ? false : true)
-    strings = []
-    values_by_field = {}
-    details.each do |detail|
-      if detail.property == 'cf'
-        field = detail.custom_field
-        if field && field.multiple?
-          values_by_field[field] ||= {:added => [], :deleted => []}
-          if detail.old_value
-            values_by_field[field][:deleted] << detail.old_value
-          end
-          if detail.value
-            values_by_field[field][:added] << detail.value
-          end
-          next
-        end
-      end
-      strings << show_detail(detail, no_html, options)
-    end
-    values_by_field.each do |field, changes|
-      detail = JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s)
-      detail.instance_variable_set "@custom_field", field
-      if changes[:added].any?
-        detail.value = changes[:added]
-        strings << show_detail(detail, no_html, options)
-      elsif changes[:deleted].any?
-        detail.old_value = changes[:deleted]
-        strings << show_detail(detail, no_html, options)
-      end
-    end
-    strings
-  end
-
-  # Returns the textual representation of a single journal detail
-  def show_detail(detail, no_html=false, options={})
-    multiple = false
-    case detail.property
-    when 'attr'
-      field = detail.prop_key.to_s.gsub(/\_id$/, "")
-      label = l(("field_" + field).to_sym)
-      case detail.prop_key
-      when 'due_date', 'start_date'
-        value = format_date(detail.value.to_date) if detail.value
-        old_value = format_date(detail.old_value.to_date) if detail.old_value
-
-      when 'project_id', 'status_id', 'tracker_id', 'assigned_to_id',
-            'priority_id', 'category_id', 'fixed_version_id'
-        value = find_name_by_reflection(field, detail.value)
-        old_value = find_name_by_reflection(field, detail.old_value)
-
-      when 'estimated_hours'
-        value = "%0.02f" % detail.value.to_f unless detail.value.blank?
-        old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
-
-      when 'parent_id'
-        label = l(:field_parent_issue)
-        value = "##{detail.value}" unless detail.value.blank?
-        old_value = "##{detail.old_value}" unless detail.old_value.blank?
-
-      when 'is_private'
-        value = l(detail.value == "0" ? :general_text_No : :general_text_Yes) unless detail.value.blank?
-        old_value = l(detail.old_value == "0" ? :general_text_No : :general_text_Yes) unless detail.old_value.blank?
-      end
-    when 'cf'
-      custom_field = detail.custom_field
-      if custom_field
-        multiple = custom_field.multiple?
-        label = custom_field.name
-        value = format_value(detail.value, custom_field.field_format) if detail.value
-        old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value
-      end
-    when 'attachment'
-      label = l(:label_attachment)
-    when 'relation'
-      if detail.value && !detail.old_value
-        rel_issue = Issue.visible.find_by_id(detail.value)
-        value = rel_issue.nil? ? "#{l(:label_issue)} ##{detail.value}" :
-                  (no_html ? rel_issue : link_to_issue(rel_issue, :only_path => options[:only_path]))
-      elsif detail.old_value && !detail.value
-        rel_issue = Issue.visible.find_by_id(detail.old_value)
-        old_value = rel_issue.nil? ? "#{l(:label_issue)} ##{detail.old_value}" :
-                          (no_html ? rel_issue : link_to_issue(rel_issue, :only_path => options[:only_path]))
-      end
-      label = l(detail.prop_key.to_sym)
-    end
-    call_hook(:helper_issues_show_detail_after_setting,
-              {:detail => detail, :label => label, :value => value, :old_value => old_value })
-
-    label ||= detail.prop_key
-    value ||= detail.value
-    old_value ||= detail.old_value
-
-    unless no_html
-      label = content_tag('strong', label)
-      old_value = content_tag("i", h(old_value)) if detail.old_value
-      if detail.old_value && detail.value.blank? && detail.property != 'relation'
-        old_value = content_tag("del", old_value)
-      end
-      if detail.property == 'attachment' && !value.blank? && atta = Attachment.find_by_id(detail.prop_key)
-        # Link to the attachment if it has not been removed
-        value = link_to_attachment(atta, :download => true, :only_path => options[:only_path])
-        if options[:only_path] != false && atta.is_text?
-          value += link_to(
-                       image_tag('magnifier.png'),
-                       :controller => 'attachments', :action => 'show',
-                       :id => atta, :filename => atta.filename
-                     )
-        end
-      else
-        value = content_tag("i", h(value)) if value
-      end
-    end
-
-    if detail.property == 'attr' && detail.prop_key == 'description'
-      s = l(:text_journal_changed_no_detail, :label => label)
-      unless no_html
-        diff_link = link_to 'diff',
-          {:controller => 'journals', :action => 'diff', :id => detail.journal_id,
-           :detail_id => detail.id, :only_path => options[:only_path]},
-          :title => l(:label_view_diff)
-        s << " (#{ diff_link })"
-      end
-      s.html_safe
-    elsif detail.value.present?
-      case detail.property
-      when 'attr', 'cf'
-        if detail.old_value.present?
-          l(:text_journal_changed, :label => label, :old => old_value, :new => value).html_safe
-        elsif multiple
-          l(:text_journal_added, :label => label, :value => value).html_safe
-        else
-          l(:text_journal_set_to, :label => label, :value => value).html_safe
-        end
-      when 'attachment', 'relation'
-        l(:text_journal_added, :label => label, :value => value).html_safe
-      end
-    else
-      l(:text_journal_deleted, :label => label, :old => old_value).html_safe
-    end
-  end
-
-  # Find the name of an associated record stored in the field attribute
-  def find_name_by_reflection(field, id)
-    unless id.present?
-      return nil
-    end
-    association = Issue.reflect_on_association(field.to_sym)
-    if association
-      record = association.class_name.constantize.find_by_id(id)
-      if record
-        record.name.force_encoding('UTF-8') if record.name.respond_to?(:force_encoding)
-        return record.name
-      end
-    end
-  end
-
-  # Renders issue children recursively
-  def render_api_issue_children(issue, api)
-    return if issue.leaf?
-    api.array :children do
-      issue.children.each do |child|
-        api.issue(:id => child.id) do
-          api.tracker(:id => child.tracker_id, :name => child.tracker.name) unless child.tracker.nil?
-          api.subject child.subject
-          render_api_issue_children(child, api)
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/06/06efa9c81bf4ffa47e3211023e46fcb09d4eac0f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RolesControllerTest < ActionController::TestCase
-  fixtures :roles, :users, :members, :member_roles, :workflows, :trackers
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 1 # admin
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-
-    assert_not_nil assigns(:roles)
-    assert_equal Role.order('builtin, position').all, assigns(:roles)
-
-    assert_tag :tag => 'a', :attributes => { :href => '/roles/1/edit' },
-                            :content => 'Manager'
-  end
-
-  def test_new
-    get :new
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_new_with_copy
-    copy_from = Role.find(2)
-
-    get :new, :copy => copy_from.id.to_s
-    assert_response :success
-    assert_template 'new'
-
-    role = assigns(:role)
-    assert_equal copy_from.permissions, role.permissions
-
-    assert_select 'form' do
-      # blank name
-      assert_select 'input[name=?][value=]', 'role[name]'
-      # edit_project permission checked
-      assert_select 'input[type=checkbox][name=?][value=edit_project][checked=checked]', 'role[permissions][]'
-      # add_project permission not checked
-      assert_select 'input[type=checkbox][name=?][value=add_project]', 'role[permissions][]'
-      assert_select 'input[type=checkbox][name=?][value=add_project][checked=checked]', 'role[permissions][]', 0
-      # workflow copy selected
-      assert_select 'select[name=?]', 'copy_workflow_from' do
-        assert_select 'option[value=2][selected=selected]'
-      end
-    end
-  end
-
-  def test_create_with_validaton_failure
-    post :create, :role => {:name => '',
-                         :permissions => ['add_issues', 'edit_issues', 'log_time', ''],
-                         :assignable => '0'}
-
-    assert_response :success
-    assert_template 'new'
-    assert_tag :tag => 'div', :attributes => { :id => 'errorExplanation' }
-  end
-
-  def test_create_without_workflow_copy
-    post :create, :role => {:name => 'RoleWithoutWorkflowCopy',
-                         :permissions => ['add_issues', 'edit_issues', 'log_time', ''],
-                         :assignable => '0'}
-
-    assert_redirected_to '/roles'
-    role = Role.find_by_name('RoleWithoutWorkflowCopy')
-    assert_not_nil role
-    assert_equal [:add_issues, :edit_issues, :log_time], role.permissions
-    assert !role.assignable?
-  end
-
-  def test_create_with_workflow_copy
-    post :create, :role => {:name => 'RoleWithWorkflowCopy',
-                         :permissions => ['add_issues', 'edit_issues', 'log_time', ''],
-                         :assignable => '0'},
-               :copy_workflow_from => '1'
-
-    assert_redirected_to '/roles'
-    role = Role.find_by_name('RoleWithWorkflowCopy')
-    assert_not_nil role
-    assert_equal Role.find(1).workflow_rules.size, role.workflow_rules.size
-  end
-
-  def test_edit
-    get :edit, :id => 1
-    assert_response :success
-    assert_template 'edit'
-    assert_equal Role.find(1), assigns(:role)
-    assert_select 'select[name=?]', 'role[issues_visibility]'
-  end
-
-  def test_edit_anonymous
-    get :edit, :id => Role.anonymous.id
-    assert_response :success
-    assert_template 'edit'
-    assert_select 'select[name=?]', 'role[issues_visibility]', 0
-  end
-
-  def test_edit_invalid_should_respond_with_404
-    get :edit, :id => 999
-    assert_response 404
-  end
-
-  def test_update
-    put :update, :id => 1,
-                :role => {:name => 'Manager',
-                          :permissions => ['edit_project', ''],
-                          :assignable => '0'}
-
-    assert_redirected_to '/roles'
-    role = Role.find(1)
-    assert_equal [:edit_project], role.permissions
-  end
-
-  def test_update_with_failure
-    put :update, :id => 1, :role => {:name => ''}
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_destroy
-    r = Role.create!(:name => 'ToBeDestroyed', :permissions => [:view_wiki_pages])
-
-    delete :destroy, :id => r
-    assert_redirected_to '/roles'
-    assert_nil Role.find_by_id(r.id)
-  end
-
-  def test_destroy_role_in_use
-    delete :destroy, :id => 1
-    assert_redirected_to '/roles'
-    assert_equal 'This role is in use and cannot be deleted.', flash[:error] 
-    assert_not_nil Role.find_by_id(1)
-  end
-
-  def test_get_permissions
-    get :permissions
-    assert_response :success
-    assert_template 'permissions'
-
-    assert_not_nil assigns(:roles)
-    assert_equal Role.order('builtin, position').all, assigns(:roles)
-
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'permissions[3][]',
-                                                 :value => 'add_issues',
-                                                 :checked => 'checked' }
-
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'permissions[3][]',
-                                                 :value => 'delete_issues',
-                                                 :checked => nil }
-  end
-
-  def test_post_permissions
-    post :permissions, :permissions => { '0' => '', '1' => ['edit_issues'], '3' => ['add_issues', 'delete_issues']}
-    assert_redirected_to '/roles'
-
-    assert_equal [:edit_issues], Role.find(1).permissions
-    assert_equal [:add_issues, :delete_issues], Role.find(3).permissions
-    assert Role.find(2).permissions.empty?
-  end
-
-  def test_clear_all_permissions
-    post :permissions, :permissions => { '0' => '' }
-    assert_redirected_to '/roles'
-    assert Role.find(1).permissions.empty?
-  end
-
-  def test_move_highest
-    put :update, :id => 3, :role => {:move_to => 'highest'}
-    assert_redirected_to '/roles'
-    assert_equal 1, Role.find(3).position
-  end
-
-  def test_move_higher
-    position = Role.find(3).position
-    put :update, :id => 3, :role => {:move_to => 'higher'}
-    assert_redirected_to '/roles'
-    assert_equal position - 1, Role.find(3).position
-  end
-
-  def test_move_lower
-    position = Role.find(2).position
-    put :update, :id => 2, :role => {:move_to => 'lower'}
-    assert_redirected_to '/roles'
-    assert_equal position + 1, Role.find(2).position
-  end
-
-  def test_move_lowest
-    put :update, :id => 2, :role => {:move_to => 'lowest'}
-    assert_redirected_to '/roles'
-    assert_equal Role.count, Role.find(2).position
-  end
-end
--- a/.svn/pristine/07/07ff3aff4af2ca5266644ab7e838820cda8c8752.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingAutoCompletesTest < ActionController::IntegrationTest
-  def test_auto_completes
-    assert_routing(
-        { :method => 'get', :path => "/issues/auto_complete" },
-        { :controller => 'auto_completes', :action => 'issues' }
-      )
-  end
-end
--- a/.svn/pristine/08/086f4bbd984edf33971e918b1e5330fe445e9dd7.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class Redmine::MenuManager::MenuHelperTest < ActionView::TestCase
-
-  include Redmine::MenuManager::MenuHelper
-  include ERB::Util
-  fixtures :users, :members, :projects, :enabled_modules, :roles, :member_roles
-
-  def setup
-    setup_with_controller
-    # Stub the current menu item in the controller
-    def current_menu_item
-      :index
-    end
-  end
-
-  context "MenuManager#current_menu_item" do
-    should "be tested"
-  end
-
-  context "MenuManager#render_main_menu" do
-    should "be tested"
-  end
-
-  context "MenuManager#render_menu" do
-    should "be tested"
-  end
-
-  context "MenuManager#menu_item_and_children" do
-    should "be tested"
-  end
-
-  context "MenuManager#extract_node_details" do
-    should "be tested"
-  end
-
-  def test_render_single_menu_node
-    node = Redmine::MenuManager::MenuItem.new(:testing, '/test', { })
-    @output_buffer = render_single_menu_node(node, 'This is a test', node.url, false)
-
-    assert_select("a.testing", "This is a test")
-  end
-
-  def test_render_menu_node
-    single_node = Redmine::MenuManager::MenuItem.new(:single_node, '/test', { })
-    @output_buffer = render_menu_node(single_node, nil)
-
-    assert_select("li") do
-      assert_select("a.single-node", "Single node")
-    end
-  end
-
-  def test_render_menu_node_with_nested_items
-    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node, '/test', { })
-    parent_node << Redmine::MenuManager::MenuItem.new(:child_one_node, '/test', { })
-    parent_node << Redmine::MenuManager::MenuItem.new(:child_two_node, '/test', { })
-    parent_node <<
-      Redmine::MenuManager::MenuItem.new(:child_three_node, '/test', { }) <<
-      Redmine::MenuManager::MenuItem.new(:child_three_inner_node, '/test', { })
-
-    @output_buffer = render_menu_node(parent_node, nil)
-
-    assert_select("li") do
-      assert_select("a.parent-node", "Parent node")
-      assert_select("ul") do
-        assert_select("li a.child-one-node", "Child one node")
-        assert_select("li a.child-two-node", "Child two node")
-        assert_select("li") do
-          assert_select("a.child-three-node", "Child three node")
-          assert_select("ul") do
-            assert_select("li a.child-three-inner-node", "Child three inner node")
-          end
-        end
-      end
-    end
-
-  end
-
-  def test_render_menu_node_with_children
-    User.current = User.find(2)
-
-    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
-                                                     '/test',
-                                                     {
-                                                       :children => Proc.new {|p|
-                                                         children = []
-                                                         3.times do |time|
-                                                           children << Redmine::MenuManager::MenuItem.new("test_child_#{time}",
-                                                                                                             {:controller => 'issues', :action => 'index'},
-                                                                                                             {})
-                                                         end
-                                                         children
-                                                       }
-                                                     })
-    @output_buffer = render_menu_node(parent_node, Project.find(1))
-
-    assert_select("li") do
-      assert_select("a.parent-node", "Parent node")
-      assert_select("ul") do
-        assert_select("li a.test-child-0", "Test child 0")
-        assert_select("li a.test-child-1", "Test child 1")
-        assert_select("li a.test-child-2", "Test child 2")
-      end
-    end
-  end
-
-  def test_render_menu_node_with_nested_items_and_children
-    User.current = User.find(2)
-
-    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
-                                                     '/test',
-                                                     {
-                                                       :children => Proc.new {|p|
-                                                         children = []
-                                                         3.times do |time|
-                                                           children << Redmine::MenuManager::MenuItem.new("test_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
-                                                         end
-                                                         children
-                                                       }
-                                                     })
-
-    parent_node << Redmine::MenuManager::MenuItem.new(:child_node,
-                                                     '/test',
-                                                     {
-                                                       :children => Proc.new {|p|
-                                                         children = []
-                                                         6.times do |time|
-                                                            children << Redmine::MenuManager::MenuItem.new("test_dynamic_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
-                                                         end
-                                                         children
-                                                       }
-                                                     })
-
-    @output_buffer = render_menu_node(parent_node, Project.find(1))
-
-    assert_select("li") do
-      assert_select("a.parent-node", "Parent node")
-      assert_select("ul") do
-        assert_select("li a.child-node", "Child node")
-        assert_select("ul") do
-          assert_select("li a.test-dynamic-child-0", "Test dynamic child 0")
-          assert_select("li a.test-dynamic-child-1", "Test dynamic child 1")
-          assert_select("li a.test-dynamic-child-2", "Test dynamic child 2")
-          assert_select("li a.test-dynamic-child-3", "Test dynamic child 3")
-          assert_select("li a.test-dynamic-child-4", "Test dynamic child 4")
-          assert_select("li a.test-dynamic-child-5", "Test dynamic child 5")
-        end
-        assert_select("li a.test-child-0", "Test child 0")
-        assert_select("li a.test-child-1", "Test child 1")
-        assert_select("li a.test-child-2", "Test child 2")
-      end
-    end
-  end
-
-  def test_render_menu_node_with_children_without_an_array
-    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
-                                                     '/test',
-                                                     {
-                                                       :children => Proc.new {|p| Redmine::MenuManager::MenuItem.new("test_child", "/testing", {})}
-                                                     })
-
-    assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
-      @output_buffer = render_menu_node(parent_node, Project.find(1))
-    end
-  end
-
-  def test_render_menu_node_with_incorrect_children
-    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
-                                                     '/test',
-                                                     {
-                                                       :children => Proc.new {|p| ["a string"] }
-                                                     })
-
-    assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
-      @output_buffer = render_menu_node(parent_node, Project.find(1))
-    end
-
-  end
-
-  def test_menu_items_for_should_yield_all_items_if_passed_a_block
-    menu_name = :test_menu_items_for_should_yield_all_items_if_passed_a_block
-    Redmine::MenuManager.map menu_name do |menu|
-      menu.push(:a_menu, '/', { })
-      menu.push(:a_menu_2, '/', { })
-      menu.push(:a_menu_3, '/', { })
-    end
-
-    items_yielded = []
-    menu_items_for(menu_name) do |item|
-      items_yielded << item
-    end
-
-    assert_equal 3, items_yielded.size
-  end
-
-  def test_menu_items_for_should_return_all_items
-    menu_name = :test_menu_items_for_should_return_all_items
-    Redmine::MenuManager.map menu_name do |menu|
-      menu.push(:a_menu, '/', { })
-      menu.push(:a_menu_2, '/', { })
-      menu.push(:a_menu_3, '/', { })
-    end
-
-    items = menu_items_for(menu_name)
-    assert_equal 3, items.size
-  end
-
-  def test_menu_items_for_should_skip_unallowed_items_on_a_project
-    menu_name = :test_menu_items_for_should_skip_unallowed_items_on_a_project
-    Redmine::MenuManager.map menu_name do |menu|
-      menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
-      menu.push(:a_menu_2, {:controller => 'issues', :action => 'index' }, { })
-      menu.push(:unallowed, {:controller => 'issues', :action => 'unallowed' }, { })
-    end
-
-    User.current = User.find(2)
-
-    items = menu_items_for(menu_name, Project.find(1))
-    assert_equal 2, items.size
-  end
-
-  def test_menu_items_for_should_skip_items_that_fail_the_conditions
-    menu_name = :test_menu_items_for_should_skip_items_that_fail_the_conditions
-    Redmine::MenuManager.map menu_name do |menu|
-      menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
-      menu.push(:unallowed,
-                {:controller => 'issues', :action => 'index' },
-                { :if => Proc.new { false }})
-    end
-
-    User.current = User.find(2)
-
-    items = menu_items_for(menu_name, Project.find(1))
-    assert_equal 1, items.size
-  end
-end
--- a/.svn/pristine/08/088eae42f08379f3106075b388f036d1754d148c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module EnumerationsHelper
-end
--- a/.svn/pristine/08/08c1f1410c30c4d18ef6cbcbd8954d1721fb044b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WatchersControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
-           :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
-
-  def setup
-    User.current = nil
-  end
-
-  def test_watch_a_single_object
-    @request.session[:user_id] = 3
-    assert_difference('Watcher.count') do
-      xhr :post, :watch, :object_type => 'issue', :object_id => '1'
-      assert_response :success
-      assert_include '$(".issue-1-watcher")', response.body
-    end
-    assert Issue.find(1).watched_by?(User.find(3))
-  end
-
-  def test_watch_a_collection_with_a_single_object
-    @request.session[:user_id] = 3
-    assert_difference('Watcher.count') do
-      xhr :post, :watch, :object_type => 'issue', :object_id => ['1']
-      assert_response :success
-      assert_include '$(".issue-1-watcher")', response.body
-    end
-    assert Issue.find(1).watched_by?(User.find(3))
-  end
-
-  def test_watch_a_collection_with_multiple_objects
-    @request.session[:user_id] = 3
-    assert_difference('Watcher.count', 2) do
-      xhr :post, :watch, :object_type => 'issue', :object_id => ['1', '3']
-      assert_response :success
-      assert_include '$(".issue-bulk-watcher")', response.body
-    end
-    assert Issue.find(1).watched_by?(User.find(3))
-    assert Issue.find(3).watched_by?(User.find(3))
-  end
-
-  def test_watch_should_be_denied_without_permission
-    Role.find(2).remove_permission! :view_issues
-    @request.session[:user_id] = 3
-    assert_no_difference('Watcher.count') do
-      xhr :post, :watch, :object_type => 'issue', :object_id => '1'
-      assert_response 403
-    end
-  end
-
-  def test_watch_invalid_class_should_respond_with_404
-    @request.session[:user_id] = 3
-    assert_no_difference('Watcher.count') do
-      xhr :post, :watch, :object_type => 'foo', :object_id => '1'
-      assert_response 404
-    end
-  end
-
-  def test_watch_invalid_object_should_respond_with_404
-    @request.session[:user_id] = 3
-    assert_no_difference('Watcher.count') do
-      xhr :post, :watch, :object_type => 'issue', :object_id => '999'
-      assert_response 404
-    end
-  end
-
-  def test_unwatch
-    @request.session[:user_id] = 3
-    assert_difference('Watcher.count', -1) do
-      xhr :delete, :unwatch, :object_type => 'issue', :object_id => '2'
-      assert_response :success
-      assert_include '$(".issue-2-watcher")', response.body
-    end
-    assert !Issue.find(1).watched_by?(User.find(3))
-  end
-
-  def test_unwatch_a_collection_with_multiple_objects
-    @request.session[:user_id] = 3
-    Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
-    Watcher.create!(:user_id => 3, :watchable => Issue.find(3))
-
-    assert_difference('Watcher.count', -2) do
-      xhr :delete, :unwatch, :object_type => 'issue', :object_id => ['1', '3']
-      assert_response :success
-      assert_include '$(".issue-bulk-watcher")', response.body
-    end
-    assert !Issue.find(1).watched_by?(User.find(3))
-    assert !Issue.find(3).watched_by?(User.find(3))
-  end
-
-  def test_new
-    @request.session[:user_id] = 2
-    xhr :get, :new, :object_type => 'issue', :object_id => '2'
-    assert_response :success
-    assert_match /ajax-modal/, response.body
-  end
-
-  def test_new_for_new_record_with_project_id
-    @request.session[:user_id] = 2
-    xhr :get, :new, :project_id => 1
-    assert_response :success
-    assert_equal Project.find(1), assigns(:project)
-    assert_match /ajax-modal/, response.body
-  end
-
-  def test_new_for_new_record_with_project_identifier
-    @request.session[:user_id] = 2
-    xhr :get, :new, :project_id => 'ecookbook'
-    assert_response :success
-    assert_equal Project.find(1), assigns(:project)
-    assert_match /ajax-modal/, response.body
-  end
-
-  def test_create
-    @request.session[:user_id] = 2
-    assert_difference('Watcher.count') do
-      xhr :post, :create, :object_type => 'issue', :object_id => '2', :watcher => {:user_id => '4'}
-      assert_response :success
-      assert_match /watchers/, response.body
-      assert_match /ajax-modal/, response.body
-    end
-    assert Issue.find(2).watched_by?(User.find(4))
-  end
-
-  def test_create_multiple
-    @request.session[:user_id] = 2
-    assert_difference('Watcher.count', 2) do
-      xhr :post, :create, :object_type => 'issue', :object_id => '2', :watcher => {:user_ids => ['4', '7']}
-      assert_response :success
-      assert_match /watchers/, response.body
-      assert_match /ajax-modal/, response.body
-    end
-    assert Issue.find(2).watched_by?(User.find(4))
-    assert Issue.find(2).watched_by?(User.find(7))
-  end
-
-  def test_autocomplete_on_watchable_creation
-    @request.session[:user_id] = 2
-    xhr :get, :autocomplete_for_user, :q => 'mi', :project_id => 'ecookbook'
-    assert_response :success
-    assert_select 'input', :count => 4
-    assert_select 'input[name=?][value=1]', 'watcher[user_ids][]'
-    assert_select 'input[name=?][value=2]', 'watcher[user_ids][]'
-    assert_select 'input[name=?][value=8]', 'watcher[user_ids][]'
-    assert_select 'input[name=?][value=9]', 'watcher[user_ids][]'
-  end
-
-  def test_autocomplete_on_watchable_update
-    @request.session[:user_id] = 2
-    xhr :get, :autocomplete_for_user, :q => 'mi', :object_id => '2' , :object_type => 'issue', :project_id => 'ecookbook'
-    assert_response :success
-    assert_select 'input', :count => 3
-    assert_select 'input[name=?][value=2]', 'watcher[user_ids][]'
-    assert_select 'input[name=?][value=8]', 'watcher[user_ids][]'
-    assert_select 'input[name=?][value=9]', 'watcher[user_ids][]'
-
-  end
-
-  def test_append
-    @request.session[:user_id] = 2
-    assert_no_difference 'Watcher.count' do
-      xhr :post, :append, :watcher => {:user_ids => ['4', '7']}, :project_id => 'ecookbook'
-      assert_response :success
-      assert_include 'watchers_inputs', response.body
-      assert_include 'issue[watcher_user_ids][]', response.body
-    end
-  end
-
-  def test_remove_watcher
-    @request.session[:user_id] = 2
-    assert_difference('Watcher.count', -1) do
-      xhr :delete, :destroy, :object_type => 'issue', :object_id => '2', :user_id => '3'
-      assert_response :success
-      assert_match /watchers/, response.body
-    end
-    assert !Issue.find(2).watched_by?(User.find(3))
-  end
-end
--- a/.svn/pristine/09/094f0fabb02fa5ce798642abc8745a5aba89d2d9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AccountControllerOpenidTest < ActionController::TestCase
-  tests AccountController
-  fixtures :users, :roles
-
-  def setup
-    User.current = nil
-    Setting.openid = '1'
-  end
-
-  def teardown
-    Setting.openid = '0'
-  end
-
-  if Object.const_defined?(:OpenID)
-
-    def test_login_with_openid_for_existing_user
-      Setting.self_registration = '3'
-      existing_user = User.new(:firstname => 'Cool',
-                               :lastname => 'User',
-                               :mail => 'user@somedomain.com',
-                               :identity_url => 'http://openid.example.com/good_user')
-      existing_user.login = 'cool_user'
-      assert existing_user.save!
-
-      post :login, :openid_url => existing_user.identity_url
-      assert_redirected_to '/my/page'
-    end
-
-    def test_login_with_invalid_openid_provider
-      Setting.self_registration = '0'
-      post :login, :openid_url => 'http;//openid.example.com/good_user'
-      assert_redirected_to home_url
-    end
-
-    def test_login_with_openid_for_existing_non_active_user
-      Setting.self_registration = '2'
-      existing_user = User.new(:firstname => 'Cool',
-                               :lastname => 'User',
-                               :mail => 'user@somedomain.com',
-                               :identity_url => 'http://openid.example.com/good_user',
-                               :status => User::STATUS_REGISTERED)
-      existing_user.login = 'cool_user'
-      assert existing_user.save!
-
-      post :login, :openid_url => existing_user.identity_url
-      assert_redirected_to '/login'
-    end
-
-    def test_login_with_openid_with_new_user_created
-      Setting.self_registration = '3'
-      post :login, :openid_url => 'http://openid.example.com/good_user'
-      assert_redirected_to '/my/account'
-      user = User.find_by_login('cool_user')
-      assert user
-      assert_equal 'Cool', user.firstname
-      assert_equal 'User', user.lastname
-    end
-
-    def test_login_with_openid_with_new_user_and_self_registration_off
-      Setting.self_registration = '0'
-      post :login, :openid_url => 'http://openid.example.com/good_user'
-      assert_redirected_to home_url
-      user = User.find_by_login('cool_user')
-      assert_nil user
-    end
-
-    def test_login_with_openid_with_new_user_created_with_email_activation_should_have_a_token
-      Setting.self_registration = '1'
-      post :login, :openid_url => 'http://openid.example.com/good_user'
-      assert_redirected_to '/login'
-      user = User.find_by_login('cool_user')
-      assert user
-
-      token = Token.find_by_user_id_and_action(user.id, 'register')
-      assert token
-    end
-
-    def test_login_with_openid_with_new_user_created_with_manual_activation
-      Setting.self_registration = '2'
-      post :login, :openid_url => 'http://openid.example.com/good_user'
-      assert_redirected_to '/login'
-      user = User.find_by_login('cool_user')
-      assert user
-      assert_equal User::STATUS_REGISTERED, user.status
-    end
-
-    def test_login_with_openid_with_new_user_with_conflict_should_register
-      Setting.self_registration = '3'
-      existing_user = User.new(:firstname => 'Cool', :lastname => 'User', :mail => 'user@somedomain.com')
-      existing_user.login = 'cool_user'
-      assert existing_user.save!
-
-      post :login, :openid_url => 'http://openid.example.com/good_user'
-      assert_response :success
-      assert_template 'register'
-      assert assigns(:user)
-      assert_equal 'http://openid.example.com/good_user', assigns(:user)[:identity_url]
-    end
-
-    def test_login_with_openid_with_new_user_with_missing_information_should_register
-      Setting.self_registration = '3'
-
-      post :login, :openid_url => 'http://openid.example.com/good_blank_user'
-      assert_response :success
-      assert_template 'register'
-      assert assigns(:user)
-      assert_equal 'http://openid.example.com/good_blank_user', assigns(:user)[:identity_url]
-
-      assert_select 'input[name=?]', 'user[login]'
-      assert_select 'input[name=?]', 'user[password]'
-      assert_select 'input[name=?]', 'user[password_confirmation]'
-      assert_select 'input[name=?][value=?]', 'user[identity_url]', 'http://openid.example.com/good_blank_user'
-    end
-
-    def test_post_login_should_not_verify_token_when_using_open_id
-      ActionController::Base.allow_forgery_protection = true
-      AccountController.any_instance.stubs(:using_open_id?).returns(true)
-      AccountController.any_instance.stubs(:authenticate_with_open_id).returns(true)
-      post :login
-      assert_response 200
-    ensure
-      ActionController::Base.allow_forgery_protection = false
-    end
-
-    def test_register_after_login_failure_should_not_require_user_to_enter_a_password
-      Setting.self_registration = '3'
-
-      assert_difference 'User.count' do
-        post :register, :user => {
-          :login => 'good_blank_user',
-          :password => '',
-          :password_confirmation => '',
-          :firstname => 'Cool',
-          :lastname => 'User',
-          :mail => 'user@somedomain.com',
-          :identity_url => 'http://openid.example.com/good_blank_user'
-        }
-        assert_response 302
-      end
-
-      user = User.first(:order => 'id DESC')
-      assert_equal 'http://openid.example.com/good_blank_user', user.identity_url
-      assert user.hashed_password.blank?, "Hashed password was #{user.hashed_password}"
-    end
-
-    def test_setting_openid_should_return_true_when_set_to_true
-      assert_equal true, Setting.openid?
-    end
-
-  else
-    puts "Skipping openid tests."
-
-    def test_dummy
-    end
-  end
-end
--- a/.svn/pristine/09/09d005add00d07aeb449a6c04ad00db8e1f72fbd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingMyTest < ActionController::IntegrationTest
-  def test_my
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/my/account" },
-          { :controller => 'my', :action => 'account' }
-        )
-    end
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/my/account/destroy" },
-          { :controller => 'my', :action => 'destroy' }
-        )
-    end
-    assert_routing(
-        { :method => 'get', :path => "/my/page" },
-        { :controller => 'my', :action => 'page' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/my" },
-        { :controller => 'my', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/my/reset_rss_key" },
-        { :controller => 'my', :action => 'reset_rss_key' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/my/reset_api_key" },
-        { :controller => 'my', :action => 'reset_api_key' }
-      )
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/my/password" },
-          { :controller => 'my', :action => 'password' }
-        )
-    end
-    assert_routing(
-        { :method => 'get', :path => "/my/page_layout" },
-        { :controller => 'my', :action => 'page_layout' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/my/add_block" },
-        { :controller => 'my', :action => 'add_block' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/my/remove_block" },
-        { :controller => 'my', :action => 'remove_block' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/my/order_blocks" },
-        { :controller => 'my', :action => 'order_blocks' }
-      )
-  end
-end
--- a/.svn/pristine/0a/0a01ef88ba34bfc6a3c1cef8891538f7504e9b0c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module I18n
-    def self.included(base)
-      base.extend Redmine::I18n
-    end
-
-    def l(*args)
-      case args.size
-      when 1
-        ::I18n.t(*args)
-      when 2
-        if args.last.is_a?(Hash)
-          ::I18n.t(*args)
-        elsif args.last.is_a?(String)
-          ::I18n.t(args.first, :value => args.last)
-        else
-          ::I18n.t(args.first, :count => args.last)
-        end
-      else
-        raise "Translation string with multiple values: #{args.first}"
-      end
-    end
-
-    def l_or_humanize(s, options={})
-      k = "#{options[:prefix]}#{s}".to_sym
-      ::I18n.t(k, :default => s.to_s.humanize)
-    end
-
-    def l_hours(hours)
-      hours = hours.to_f
-      l((hours < 2.0 ? :label_f_hour : :label_f_hour_plural), :value => ("%.2f" % hours.to_f))
-    end
-
-    def ll(lang, str, value=nil)
-      ::I18n.t(str.to_s, :value => value, :locale => lang.to_s.gsub(%r{(.+)\-(.+)$}) { "#{$1}-#{$2.upcase}" })
-    end
-
-    def format_date(date)
-      return nil unless date
-      options = {}
-      options[:format] = Setting.date_format unless Setting.date_format.blank?
-      options[:locale] = User.current.language unless User.current.language.blank?
-      ::I18n.l(date.to_date, options)
-    end
-
-    def format_time(time, include_date = true)
-      return nil unless time
-      options = {}
-      options[:format] = (Setting.time_format.blank? ? :time : Setting.time_format)
-      options[:locale] = User.current.language unless User.current.language.blank?
-      time = time.to_time if time.is_a?(String)
-      zone = User.current.time_zone
-      local = zone ? time.in_time_zone(zone) : (time.utc? ? time.localtime : time)
-      (include_date ? "#{format_date(local)} " : "") + ::I18n.l(local, options)
-    end
-
-    def day_name(day)
-      ::I18n.t('date.day_names')[day % 7]
-    end
-
-    def day_letter(day)
-      ::I18n.t('date.abbr_day_names')[day % 7].first
-    end
-
-    def month_name(month)
-      ::I18n.t('date.month_names')[month]
-    end
-
-    def valid_languages
-      ::I18n.available_locales
-    end
-
-    # Returns an array of languages names and code sorted by names, example:
-    # [["Deutsch", "de"], ["English", "en"] ...]
-    #
-    # The result is cached to prevent from loading all translations files.
-    def languages_options
-      ActionController::Base.cache_store.fetch "i18n/languages_options" do
-        valid_languages.map {|lang| [ll(lang.to_s, :general_lang_name), lang.to_s]}.sort {|x,y| x.first <=> y.first }
-      end      
-    end
-
-    def find_language(lang)
-      @@languages_lookup = valid_languages.inject({}) {|k, v| k[v.to_s.downcase] = v; k }
-      @@languages_lookup[lang.to_s.downcase]
-    end
-
-    def set_language_if_valid(lang)
-      if l = find_language(lang)
-        ::I18n.locale = l
-      end
-    end
-
-    def current_language
-      ::I18n.locale
-    end
-
-    # Custom backend based on I18n::Backend::Simple with the following changes:
-    # * lazy loading of translation files
-    # * available_locales are determined by looking at translation file names
-    class Backend
-      (class << self; self; end).class_eval { public :include }
-
-      module Implementation
-        include ::I18n::Backend::Base
-
-        # Stores translations for the given locale in memory.
-        # This uses a deep merge for the translations hash, so existing
-        # translations will be overwritten by new ones only at the deepest
-        # level of the hash.
-        def store_translations(locale, data, options = {})
-          locale = locale.to_sym
-          translations[locale] ||= {}
-          data = data.deep_symbolize_keys
-          translations[locale].deep_merge!(data)
-        end
-
-        # Get available locales from the translations filenames
-        def available_locales
-          @available_locales ||= ::I18n.load_path.map {|path| File.basename(path, '.*')}.uniq.sort.map(&:to_sym)
-        end
-
-        # Clean up translations
-        def reload!
-          @translations = nil
-          @available_locales = nil
-          super
-        end
-
-        protected
-
-        def init_translations(locale)
-          locale = locale.to_s
-          paths = ::I18n.load_path.select {|path| File.basename(path, '.*') == locale}
-          load_translations(paths)
-          translations[locale] ||= {}
-        end
-
-        def translations
-          @translations ||= {}
-        end
-
-        # Looks up a translation from the translations hash. Returns nil if
-        # eiher key is nil, or locale, scope or key do not exist as a key in the
-        # nested translations hash. Splits keys or scopes containing dots
-        # into multiple keys, i.e. <tt>currency.format</tt> is regarded the same as
-        # <tt>%w(currency format)</tt>.
-        def lookup(locale, key, scope = [], options = {})
-          init_translations(locale) unless translations.key?(locale)
-          keys = ::I18n.normalize_keys(locale, key, scope, options[:separator])
-
-          keys.inject(translations) do |result, _key|
-            _key = _key.to_sym
-            return nil unless result.is_a?(Hash) && result.has_key?(_key)
-            result = result[_key]
-            result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol)
-            result
-          end
-        end
-      end
-
-      include Implementation
-      # Adds fallback to default locale for untranslated strings
-      include ::I18n::Backend::Fallbacks
-    end
-  end
-end
--- a/.svn/pristine/0b/0b7befce1d7322f245834ffc9480adf8d5c60890.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,294 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../test_case', __FILE__)
-require 'tmpdir'
-
-class RedminePmTest::RepositorySubversionTest < RedminePmTest::TestCase
-  fixtures :projects, :users, :members, :roles, :member_roles, :auth_sources
-
-  SVN_BIN = Redmine::Configuration['scm_subversion_command'] || "svn"
-
-  def test_anonymous_read_on_public_repo_with_permission_should_succeed
-    assert_success "ls", svn_url
-  end
-
-  def test_anonymous_read_on_public_repo_without_permission_should_fail
-    Role.anonymous.remove_permission! :browse_repository
-    assert_failure "ls", svn_url
-  end
-
-  def test_anonymous_read_on_private_repo_should_fail
-    Project.find(1).update_attribute :is_public, false
-    assert_failure "ls", svn_url
-  end
-
-  def test_anonymous_commit_on_public_repo_should_fail
-    Role.anonymous.add_permission! :commit_access
-    assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
-  end
-
-  def test_anonymous_commit_on_private_repo_should_fail
-    Role.anonymous.add_permission! :commit_access
-    Project.find(1).update_attribute :is_public, false
-    assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
-  end
-
-  def test_non_member_read_on_public_repo_with_permission_should_succeed
-    Role.anonymous.remove_permission! :browse_repository
-    with_credentials "miscuser8", "foo" do
-      assert_success "ls", svn_url
-    end
-  end
-
-  def test_non_member_read_on_public_repo_without_permission_should_fail
-    Role.anonymous.remove_permission! :browse_repository
-    Role.non_member.remove_permission! :browse_repository
-    with_credentials "miscuser8", "foo" do
-      assert_failure "ls", svn_url
-    end
-  end
-
-  def test_non_member_read_on_private_repo_should_fail
-    Project.find(1).update_attribute :is_public, false
-    with_credentials "miscuser8", "foo" do
-      assert_failure "ls", svn_url
-    end
-  end
-
-  def test_non_member_commit_on_public_repo_should_fail
-    Role.non_member.add_permission! :commit_access
-    assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
-  end
-
-  def test_non_member_commit_on_private_repo_should_fail
-    Role.non_member.add_permission! :commit_access
-    Project.find(1).update_attribute :is_public, false
-    assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
-  end
-
-  def test_member_read_on_public_repo_with_permission_should_succeed
-    Role.anonymous.remove_permission! :browse_repository
-    Role.non_member.remove_permission! :browse_repository
-    with_credentials "dlopper", "foo" do
-      assert_success "ls", svn_url
-    end
-  end
-
-  def test_member_read_on_public_repo_without_permission_should_fail
-    Role.anonymous.remove_permission! :browse_repository
-    Role.non_member.remove_permission! :browse_repository
-    Role.find(2).remove_permission! :browse_repository
-    with_credentials "dlopper", "foo" do
-      assert_failure "ls", svn_url
-    end
-  end
-
-  def test_member_read_on_private_repo_with_permission_should_succeed
-    Project.find(1).update_attribute :is_public, false
-    with_credentials "dlopper", "foo" do
-      assert_success "ls", svn_url
-    end
-  end
-
-  def test_member_read_on_private_repo_without_permission_should_fail
-    Role.find(2).remove_permission! :browse_repository
-    Project.find(1).update_attribute :is_public, false
-    with_credentials "dlopper", "foo" do
-      assert_failure "ls", svn_url
-    end
-  end
-
-  def test_member_commit_on_public_repo_with_permission_should_succeed
-    Role.find(2).add_permission! :commit_access
-    with_credentials "dlopper", "foo" do
-      assert_success "mkdir --message Creating_a_directory", svn_url(random_filename)
-    end
-  end
-
-  def test_member_commit_on_public_repo_without_permission_should_fail
-    Role.find(2).remove_permission! :commit_access
-    with_credentials "dlopper", "foo" do
-      assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
-    end
-  end
-
-  def test_member_commit_on_private_repo_with_permission_should_succeed
-    Role.find(2).add_permission! :commit_access
-    Project.find(1).update_attribute :is_public, false
-    with_credentials "dlopper", "foo" do
-      assert_success "mkdir --message Creating_a_directory", svn_url(random_filename)
-    end
-  end
-
-  def test_member_commit_on_private_repo_without_permission_should_fail
-    Role.find(2).remove_permission! :commit_access
-    Project.find(1).update_attribute :is_public, false
-    with_credentials "dlopper", "foo" do
-      assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
-    end
-  end
-
-  def test_invalid_credentials_should_fail
-    Project.find(1).update_attribute :is_public, false
-    with_credentials "dlopper", "foo" do
-      assert_success "ls", svn_url
-    end
-    with_credentials "dlopper", "wrong" do
-      assert_failure "ls", svn_url
-    end
-  end
-
-  def test_anonymous_read_should_fail_with_login_required
-    assert_success "ls", svn_url
-    with_settings :login_required => '1' do
-      assert_failure "ls", svn_url
-    end
-  end
-
-  def test_authenticated_read_should_succeed_with_login_required
-    with_settings :login_required => '1' do
-      with_credentials "miscuser8", "foo" do
-        assert_success "ls", svn_url
-      end
-    end
-  end
-
-  def test_read_on_archived_projects_should_fail
-    Project.find(1).update_attribute :status, Project::STATUS_ARCHIVED
-    assert_failure "ls", svn_url
-  end
-
-  def test_read_on_archived_private_projects_should_fail
-    Project.find(1).update_attribute :status, Project::STATUS_ARCHIVED
-    Project.find(1).update_attribute :is_public, false
-    with_credentials "dlopper", "foo" do
-      assert_failure "ls", svn_url
-    end
-  end
-
-  def test_read_on_closed_projects_should_succeed
-    Project.find(1).update_attribute :status, Project::STATUS_CLOSED
-    assert_success "ls", svn_url
-  end
-
-  def test_read_on_closed_private_projects_should_succeed
-    Project.find(1).update_attribute :status, Project::STATUS_CLOSED
-    Project.find(1).update_attribute :is_public, false
-    with_credentials "dlopper", "foo" do
-      assert_success "ls", svn_url
-    end
-  end
-
-  def test_commit_on_closed_projects_should_fail
-    Project.find(1).update_attribute :status, Project::STATUS_CLOSED
-    Role.find(2).add_permission! :commit_access
-    with_credentials "dlopper", "foo" do
-      assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
-    end
-  end
-
-  def test_commit_on_closed_private_projects_should_fail
-    Project.find(1).update_attribute :status, Project::STATUS_CLOSED
-    Project.find(1).update_attribute :is_public, false
-    Role.find(2).add_permission! :commit_access
-    with_credentials "dlopper", "foo" do
-      assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
-    end
-  end
-
-  if ldap_configured?
-    def test_user_with_ldap_auth_source_should_authenticate_with_ldap_credentials
-      ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
-      ldap_user.login = 'example1'
-      ldap_user.save!
-  
-      with_settings :login_required => '1' do
-        with_credentials "example1", "123456" do
-          assert_success "ls", svn_url
-        end
-      end
-  
-      with_settings :login_required => '1' do
-        with_credentials "example1", "wrong" do
-          assert_failure "ls", svn_url
-        end
-      end
-    end
-  end
-
-  def test_checkout
-    Dir.mktmpdir do |dir|
-      assert_success "checkout", svn_url, dir
-    end
-  end
-
-  def test_read_commands
-    assert_success "info", svn_url
-    assert_success "ls", svn_url
-    assert_success "log", svn_url
-  end
-
-  def test_write_commands
-    Role.find(2).add_permission! :commit_access
-    filename = random_filename
-
-    Dir.mktmpdir do |dir|
-      assert_success "checkout", svn_url, dir
-      Dir.chdir(dir) do
-        # creates a file in the working copy
-        f = File.new(File.join(dir, filename), "w")
-        f.write "test file content"
-        f.close
-
-        assert_success "add", filename
-        with_credentials "dlopper", "foo" do
-          assert_success "commit --message Committing_a_file"
-          assert_success "copy   --message Copying_a_file", svn_url(filename), svn_url("#{filename}_copy")
-          assert_success "delete --message Deleting_a_file", svn_url(filename)
-          assert_success "mkdir  --message Creating_a_directory", svn_url("#{filename}_dir")
-        end
-        assert_success "update"
-
-        # checks that the working copy was updated
-        assert File.exists?(File.join(dir, "#{filename}_copy"))
-        assert File.directory?(File.join(dir, "#{filename}_dir"))
-      end
-    end
-  end
-
-  def test_read_invalid_repo_should_fail
-    assert_failure "ls", svn_url("invalid")
-  end
-
-  protected
-
-  def execute(*args)
-    a = [SVN_BIN, "--no-auth-cache --non-interactive"]
-    a << "--username #{username}" if username
-    a << "--password #{password}" if password
-
-    super a, *args
-  end
-
-  def svn_url(path=nil)
-    host = ENV['REDMINE_TEST_DAV_SERVER'] || '127.0.0.1'
-    url = "http://#{host}/svn/ecookbook"
-    url << "/#{path}" if path
-    url
-  end
-end
--- a/.svn/pristine/0b/0b8a142f46ed608799d7faf6016772f4b1f09f42.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingAdminTest < ActionController::IntegrationTest
-  def test_administration_panel
-    assert_routing(
-        { :method => 'get', :path => "/admin" },
-        { :controller => 'admin', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/admin/projects" },
-        { :controller => 'admin', :action => 'projects' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/admin/plugins" },
-        { :controller => 'admin', :action => 'plugins' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/admin/info" },
-        { :controller => 'admin', :action => 'info' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/admin/test_email" },
-        { :controller => 'admin', :action => 'test_email' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/admin/default_configuration" },
-        { :controller => 'admin', :action => 'default_configuration' }
-      )
-  end
-end
--- a/.svn/pristine/0b/0bba8bba58df7fc70a5a93a0d2973b34736d639d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,448 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'cgi'
-require 'redmine/scm/adapters'
-
-if RUBY_VERSION < '1.9'
-  require 'iconv'
-end
-
-module Redmine
-  module Scm
-    module Adapters
-      class AbstractAdapter #:nodoc:
-
-        # raised if scm command exited with error, e.g. unknown revision.
-        class ScmCommandAborted < CommandFailed; end
-
-        class << self
-          def client_command
-            ""
-          end
-
-          def shell_quote_command
-            if Redmine::Platform.mswin? && RUBY_PLATFORM == 'java'
-              client_command
-            else
-              shell_quote(client_command)
-            end
-          end
-
-          # Returns the version of the scm client
-          # Eg: [1, 5, 0] or [] if unknown
-          def client_version
-            []
-          end
-
-          # Returns the version string of the scm client
-          # Eg: '1.5.0' or 'Unknown version' if unknown
-          def client_version_string
-            v = client_version || 'Unknown version'
-            v.is_a?(Array) ? v.join('.') : v.to_s
-          end
-
-          # Returns true if the current client version is above
-          # or equals the given one
-          # If option is :unknown is set to true, it will return
-          # true if the client version is unknown
-          def client_version_above?(v, options={})
-            ((client_version <=> v) >= 0) || (client_version.empty? && options[:unknown])
-          end
-
-          def client_available
-            true
-          end
-
-          def shell_quote(str)
-            if Redmine::Platform.mswin?
-              '"' + str.gsub(/"/, '\\"') + '"'
-            else
-              "'" + str.gsub(/'/, "'\"'\"'") + "'"
-            end
-          end
-        end
-
-        def initialize(url, root_url=nil, login=nil, password=nil,
-                       path_encoding=nil)
-          @url = url
-          @login = login if login && !login.empty?
-          @password = (password || "") if @login
-          @root_url = root_url.blank? ? retrieve_root_url : root_url
-        end
-
-        def adapter_name
-          'Abstract'
-        end
-
-        def supports_cat?
-          true
-        end
-
-        def supports_annotate?
-          respond_to?('annotate')
-        end
-
-        def root_url
-          @root_url
-        end
-
-        def url
-          @url
-        end
-
-        def path_encoding
-          nil
-        end
-
-        # get info about the svn repository
-        def info
-          return nil
-        end
-
-        # Returns the entry identified by path and revision identifier
-        # or nil if entry doesn't exist in the repository
-        def entry(path=nil, identifier=nil)
-          parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
-          search_path = parts[0..-2].join('/')
-          search_name = parts[-1]
-          if search_path.blank? && search_name.blank?
-            # Root entry
-            Entry.new(:path => '', :kind => 'dir')
-          else
-            # Search for the entry in the parent directory
-            es = entries(search_path, identifier)
-            es ? es.detect {|e| e.name == search_name} : nil
-          end
-        end
-
-        # Returns an Entries collection
-        # or nil if the given path doesn't exist in the repository
-        def entries(path=nil, identifier=nil, options={})
-          return nil
-        end
-
-        def branches
-          return nil
-        end
-
-        def tags
-          return nil
-        end
-
-        def default_branch
-          return nil
-        end
-
-        def properties(path, identifier=nil)
-          return nil
-        end
-
-        def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
-          return nil
-        end
-
-        def diff(path, identifier_from, identifier_to=nil)
-          return nil
-        end
-
-        def cat(path, identifier=nil)
-          return nil
-        end
-
-        def with_leading_slash(path)
-          path ||= ''
-          (path[0,1]!="/") ? "/#{path}" : path
-        end
-
-        def with_trailling_slash(path)
-          path ||= ''
-          (path[-1,1] == "/") ? path : "#{path}/"
-        end
-
-        def without_leading_slash(path)
-          path ||= ''
-          path.gsub(%r{^/+}, '')
-        end
-
-        def without_trailling_slash(path)
-          path ||= ''
-          (path[-1,1] == "/") ? path[0..-2] : path
-         end
-
-        def shell_quote(str)
-          self.class.shell_quote(str)
-        end
-
-      private
-        def retrieve_root_url
-          info = self.info
-          info ? info.root_url : nil
-        end
-
-        def target(path, sq=true)
-          path ||= ''
-          base = path.match(/^\//) ? root_url : url
-          str = "#{base}/#{path}".gsub(/[?<>\*]/, '')
-          if sq
-            str = shell_quote(str)
-          end
-          str
-        end
-
-        def logger
-          self.class.logger
-        end
-
-        def shellout(cmd, options = {}, &block)
-          self.class.shellout(cmd, options, &block)
-        end
-
-        def self.logger
-          Rails.logger
-        end
-
-        # Path to the file where scm stderr output is logged
-        # Returns nil if the log file is not writable
-        def self.stderr_log_file
-          if @stderr_log_file.nil?
-            writable = false
-            path = Redmine::Configuration['scm_stderr_log_file'].presence
-            path ||= Rails.root.join("log/#{Rails.env}.scm.stderr.log").to_s
-            if File.exists?(path)
-              if File.file?(path) && File.writable?(path) 
-                writable = true
-              else
-                logger.warn("SCM log file (#{path}) is not writable")
-              end
-            else
-              begin
-                File.open(path, "w") {}
-                writable = true
-              rescue => e
-                logger.warn("SCM log file (#{path}) cannot be created: #{e.message}")
-              end
-            end
-            @stderr_log_file = writable ? path : false
-          end
-          @stderr_log_file || nil
-        end
-
-        def self.shellout(cmd, options = {}, &block)
-          if logger && logger.debug?
-            logger.debug "Shelling out: #{strip_credential(cmd)}"
-            # Capture stderr in a log file
-            if stderr_log_file
-              cmd = "#{cmd} 2>>#{shell_quote(stderr_log_file)}"
-            end
-          end
-          begin
-            mode = "r+"
-            IO.popen(cmd, mode) do |io|
-              io.set_encoding("ASCII-8BIT") if io.respond_to?(:set_encoding)
-              io.close_write unless options[:write_stdin]
-              block.call(io) if block_given?
-            end
-          ## If scm command does not exist,
-          ## Linux JRuby 1.6.2 (ruby-1.8.7-p330) raises java.io.IOException
-          ## in production environment.
-          # rescue Errno::ENOENT => e
-          rescue Exception => e
-            msg = strip_credential(e.message)
-            # The command failed, log it and re-raise
-            logmsg = "SCM command failed, "
-            logmsg += "make sure that your SCM command (e.g. svn) is "
-            logmsg += "in PATH (#{ENV['PATH']})\n"
-            logmsg += "You can configure your scm commands in config/configuration.yml.\n"
-            logmsg += "#{strip_credential(cmd)}\n"
-            logmsg += "with: #{msg}"
-            logger.error(logmsg)
-            raise CommandFailed.new(msg)
-          end
-        end
-
-        # Hides username/password in a given command
-        def self.strip_credential(cmd)
-          q = (Redmine::Platform.mswin? ? '"' : "'")
-          cmd.to_s.gsub(/(\-\-(password|username))\s+(#{q}[^#{q}]+#{q}|[^#{q}]\S+)/, '\\1 xxxx')
-        end
-
-        def strip_credential(cmd)
-          self.class.strip_credential(cmd)
-        end
-
-        def scm_iconv(to, from, str)
-          return nil if str.nil?
-          return str if to == from
-          if str.respond_to?(:force_encoding)
-            str.force_encoding(from)
-            begin
-              str.encode(to)
-            rescue Exception => err
-              logger.error("failed to convert from #{from} to #{to}. #{err}")
-              nil
-            end
-          else
-            begin
-              Iconv.conv(to, from, str)
-            rescue Iconv::Failure => err
-              logger.error("failed to convert from #{from} to #{to}. #{err}")
-              nil
-            end
-          end
-        end
-
-        def parse_xml(xml)
-          if RUBY_PLATFORM == 'java'
-            xml = xml.sub(%r{<\?xml[^>]*\?>}, '')
-          end
-          ActiveSupport::XmlMini.parse(xml)
-        end
-      end
-
-      class Entries < Array
-        def sort_by_name
-          dup.sort! {|x,y|
-            if x.kind == y.kind
-              x.name.to_s <=> y.name.to_s
-            else
-              x.kind <=> y.kind
-            end
-          }
-        end
-
-        def revisions
-          revisions ||= Revisions.new(collect{|entry| entry.lastrev}.compact)
-        end
-      end
-
-      class Info
-        attr_accessor :root_url, :lastrev
-        def initialize(attributes={})
-          self.root_url = attributes[:root_url] if attributes[:root_url]
-          self.lastrev = attributes[:lastrev]
-        end
-      end
-
-      class Entry
-        attr_accessor :name, :path, :kind, :size, :lastrev, :changeset
-
-        def initialize(attributes={})
-          self.name = attributes[:name] if attributes[:name]
-          self.path = attributes[:path] if attributes[:path]
-          self.kind = attributes[:kind] if attributes[:kind]
-          self.size = attributes[:size].to_i if attributes[:size]
-          self.lastrev = attributes[:lastrev]
-        end
-
-        def is_file?
-          'file' == self.kind
-        end
-
-        def is_dir?
-          'dir' == self.kind
-        end
-
-        def is_text?
-          Redmine::MimeType.is_type?('text', name)
-        end
-
-        def author
-          if changeset
-            changeset.author.to_s
-          elsif lastrev
-            Redmine::CodesetUtil.replace_invalid_utf8(lastrev.author.to_s.split('<').first)
-          end
-        end
-      end
-
-      class Revisions < Array
-        def latest
-          sort {|x,y|
-            unless x.time.nil? or y.time.nil?
-              x.time <=> y.time
-            else
-              0
-            end
-          }.last
-        end
-      end
-
-      class Revision
-        attr_accessor :scmid, :name, :author, :time, :message,
-                      :paths, :revision, :branch, :identifier,
-                      :parents
-
-        def initialize(attributes={})
-          self.identifier = attributes[:identifier]
-          self.scmid      = attributes[:scmid]
-          self.name       = attributes[:name] || self.identifier
-          self.author     = attributes[:author]
-          self.time       = attributes[:time]
-          self.message    = attributes[:message] || ""
-          self.paths      = attributes[:paths]
-          self.revision   = attributes[:revision]
-          self.branch     = attributes[:branch]
-          self.parents    = attributes[:parents]
-        end
-
-        # Returns the readable identifier.
-        def format_identifier
-          self.identifier.to_s
-        end
-
-        def ==(other)
-          if other.nil?
-            false
-          elsif scmid.present?
-            scmid == other.scmid
-          elsif identifier.present?
-            identifier == other.identifier
-          elsif revision.present?
-            revision == other.revision
-          end
-        end
-      end
-
-      class Annotate
-        attr_reader :lines, :revisions
-
-        def initialize
-          @lines = []
-          @revisions = []
-        end
-
-        def add_line(line, revision)
-          @lines << line
-          @revisions << revision
-        end
-
-        def content
-          content = lines.join("\n")
-        end
-
-        def empty?
-          lines.empty?
-        end
-      end
-
-      class Branch < String
-        attr_accessor :revision, :scmid
-      end
-    end
-  end
-end
--- a/.svn/pristine/0b/0bd8b54775e82ba1bfa004993bdb8bf956e85c99.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class TimeEntryQuery < Query
-
-  self.queried_class = TimeEntry
-
-  self.available_columns = [
-    QueryColumn.new(:project, :sortable => "#{Project.table_name}.name", :groupable => true),
-    QueryColumn.new(:spent_on, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"], :default_order => 'desc', :groupable => true),
-    QueryColumn.new(:user, :sortable => lambda {User.fields_for_order_statement}, :groupable => true),
-    QueryColumn.new(:activity, :sortable => "#{TimeEntryActivity.table_name}.position", :groupable => true),
-    QueryColumn.new(:issue, :sortable => "#{Issue.table_name}.id"),
-    QueryColumn.new(:comments),
-    QueryColumn.new(:hours, :sortable => "#{TimeEntry.table_name}.hours"),
-  ]
-
-  def initialize(attributes=nil, *args)
-    super attributes
-    self.filters ||= {}
-    add_filter('spent_on', '*') unless filters.present?
-  end
-
-  def initialize_available_filters
-    add_available_filter "spent_on", :type => :date_past
-
-    principals = []
-    if project
-      principals += project.principals.sort
-      unless project.leaf?
-        subprojects = project.descendants.visible.all
-        if subprojects.any?
-          add_available_filter "subproject_id",
-            :type => :list_subprojects,
-            :values => subprojects.collect{|s| [s.name, s.id.to_s] }
-          principals += Principal.member_of(subprojects)
-        end
-      end
-    else
-      if all_projects.any?
-        # members of visible projects
-        principals += Principal.member_of(all_projects)
-        # project filter
-        project_values = []
-        if User.current.logged? && User.current.memberships.any?
-          project_values << ["<< #{l(:label_my_projects).downcase} >>", "mine"]
-        end
-        project_values += all_projects_values
-        add_available_filter("project_id",
-          :type => :list, :values => project_values
-        ) unless project_values.empty?
-      end
-    end
-    principals.uniq!
-    principals.sort!
-    users = principals.select {|p| p.is_a?(User)}
-
-    users_values = []
-    users_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
-    users_values += users.collect{|s| [s.name, s.id.to_s] }
-    add_available_filter("user_id",
-      :type => :list_optional, :values => users_values
-    ) unless users_values.empty?
-
-    activities = (project ? project.activities : TimeEntryActivity.shared.active)
-    add_available_filter("activity_id",
-      :type => :list, :values => activities.map {|a| [a.name, a.id.to_s]}
-    ) unless activities.empty?
-
-    add_available_filter "comments", :type => :text
-    add_available_filter "hours", :type => :float
-
-    add_custom_fields_filters(TimeEntryCustomField)
-    add_associations_custom_fields_filters :project, :issue, :user
-  end
-
-  def available_columns
-    return @available_columns if @available_columns
-    @available_columns = self.class.available_columns.dup
-    @available_columns += TimeEntryCustomField.visible.all.map {|cf| QueryCustomFieldColumn.new(cf) }
-    @available_columns += IssueCustomField.visible.all.map {|cf| QueryAssociationCustomFieldColumn.new(:issue, cf) }
-    @available_columns
-  end
-
-  def default_columns_names
-    @default_columns_names ||= [:project, :spent_on, :user, :activity, :issue, :comments, :hours]
-  end
-
-  def results_scope(options={})
-    order_option = [group_by_sort_order, options[:order]].flatten.reject(&:blank?)
-
-    TimeEntry.visible.
-      where(statement).
-      order(order_option).
-      joins(joins_for_order_statement(order_option.join(','))).
-      includes(:activity)
-  end
-
-  def sql_for_activity_id_field(field, operator, value)
-    condition_on_id = sql_for_field(field, operator, value, Enumeration.table_name, 'id')
-    condition_on_parent_id = sql_for_field(field, operator, value, Enumeration.table_name, 'parent_id')
-    ids = value.map(&:to_i).join(',')
-    table_name = Enumeration.table_name
-    if operator == '='
-      "(#{table_name}.id IN (#{ids}) OR #{table_name}.parent_id IN (#{ids}))"
-    else
-      "(#{table_name}.id NOT IN (#{ids}) AND (#{table_name}.parent_id IS NULL OR #{table_name}.parent_id NOT IN (#{ids})))"
-    end
-  end
-
-  # Accepts :from/:to params as shortcut filters
-  def build_from_params(params)
-    super
-    if params[:from].present? && params[:to].present?
-      add_filter('spent_on', '><', [params[:from], params[:to]])
-    elsif params[:from].present?
-      add_filter('spent_on', '>=', [params[:from]])
-    elsif params[:to].present?
-      add_filter('spent_on', '<=', [params[:to]])
-    end
-    self
-  end
-end
--- a/.svn/pristine/0c/0ca7bda81025c5f7a9ebad14d8b0c08f3a0b8176.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingSysTest < ActionController::IntegrationTest
-  def test_sys
-    assert_routing(
-        { :method => 'get', :path => "/sys/projects" },
-        { :controller => 'sys', :action => 'projects' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/sys/projects/testid/repository" },
-        { :controller => 'sys', :action => 'create_project_repository', :id => 'testid' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/sys/fetch_changesets" },
-        { :controller => 'sys', :action => 'fetch_changesets' }
-      )
-  end
-end
--- a/.svn/pristine/0c/0cb5ab49f6fd89443044a7c2f37992f0e2874866.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-# Copyright (C) 2007  Patrick Aljord patcito@ŋmail.com
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/git_adapter'
-
-class Repository::Git < Repository
-  attr_protected :root_url
-  validates_presence_of :url
-
-  def self.human_attribute_name(attribute_key_name, *args)
-    attr_name = attribute_key_name.to_s
-    if attr_name == "url"
-      attr_name = "path_to_repository"
-    end
-    super(attr_name, *args)
-  end
-
-  def self.scm_adapter_class
-    Redmine::Scm::Adapters::GitAdapter
-  end
-
-  def self.scm_name
-    'Git'
-  end
-
-  def report_last_commit
-    extra_report_last_commit
-  end
-
-  def extra_report_last_commit
-    return false if extra_info.nil?
-    v = extra_info["extra_report_last_commit"]
-    return false if v.nil?
-    v.to_s != '0'
-  end
-
-  def supports_directory_revisions?
-    true
-  end
-
-  def supports_revision_graph?
-    true
-  end
-
-  def repo_log_encoding
-    'UTF-8'
-  end
-
-  # Returns the identifier for the given git changeset
-  def self.changeset_identifier(changeset)
-    changeset.scmid
-  end
-
-  # Returns the readable identifier for the given git changeset
-  def self.format_changeset_identifier(changeset)
-    changeset.revision[0, 8]
-  end
-
-  def branches
-    scm.branches
-  end
-
-  def tags
-    scm.tags
-  end
-
-  def default_branch
-    scm.default_branch
-  rescue Exception => e
-    logger.error "git: error during get default branch: #{e.message}"
-    nil
-  end
-
-  def find_changeset_by_name(name)
-    if name.present?
-      changesets.where(:revision => name.to_s).first ||
-        changesets.where('scmid LIKE ?', "#{name}%").first
-    end
-  end
-
-  def entries(path=nil, identifier=nil)
-    entries = scm.entries(path, identifier, :report_last_commit => extra_report_last_commit)
-    load_entries_changesets(entries)
-    entries
-  end
-
-  # With SCMs that have a sequential commit numbering,
-  # such as Subversion and Mercurial,
-  # Redmine is able to be clever and only fetch changesets
-  # going forward from the most recent one it knows about.
-  #
-  # However, Git does not have a sequential commit numbering.
-  #
-  # In order to fetch only new adding revisions,
-  # Redmine needs to save "heads".
-  #
-  # In Git and Mercurial, revisions are not in date order.
-  # Redmine Mercurial fixed issues.
-  #    * Redmine Takes Too Long On Large Mercurial Repository
-  #      http://www.redmine.org/issues/3449
-  #    * Sorting for changesets might go wrong on Mercurial repos
-  #      http://www.redmine.org/issues/3567
-  #
-  # Database revision column is text, so Redmine can not sort by revision.
-  # Mercurial has revision number, and revision number guarantees revision order.
-  # Redmine Mercurial model stored revisions ordered by database id to database.
-  # So, Redmine Mercurial model can use correct ordering revisions.
-  #
-  # Redmine Mercurial adapter uses "hg log -r 0:tip --limit 10"
-  # to get limited revisions from old to new.
-  # But, Git 1.7.3.4 does not support --reverse with -n or --skip.
-  #
-  # The repository can still be fully reloaded by calling #clear_changesets
-  # before fetching changesets (eg. for offline resync)
-  def fetch_changesets
-    scm_brs = branches
-    return if scm_brs.nil? || scm_brs.empty?
-
-    h1 = extra_info || {}
-    h  = h1.dup
-    repo_heads = scm_brs.map{ |br| br.scmid }
-    h["heads"] ||= []
-    prev_db_heads = h["heads"].dup
-    if prev_db_heads.empty?
-      prev_db_heads += heads_from_branches_hash
-    end
-    return if prev_db_heads.sort == repo_heads.sort
-
-    h["db_consistent"]  ||= {}
-    if changesets.count == 0
-      h["db_consistent"]["ordering"] = 1
-      merge_extra_info(h)
-      self.save
-    elsif ! h["db_consistent"].has_key?("ordering")
-      h["db_consistent"]["ordering"] = 0
-      merge_extra_info(h)
-      self.save
-    end
-    save_revisions(prev_db_heads, repo_heads)
-  end
-
-  def save_revisions(prev_db_heads, repo_heads)
-    h = {}
-    opts = {}
-    opts[:reverse]  = true
-    opts[:excludes] = prev_db_heads
-    opts[:includes] = repo_heads
-
-    revisions = scm.revisions('', nil, nil, opts)
-    return if revisions.blank?
-
-    # Make the search for existing revisions in the database in a more sufficient manner
-    #
-    # Git branch is the reference to the specific revision.
-    # Git can *delete* remote branch and *re-push* branch.
-    #
-    #  $ git push remote :branch
-    #  $ git push remote branch
-    #
-    # After deleting branch, revisions remain in repository until "git gc".
-    # On git 1.7.2.3, default pruning date is 2 weeks.
-    # So, "git log --not deleted_branch_head_revision" return code is 0.
-    #
-    # After re-pushing branch, "git log" returns revisions which are saved in database.
-    # So, Redmine needs to scan revisions and database every time.
-    #
-    # This is replacing the one-after-one queries.
-    # Find all revisions, that are in the database, and then remove them from the revision array.
-    # Then later we won't need any conditions for db existence.
-    # Query for several revisions at once, and remove them from the revisions array, if they are there.
-    # Do this in chunks, to avoid eventual memory problems (in case of tens of thousands of commits).
-    # If there are no revisions (because the original code's algorithm filtered them),
-    # then this part will be stepped over.
-    # We make queries, just if there is any revision.
-    limit = 100
-    offset = 0
-    revisions_copy = revisions.clone # revisions will change
-    while offset < revisions_copy.size
-      scmids = revisions_copy.slice(offset, limit).map{|x| x.scmid}
-      recent_changesets_slice = changesets.where(:scmid => scmids).all
-      # Subtract revisions that redmine already knows about
-      recent_revisions = recent_changesets_slice.map{|c| c.scmid}
-      revisions.reject!{|r| recent_revisions.include?(r.scmid)}
-      offset += limit
-    end
-
-    revisions.each do |rev|
-      transaction do
-        # There is no search in the db for this revision, because above we ensured,
-        # that it's not in the db.
-        save_revision(rev)
-      end
-    end
-    h["heads"] = repo_heads.dup
-    merge_extra_info(h)
-    self.save
-  end
-  private :save_revisions
-
-  def save_revision(rev)
-    parents = (rev.parents || []).collect{|rp| find_changeset_by_name(rp)}.compact
-    changeset = Changeset.create(
-              :repository   => self,
-              :revision     => rev.identifier,
-              :scmid        => rev.scmid,
-              :committer    => rev.author,
-              :committed_on => rev.time,
-              :comments     => rev.message,
-              :parents      => parents
-              )
-    unless changeset.new_record?
-      rev.paths.each { |change| changeset.create_change(change) }
-    end
-    changeset
-  end
-  private :save_revision
-
-  def heads_from_branches_hash
-    h1 = extra_info || {}
-    h  = h1.dup
-    h["branches"] ||= {}
-    h['branches'].map{|br, hs| hs['last_scmid']}
-  end
-
-  def latest_changesets(path,rev,limit=10)
-    revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false)
-    return [] if revisions.nil? || revisions.empty?
-
-    changesets.where(:scmid => revisions.map {|c| c.scmid}).all
-  end
-
-  def clear_extra_info_of_changesets
-    return if extra_info.nil?
-    v = extra_info["extra_report_last_commit"]
-    write_attribute(:extra_info, nil)
-    h = {}
-    h["extra_report_last_commit"] = v
-    merge_extra_info(h)
-    self.save
-  end
-  private :clear_extra_info_of_changesets
-end
--- a/.svn/pristine/0c/0cc9601ec1a6e3a27ab4a946d394cf4ba82254b4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class TimeEntryActivityCustomField < CustomField
-  def type_name
-    :enumeration_activities
-  end
-end
--- a/.svn/pristine/0e/0e9c8f11b3db41702079f085c94dfa01133abcd9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class PdfTest < ActiveSupport::TestCase
-  fixtures :users, :projects, :roles, :members, :member_roles,
-           :enabled_modules, :issues, :trackers, :attachments
-
-  def test_fix_text_encoding_nil
-    assert_equal '', Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(nil, "UTF-8")
-    assert_equal '', Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(nil, "ISO-8859-1")
-  end
-
-  def test_rdm_pdf_iconv_cannot_convert_ja_cp932
-    encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
-    utf8_txt_1  = "\xe7\x8b\x80\xe6\x85\x8b"
-    utf8_txt_2  = "\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"
-    utf8_txt_3  = "\xe7\x8b\x80\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"
-    if utf8_txt_1.respond_to?(:force_encoding)
-      txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
-      txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
-      txt_3 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
-      assert_equal "?\x91\xd4".force_encoding("ASCII-8BIT"), txt_1
-      assert_equal "?\x91\xd4?".force_encoding("ASCII-8BIT"), txt_2
-      assert_equal "??\x91\xd4?".force_encoding("ASCII-8BIT"), txt_3
-      assert_equal "ASCII-8BIT", txt_1.encoding.to_s
-      assert_equal "ASCII-8BIT", txt_2.encoding.to_s
-      assert_equal "ASCII-8BIT", txt_3.encoding.to_s
-    elsif RUBY_PLATFORM == 'java'
-      assert_equal "??",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
-      assert_equal "???",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
-      assert_equal "????",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
-    else
-      assert_equal "???\x91\xd4",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
-      assert_equal "???\x91\xd4???",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
-      assert_equal "??????\x91\xd4???",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
-    end
-  end
-
-  def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_en
-    str1 = "Texte encod\xe9 en ISO-8859-1"
-    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
-    str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
-    txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, 'UTF-8')
-    txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, 'UTF-8')
-    if txt_1.respond_to?(:force_encoding)
-      assert_equal "ASCII-8BIT", txt_1.encoding.to_s
-      assert_equal "ASCII-8BIT", txt_2.encoding.to_s
-    end
-    assert_equal "Texte encod? en ISO-8859-1", txt_1
-    assert_equal "?a?b?c?d?e test", txt_2
-  end
-
-  def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_ja
-    str1 = "Texte encod\xe9 en ISO-8859-1"
-    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
-    str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
-    encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
-    txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, encoding)
-    txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, encoding)
-    if txt_1.respond_to?(:force_encoding)
-      assert_equal "ASCII-8BIT", txt_1.encoding.to_s
-      assert_equal "ASCII-8BIT", txt_2.encoding.to_s
-    end
-    assert_equal "Texte encod? en ISO-8859-1", txt_1
-    assert_equal "?a?b?c?d?e test", txt_2
-  end
-
-  def test_attach
-    set_fixtures_attachments_directory
-
-    str2 = "\x83e\x83X\x83g"
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
-    encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
-
-    a1 = Attachment.find(17)
-    a2 = Attachment.find(19)
-
-    User.current = User.find(1)
-    assert a1.readable?
-    assert a1.visible?
-    assert a2.readable?
-    assert a2.visible?
-
-    aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
-    assert_not_nil aa1
-    assert_equal 17, aa1.id
-    aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
-    assert_not_nil aa2
-    assert_equal 19, aa2.id
-
-    User.current = nil
-    assert a1.readable?
-    assert (! a1.visible?)
-    assert a2.readable?
-    assert (! a2.visible?)
-
-    aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
-    assert_equal nil, aa1
-    aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
-    assert_equal nil, aa2
-
-    set_tmp_attachments_directory
-  end
-end
--- a/.svn/pristine/0f/0fc81c2978046c22ad1fddeadeabe4e288474193.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesBazaarControllerTest < ActionController::TestCase
-  tests RepositoriesController
-
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :repositories, :enabled_modules
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
-  REPOSITORY_PATH_TRUNK = File.join(REPOSITORY_PATH, "trunk")
-  PRJ_ID = 3
-  CHAR_1_UTF8_HEX   = "\xc3\x9c"
-
-  def setup
-    User.current = nil
-    @project = Project.find(PRJ_ID)
-    @repository = Repository::Bazaar.create(
-                    :project      => @project,
-                    :url          => REPOSITORY_PATH_TRUNK,
-                    :log_encoding => 'UTF-8')
-    assert @repository
-    @char_1_utf8 = CHAR_1_UTF8_HEX.dup
-    if @char_1_utf8.respond_to?(:force_encoding)
-      @char_1_utf8.force_encoding('UTF-8')
-    end
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    def test_get_new
-      @request.session[:user_id] = 1
-      @project.repository.destroy
-      get :new, :project_id => 'subproject1', :repository_scm => 'Bazaar'
-      assert_response :success
-      assert_template 'new'
-      assert_kind_of Repository::Bazaar, assigns(:repository)
-      assert assigns(:repository).new_record?
-    end
-
-    def test_browse_root
-      get :show, :id => PRJ_ID
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal 2, assigns(:entries).size
-      assert assigns(:entries).detect {|e| e.name == 'directory' && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'doc-mkdir.txt' && e.kind == 'file'}
-    end
-
-    def test_browse_directory
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['directory'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['doc-ls.txt', 'document.txt', 'edit.png'], assigns(:entries).collect(&:name)
-      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
-      assert_not_nil entry
-      assert_equal 'file', entry.kind
-      assert_equal 'directory/edit.png', entry.path
-    end
-
-    def test_browse_at_given_revision
-      get :show, :id => PRJ_ID, :path => repository_path_hash([])[:param],
-          :rev => 3
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['directory', 'doc-deleted.txt', 'doc-ls.txt', 'doc-mkdir.txt'],
-                   assigns(:entries).collect(&:name)
-    end
-
-    def test_changes
-      get :changes, :id => PRJ_ID,
-          :path => repository_path_hash(['doc-mkdir.txt'])[:param]
-      assert_response :success
-      assert_template 'changes'
-      assert_tag :tag => 'h2', :content => 'doc-mkdir.txt'
-    end
-
-    def test_entry_show
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['directory', 'doc-ls.txt'])[:param]
-      assert_response :success
-      assert_template 'entry'
-      # Line 19
-      assert_tag :tag => 'th',
-                 :content => /29/,
-                 :attributes => { :class => /line-num/ },
-                 :sibling => { :tag => 'td', :content => /Show help message/ }
-    end
-
-    def test_entry_download
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['directory', 'doc-ls.txt'])[:param],
-          :format => 'raw'
-      assert_response :success
-      # File content
-      assert @response.body.include?('Show help message')
-    end
-
-    def test_directory_entry
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['directory'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entry)
-      assert_equal 'directory', assigns(:entry).name
-    end
-
-    def test_diff
-      # Full diff of changeset 3
-      ['inline', 'sbs'].each do |dt|
-        get :diff, :id => PRJ_ID, :rev => 3, :type => dt
-        assert_response :success
-        assert_template 'diff'
-        # Line 11 removed
-        assert_tag :tag => 'th',
-                   :content => '11',
-                   :sibling => { :tag => 'td',
-                                 :attributes => { :class => /diff_out/ },
-                                 :content => /Display more information/ }
-      end
-    end
-
-    def test_annotate
-      get :annotate, :id => PRJ_ID,
-          :path => repository_path_hash(['doc-mkdir.txt'])[:param]
-      assert_response :success
-      assert_template 'annotate'
-      assert_select "th.line-num", :text => '2' do
-        assert_select "+ td.revision" do
-          assert_select "a", :text => '3'
-          assert_select "+ td.author", :text => "jsmith@" do
-            assert_select "+ td",
-                          :text => "Main purpose:"
-          end
-        end
-      end
-    end
-
-    def test_annotate_author_escaping
-      repository = Repository::Bazaar.create(
-                    :project      => @project,
-                    :url          => File.join(REPOSITORY_PATH, "author_escaping"),
-                    :identifier => 'author_escaping',
-                    :log_encoding => 'UTF-8')
-      assert repository
-      get :annotate, :id => PRJ_ID, :repository_id => 'author_escaping',
-          :path => repository_path_hash(['author-escaping-test.txt'])[:param]
-      assert_response :success
-      assert_template 'annotate'
-      assert_select "th.line-num", :text => '1' do
-        assert_select "+ td.revision" do
-          assert_select "a", :text => '2'
-          assert_select "+ td.author", :text => "test &amp;" do
-            assert_select "+ td",
-                          :text => "author escaping test"
-          end
-        end
-      end
-    end
-
-    if REPOSITORY_PATH.respond_to?(:force_encoding)
-      def test_annotate_author_non_ascii
-        log_encoding = nil
-        if Encoding.locale_charmap == "UTF-8" ||
-             Encoding.locale_charmap == "ISO-8859-1"
-          log_encoding = Encoding.locale_charmap
-        end
-        unless log_encoding.nil?
-          repository = Repository::Bazaar.create(
-                        :project      => @project,
-                        :url          => File.join(REPOSITORY_PATH, "author_non_ascii"),
-                        :identifier => 'author_non_ascii',
-                        :log_encoding => log_encoding)
-          assert repository
-          get :annotate, :id => PRJ_ID, :repository_id => 'author_non_ascii',
-              :path => repository_path_hash(['author-non-ascii-test.txt'])[:param]
-          assert_response :success
-          assert_template 'annotate'
-          assert_select "th.line-num", :text => '1' do
-            assert_select "+ td.revision" do
-              assert_select "a", :text => '2'
-              assert_select "+ td.author", :text => "test #{@char_1_utf8}" do
-                assert_select "+ td",
-                              :text => "author non ASCII test"
-              end
-            end
-          end
-        end
-      end
-    end
-
-    def test_destroy_valid_repository
-      @request.session[:user_id] = 1 # admin
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      assert @repository.changesets.count > 0
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-
-    def test_destroy_invalid_repository
-      @request.session[:user_id] = 1 # admin
-      @project.repository.destroy
-      @repository = Repository::Bazaar.create!(
-                    :project      => @project,
-                    :url          => "/invalid",
-                    :log_encoding => 'UTF-8')
-      @repository.fetch_changesets
-      @repository.reload
-      assert_equal 0, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-  else
-    puts "Bazaar test repository NOT FOUND. Skipping functional tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/11/11276ad92ab446760ef27dc63e4ad98666e8240c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingAccountTest < ActionController::IntegrationTest
-  def test_account
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/login" },
-          { :controller => 'account', :action => 'login' }
-        )
-    end
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/logout" },
-          { :controller => 'account', :action => 'logout' }
-        )
-    end
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/account/register" },
-          { :controller => 'account', :action => 'register' }
-        )
-    end
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/account/lost_password" },
-          { :controller => 'account', :action => 'lost_password' }
-        )
-    end
-    assert_routing(
-        { :method => 'get', :path => "/account/activate" },
-        { :controller => 'account', :action => 'activate' }
-      )
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/11/11c16631f55588a98678a93f0bb375404c2e534c.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,33 @@
+# Settings specified here will take precedence over those in config/application.rb
+RedmineApp::Application.configure do
+  # The production environment is meant for finished, "live" apps.
+  # Code is not reloaded between requests
+  config.cache_classes = true
+
+  #####
+  # Customize the default logger
+  # http://www.ruby-doc.org/stdlib-1.8.7/libdoc/logger/rdoc/Logger.html
+  #
+  # Use a different logger for distributed setups
+  # config.logger        = SyslogLogger.new
+  #
+  # Rotate logs bigger than 1MB, keeps no more than 7 rotated logs around.
+  # When setting a new Logger, make sure to set it's log level too.
+  #
+  # config.logger = Logger.new(config.log_path, 7, 1048576)
+  # config.logger.level = Logger::INFO
+
+  # Full error reports are disabled and caching is turned on
+  config.action_controller.perform_caching = true
+
+  # Enable serving of images, stylesheets, and javascripts from an asset server
+  # config.action_controller.asset_host                  = "http://assets.example.com"
+
+  # Disable delivery errors if you bad email addresses should just be ignored
+  config.action_mailer.raise_delivery_errors = false
+
+  # No email in production log
+  config.action_mailer.logger = nil
+
+  config.active_support.deprecation = :log
+end
--- a/.svn/pristine/12/120840d537ad68f417065b102e2763e8f985fe62.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class MembersController < ApplicationController
-  model_object Member
-  before_filter :find_model_object, :except => [:index, :create, :autocomplete]
-  before_filter :find_project_from_association, :except => [:index, :create, :autocomplete]
-  before_filter :find_project_by_project_id, :only => [:index, :create, :autocomplete]
-  before_filter :authorize
-  accept_api_auth :index, :show, :create, :update, :destroy
-
-  def index
-    @offset, @limit = api_offset_and_limit
-    @member_count = @project.member_principals.count
-    @member_pages = Paginator.new @member_count, @limit, params['page']
-    @offset ||= @member_pages.offset
-    @members =  @project.member_principals.all(
-      :order => "#{Member.table_name}.id",
-      :limit  =>  @limit,
-      :offset =>  @offset
-    )
-
-    respond_to do |format|
-      format.html { head 406 }
-      format.api
-    end
-  end
-
-  def show
-    respond_to do |format|
-      format.html { head 406 }
-      format.api
-    end
-  end
-
-  def create
-    members = []
-    if params[:membership]
-      if params[:membership][:user_ids]
-        attrs = params[:membership].dup
-        user_ids = attrs.delete(:user_ids)
-        user_ids.each do |user_id|
-          members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => user_id)
-        end
-      else
-        members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => params[:membership][:user_id])
-      end
-      @project.members << members
-    end
-
-    respond_to do |format|
-      format.html { redirect_to_settings_in_projects }
-      format.js { @members = members }
-      format.api {
-        @member = members.first
-        if @member.valid?
-          render :action => 'show', :status => :created, :location => membership_url(@member)
-        else
-          render_validation_errors(@member)
-        end
-      }
-    end
-  end
-
-  def update
-    if params[:membership]
-      @member.role_ids = params[:membership][:role_ids]
-    end
-    saved = @member.save
-    respond_to do |format|
-      format.html { redirect_to_settings_in_projects }
-      format.js
-      format.api {
-        if saved
-          render_api_ok
-        else
-          render_validation_errors(@member)
-        end
-      }
-    end
-  end
-
-  def destroy
-    if request.delete? && @member.deletable?
-      @member.destroy
-    end
-    respond_to do |format|
-      format.html { redirect_to_settings_in_projects }
-      format.js
-      format.api {
-        if @member.destroyed?
-          render_api_ok
-        else
-          head :unprocessable_entity
-        end
-      }
-    end
-  end
-
-  def autocomplete
-    respond_to do |format|
-      format.js
-    end
-  end
-
-  private
-
-  def redirect_to_settings_in_projects
-    redirect_to settings_project_path(@project, :tab => 'members')
-  end
-end
--- a/.svn/pristine/13/134ab6c377c7865f7eab83c298719a41c97ec009.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AttachmentsTest < ActionController::IntegrationTest
-  fixtures :projects, :enabled_modules,
-           :users, :roles, :members, :member_roles,
-           :trackers, :projects_trackers,
-           :issue_statuses, :enumerations
-
-  def test_upload_as_js_and_attach_to_an_issue
-    log_user('jsmith', 'jsmith')
-
-    token = ajax_upload('myupload.txt', 'File content')
-
-    assert_difference 'Issue.count' do
-      post '/projects/ecookbook/issues', {
-          :issue => {:tracker_id => 1, :subject => 'Issue with upload'},
-          :attachments => {'1' => {:filename => 'myupload.txt', :description => 'My uploaded file', :token => token}}
-        }
-      assert_response 302
-    end
-
-    issue = Issue.order('id DESC').first
-    assert_equal 'Issue with upload', issue.subject
-    assert_equal 1, issue.attachments.count
-
-    attachment = issue.attachments.first
-    assert_equal 'myupload.txt', attachment.filename
-    assert_equal 'My uploaded file', attachment.description
-    assert_equal 'File content'.length, attachment.filesize
-  end
-
-  def test_upload_as_js_and_preview_as_inline_attachment
-    log_user('jsmith', 'jsmith')
-
-    token = ajax_upload('myupload.jpg', 'JPEG content')
-
-    post '/issues/preview/new/ecookbook', {
-        :issue => {:tracker_id => 1, :description => 'Inline upload: !myupload.jpg!'},
-        :attachments => {'1' => {:filename => 'myupload.jpg', :description => 'My uploaded file', :token => token}}
-      }
-    assert_response :success
-
-    attachment_path = response.body.match(%r{<img src="(/attachments/download/\d+/myupload.jpg)"})[1]
-    assert_not_nil token, "No attachment path found in response:\n#{response.body}"
-
-    get attachment_path
-    assert_response :success
-    assert_equal 'JPEG content', response.body
-  end
-
-  def test_upload_and_resubmit_after_validation_failure
-    log_user('jsmith', 'jsmith')
-
-    token = ajax_upload('myupload.txt', 'File content')
-
-    assert_no_difference 'Issue.count' do
-      post '/projects/ecookbook/issues', {
-          :issue => {:tracker_id => 1, :subject => ''},
-          :attachments => {'1' => {:filename => 'myupload.txt', :description => 'My uploaded file', :token => token}}
-        }
-      assert_response :success
-    end
-    assert_select 'input[type=hidden][name=?][value=?]', 'attachments[p0][token]', token
-    assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'myupload.txt'
-    assert_select 'input[name=?][value=?]', 'attachments[p0][description]', 'My uploaded file'
-
-    assert_difference 'Issue.count' do
-      post '/projects/ecookbook/issues', {
-          :issue => {:tracker_id => 1, :subject => 'Issue with upload'},
-          :attachments => {'p0' => {:filename => 'myupload.txt', :description => 'My uploaded file', :token => token}}
-        }
-      assert_response 302
-    end
-
-    issue = Issue.order('id DESC').first
-    assert_equal 'Issue with upload', issue.subject
-    assert_equal 1, issue.attachments.count
-
-    attachment = issue.attachments.first
-    assert_equal 'myupload.txt', attachment.filename
-    assert_equal 'My uploaded file', attachment.description
-    assert_equal 'File content'.length, attachment.filesize
-  end
-
-  def test_upload_as_js_and_destroy
-    log_user('jsmith', 'jsmith')
-
-    token = ajax_upload('myupload.txt', 'File content')
-
-    attachment = Attachment.order('id DESC').first
-    attachment_path = "/attachments/#{attachment.id}.js?attachment_id=1"
-    assert_include "href: '#{attachment_path}'", response.body, "Path to attachment: #{attachment_path} not found in response:\n#{response.body}"
-
-    assert_difference 'Attachment.count', -1 do
-      delete attachment_path
-      assert_response :success
-    end
-
-    assert_include "$('#attachments_1').remove();", response.body
-  end
-
-  private
-
-  def ajax_upload(filename, content, attachment_id=1)
-    assert_difference 'Attachment.count' do
-      post "/uploads.js?attachment_id=#{attachment_id}&filename=#{filename}", content, {"CONTENT_TYPE" => 'application/octet-stream'}
-      assert_response :success
-      assert_equal 'text/javascript', response.content_type
-    end
-
-    token = response.body.match(/\.val\('(\d+\.[0-9a-f]+)'\)/)[1]
-    assert_not_nil token, "No upload token found in response:\n#{response.body}"
-    token
-  end
-end
--- a/.svn/pristine/13/1398acbd60647babc95a74c09ce2afa2acef1b0b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-
-class Redmine::Views::Builders::JsonTest < ActiveSupport::TestCase
-
-  def test_hash
-    assert_json_output({'person' => {'name' => 'Ryan', 'age' => 32}}) do |b|
-      b.person do
-        b.name 'Ryan'
-        b.age  32
-      end
-    end
-  end
-
-  def test_hash_hash
-    assert_json_output({'person' => {'name' => 'Ryan', 'birth' => {'city' => 'London', 'country' => 'UK'}}}) do |b|
-      b.person do
-        b.name 'Ryan'
-        b.birth :city => 'London', :country => 'UK'
-      end
-    end
-
-    assert_json_output({'person' => {'id' => 1, 'name' => 'Ryan', 'birth' => {'city' => 'London', 'country' => 'UK'}}}) do |b|
-      b.person :id => 1 do
-        b.name 'Ryan'
-        b.birth :city => 'London', :country => 'UK'
-      end
-    end
-  end
-
-  def test_array
-    assert_json_output({'books' => [{'title' => 'Book 1', 'author' => 'B. Smith'}, {'title' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
-      b.array :books do |b|
-        b.book :title => 'Book 1', :author => 'B. Smith'
-        b.book :title => 'Book 2', :author => 'G. Cooper'
-      end
-    end
-
-    assert_json_output({'books' => [{'title' => 'Book 1', 'author' => 'B. Smith'}, {'title' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
-      b.array :books do |b|
-        b.book :title => 'Book 1' do
-          b.author 'B. Smith'
-        end
-        b.book :title => 'Book 2' do
-          b.author 'G. Cooper'
-        end
-      end
-    end
-  end
-
-  def test_array_with_content_tags
-    assert_json_output({'books' => [{'value' => 'Book 1', 'author' => 'B. Smith'}, {'value' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
-      b.array :books do |b|
-        b.book 'Book 1', :author => 'B. Smith'
-        b.book 'Book 2', :author => 'G. Cooper'
-      end
-    end
-  end
-
-  def test_nested_arrays
-    assert_json_output({'books' => [{'authors' => ['B. Smith', 'G. Cooper']}]}) do |b|
-      b.array :books do |books|
-        books.book do |book|
-          book.array :authors do |authors|
-            authors.author 'B. Smith'
-            authors.author 'G. Cooper'
-          end
-        end
-      end
-    end
-  end
-
-  def assert_json_output(expected, &block)
-    builder = Redmine::Views::Builders::Json.new(ActionDispatch::TestRequest.new, ActionDispatch::TestResponse.new)
-    block.call(builder)
-    assert_equal(expected, ActiveSupport::JSON.decode(builder.output))
-  end
-end
--- a/.svn/pristine/13/13e6190365f9e0ad8532e5e563cf7ad5676797a5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1044 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Project < ActiveRecord::Base
-  include Redmine::SafeAttributes
-
-  # Project statuses
-  STATUS_ACTIVE     = 1
-  STATUS_CLOSED     = 5
-  STATUS_ARCHIVED   = 9
-
-  # Maximum length for project identifiers
-  IDENTIFIER_MAX_LENGTH = 100
-
-  # Specific overidden Activities
-  has_many :time_entry_activities
-  has_many :members, :include => [:principal, :roles], :conditions => "#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE}"
-  has_many :memberships, :class_name => 'Member'
-  has_many :member_principals, :class_name => 'Member',
-                               :include => :principal,
-                               :conditions => "#{Principal.table_name}.type='Group' OR (#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE})"
-
-  has_many :enabled_modules, :dependent => :delete_all
-  has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
-  has_many :issues, :dependent => :destroy, :include => [:status, :tracker]
-  has_many :issue_changes, :through => :issues, :source => :journals
-  has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
-  has_many :time_entries, :dependent => :delete_all
-  has_many :queries, :class_name => 'IssueQuery', :dependent => :delete_all
-  has_many :documents, :dependent => :destroy
-  has_many :news, :dependent => :destroy, :include => :author
-  has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
-  has_many :boards, :dependent => :destroy, :order => "position ASC"
-  has_one :repository, :conditions => ["is_default = ?", true]
-  has_many :repositories, :dependent => :destroy
-  has_many :changesets, :through => :repository
-  has_one :wiki, :dependent => :destroy
-  # Custom field for the project issues
-  has_and_belongs_to_many :issue_custom_fields,
-                          :class_name => 'IssueCustomField',
-                          :order => "#{CustomField.table_name}.position",
-                          :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
-                          :association_foreign_key => 'custom_field_id'
-
-  acts_as_nested_set :order => 'name', :dependent => :destroy
-  acts_as_attachable :view_permission => :view_files,
-                     :delete_permission => :manage_files
-
-  acts_as_customizable
-  acts_as_searchable :columns => ['name', 'identifier', 'description'], :project_key => 'id', :permission => nil
-  acts_as_event :title => Proc.new {|o| "#{l(:label_project)}: #{o.name}"},
-                :url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o}},
-                :author => nil
-
-  attr_protected :status
-
-  validates_presence_of :name, :identifier
-  validates_uniqueness_of :identifier
-  validates_associated :repository, :wiki
-  validates_length_of :name, :maximum => 255
-  validates_length_of :homepage, :maximum => 255
-  validates_length_of :identifier, :in => 1..IDENTIFIER_MAX_LENGTH
-  # donwcase letters, digits, dashes but not digits only
-  validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :if => Proc.new { |p| p.identifier_changed? }
-  # reserved words
-  validates_exclusion_of :identifier, :in => %w( new )
-
-  after_save :update_position_under_parent, :if => Proc.new {|project| project.name_changed?}
-  after_save :update_inherited_members, :if => Proc.new {|project| project.inherit_members_changed?}
-  before_destroy :delete_all_members
-
-  scope :has_module, lambda {|mod|
-    where("#{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name=?)", mod.to_s)
-  }
-  scope :active, lambda { where(:status => STATUS_ACTIVE) }
-  scope :status, lambda {|arg| where(arg.blank? ? nil : {:status => arg.to_i}) }
-  scope :all_public, lambda { where(:is_public => true) }
-  scope :visible, lambda {|*args| where(Project.visible_condition(args.shift || User.current, *args)) }
-  scope :allowed_to, lambda {|*args|
-    user = User.current
-    permission = nil
-    if args.first.is_a?(Symbol)
-      permission = args.shift
-    else
-      user = args.shift
-      permission = args.shift
-    end
-    where(Project.allowed_to_condition(user, permission, *args))
-  }
-  scope :like, lambda {|arg|
-    if arg.blank?
-      where(nil)
-    else
-      pattern = "%#{arg.to_s.strip.downcase}%"
-      where("LOWER(identifier) LIKE :p OR LOWER(name) LIKE :p", :p => pattern)
-    end
-  }
-
-  def initialize(attributes=nil, *args)
-    super
-
-    initialized = (attributes || {}).stringify_keys
-    if !initialized.key?('identifier') && Setting.sequential_project_identifiers?
-      self.identifier = Project.next_identifier
-    end
-    if !initialized.key?('is_public')
-      self.is_public = Setting.default_projects_public?
-    end
-    if !initialized.key?('enabled_module_names')
-      self.enabled_module_names = Setting.default_projects_modules
-    end
-    if !initialized.key?('trackers') && !initialized.key?('tracker_ids')
-      default = Setting.default_projects_tracker_ids
-      if default.is_a?(Array)
-        self.trackers = Tracker.where(:id => default.map(&:to_i)).sorted.all
-      else
-        self.trackers = Tracker.sorted.all
-      end
-    end
-  end
-
-  def identifier=(identifier)
-    super unless identifier_frozen?
-  end
-
-  def identifier_frozen?
-    errors[:identifier].blank? && !(new_record? || identifier.blank?)
-  end
-
-  # returns latest created projects
-  # non public projects will be returned only if user is a member of those
-  def self.latest(user=nil, count=5)
-    visible(user).limit(count).order("created_on DESC").all
-  end
-
-  # Returns true if the project is visible to +user+ or to the current user.
-  def visible?(user=User.current)
-    user.allowed_to?(:view_project, self)
-  end
-
-  # Returns a SQL conditions string used to find all projects visible by the specified user.
-  #
-  # Examples:
-  #   Project.visible_condition(admin)        => "projects.status = 1"
-  #   Project.visible_condition(normal_user)  => "((projects.status = 1) AND (projects.is_public = 1 OR projects.id IN (1,3,4)))"
-  #   Project.visible_condition(anonymous)    => "((projects.status = 1) AND (projects.is_public = 1))"
-  def self.visible_condition(user, options={})
-    allowed_to_condition(user, :view_project, options)
-  end
-
-  # Returns a SQL conditions string used to find all projects for which +user+ has the given +permission+
-  #
-  # Valid options:
-  # * :project => limit the condition to project
-  # * :with_subprojects => limit the condition to project and its subprojects
-  # * :member => limit the condition to the user projects
-  def self.allowed_to_condition(user, permission, options={})
-    perm = Redmine::AccessControl.permission(permission)
-    base_statement = (perm && perm.read? ? "#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED}" : "#{Project.table_name}.status = #{Project::STATUS_ACTIVE}")
-    if perm && perm.project_module
-      # If the permission belongs to a project module, make sure the module is enabled
-      base_statement << " AND #{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name='#{perm.project_module}')"
-    end
-    if options[:project]
-      project_statement = "#{Project.table_name}.id = #{options[:project].id}"
-      project_statement << " OR (#{Project.table_name}.lft > #{options[:project].lft} AND #{Project.table_name}.rgt < #{options[:project].rgt})" if options[:with_subprojects]
-      base_statement = "(#{project_statement}) AND (#{base_statement})"
-    end
-
-    if user.admin?
-      base_statement
-    else
-      statement_by_role = {}
-      unless options[:member]
-        role = user.builtin_role
-        if role.allowed_to?(permission)
-          statement_by_role[role] = "#{Project.table_name}.is_public = #{connection.quoted_true}"
-        end
-      end
-      if user.logged?
-        user.projects_by_role.each do |role, projects|
-          if role.allowed_to?(permission) && projects.any?
-            statement_by_role[role] = "#{Project.table_name}.id IN (#{projects.collect(&:id).join(',')})"
-          end
-        end
-      end
-      if statement_by_role.empty?
-        "1=0"
-      else
-        if block_given?
-          statement_by_role.each do |role, statement|
-            if s = yield(role, user)
-              statement_by_role[role] = "(#{statement} AND (#{s}))"
-            end
-          end
-        end
-        "((#{base_statement}) AND (#{statement_by_role.values.join(' OR ')}))"
-      end
-    end
-  end
-
-  def principals
-    @principals ||= Principal.active.joins(:members).where("#{Member.table_name}.project_id = ?", id).uniq
-  end
-
-  def users
-    @users ||= User.active.joins(:members).where("#{Member.table_name}.project_id = ?", id).uniq
-  end
-
-  # Returns the Systemwide and project specific activities
-  def activities(include_inactive=false)
-    if include_inactive
-      return all_activities
-    else
-      return active_activities
-    end
-  end
-
-  # Will create a new Project specific Activity or update an existing one
-  #
-  # This will raise a ActiveRecord::Rollback if the TimeEntryActivity
-  # does not successfully save.
-  def update_or_create_time_entry_activity(id, activity_hash)
-    if activity_hash.respond_to?(:has_key?) && activity_hash.has_key?('parent_id')
-      self.create_time_entry_activity_if_needed(activity_hash)
-    else
-      activity = project.time_entry_activities.find_by_id(id.to_i)
-      activity.update_attributes(activity_hash) if activity
-    end
-  end
-
-  # Create a new TimeEntryActivity if it overrides a system TimeEntryActivity
-  #
-  # This will raise a ActiveRecord::Rollback if the TimeEntryActivity
-  # does not successfully save.
-  def create_time_entry_activity_if_needed(activity)
-    if activity['parent_id']
-
-      parent_activity = TimeEntryActivity.find(activity['parent_id'])
-      activity['name'] = parent_activity.name
-      activity['position'] = parent_activity.position
-
-      if Enumeration.overridding_change?(activity, parent_activity)
-        project_activity = self.time_entry_activities.create(activity)
-
-        if project_activity.new_record?
-          raise ActiveRecord::Rollback, "Overridding TimeEntryActivity was not successfully saved"
-        else
-          self.time_entries.update_all("activity_id = #{project_activity.id}", ["activity_id = ?", parent_activity.id])
-        end
-      end
-    end
-  end
-
-  # Returns a :conditions SQL string that can be used to find the issues associated with this project.
-  #
-  # Examples:
-  #   project.project_condition(true)  => "(projects.id = 1 OR (projects.lft > 1 AND projects.rgt < 10))"
-  #   project.project_condition(false) => "projects.id = 1"
-  def project_condition(with_subprojects)
-    cond = "#{Project.table_name}.id = #{id}"
-    cond = "(#{cond} OR (#{Project.table_name}.lft > #{lft} AND #{Project.table_name}.rgt < #{rgt}))" if with_subprojects
-    cond
-  end
-
-  def self.find(*args)
-    if args.first && args.first.is_a?(String) && !args.first.match(/^\d*$/)
-      project = find_by_identifier(*args)
-      raise ActiveRecord::RecordNotFound, "Couldn't find Project with identifier=#{args.first}" if project.nil?
-      project
-    else
-      super
-    end
-  end
-
-  def self.find_by_param(*args)
-    self.find(*args)
-  end
-
-  alias :base_reload :reload
-  def reload(*args)
-    @principals = nil
-    @users = nil
-    @shared_versions = nil
-    @rolled_up_versions = nil
-    @rolled_up_trackers = nil
-    @all_issue_custom_fields = nil
-    @all_time_entry_custom_fields = nil
-    @to_param = nil
-    @allowed_parents = nil
-    @allowed_permissions = nil
-    @actions_allowed = nil
-    @start_date = nil
-    @due_date = nil
-    base_reload(*args)
-  end
-
-  def to_param
-    # id is used for projects with a numeric identifier (compatibility)
-    @to_param ||= (identifier.to_s =~ %r{^\d*$} ? id.to_s : identifier)
-  end
-
-  def active?
-    self.status == STATUS_ACTIVE
-  end
-
-  def archived?
-    self.status == STATUS_ARCHIVED
-  end
-
-  # Archives the project and its descendants
-  def archive
-    # Check that there is no issue of a non descendant project that is assigned
-    # to one of the project or descendant versions
-    v_ids = self_and_descendants.collect {|p| p.version_ids}.flatten
-    if v_ids.any? &&
-      Issue.
-        includes(:project).
-        where("#{Project.table_name}.lft < ? OR #{Project.table_name}.rgt > ?", lft, rgt).
-        where("#{Issue.table_name}.fixed_version_id IN (?)", v_ids).
-        exists?
-      return false
-    end
-    Project.transaction do
-      archive!
-    end
-    true
-  end
-
-  # Unarchives the project
-  # All its ancestors must be active
-  def unarchive
-    return false if ancestors.detect {|a| !a.active?}
-    update_attribute :status, STATUS_ACTIVE
-  end
-
-  def close
-    self_and_descendants.status(STATUS_ACTIVE).update_all :status => STATUS_CLOSED
-  end
-
-  def reopen
-    self_and_descendants.status(STATUS_CLOSED).update_all :status => STATUS_ACTIVE
-  end
-
-  # Returns an array of projects the project can be moved to
-  # by the current user
-  def allowed_parents
-    return @allowed_parents if @allowed_parents
-    @allowed_parents = Project.where(Project.allowed_to_condition(User.current, :add_subprojects)).all
-    @allowed_parents = @allowed_parents - self_and_descendants
-    if User.current.allowed_to?(:add_project, nil, :global => true) || (!new_record? && parent.nil?)
-      @allowed_parents << nil
-    end
-    unless parent.nil? || @allowed_parents.empty? || @allowed_parents.include?(parent)
-      @allowed_parents << parent
-    end
-    @allowed_parents
-  end
-
-  # Sets the parent of the project with authorization check
-  def set_allowed_parent!(p)
-    unless p.nil? || p.is_a?(Project)
-      if p.to_s.blank?
-        p = nil
-      else
-        p = Project.find_by_id(p)
-        return false unless p
-      end
-    end
-    if p.nil?
-      if !new_record? && allowed_parents.empty?
-        return false
-      end
-    elsif !allowed_parents.include?(p)
-      return false
-    end
-    set_parent!(p)
-  end
-
-  # Sets the parent of the project
-  # Argument can be either a Project, a String, a Fixnum or nil
-  def set_parent!(p)
-    unless p.nil? || p.is_a?(Project)
-      if p.to_s.blank?
-        p = nil
-      else
-        p = Project.find_by_id(p)
-        return false unless p
-      end
-    end
-    if p == parent && !p.nil?
-      # Nothing to do
-      true
-    elsif p.nil? || (p.active? && move_possible?(p))
-      set_or_update_position_under(p)
-      Issue.update_versions_from_hierarchy_change(self)
-      true
-    else
-      # Can not move to the given target
-      false
-    end
-  end
-
-  # Recalculates all lft and rgt values based on project names
-  # Unlike Project.rebuild!, these values are recalculated even if the tree "looks" valid
-  # Used in BuildProjectsTree migration
-  def self.rebuild_tree!
-    transaction do
-      update_all "lft = NULL, rgt = NULL"
-      rebuild!(false)
-    end
-  end
-
-  # Returns an array of the trackers used by the project and its active sub projects
-  def rolled_up_trackers
-    @rolled_up_trackers ||=
-      Tracker.
-        joins(:projects).
-        joins("JOIN #{EnabledModule.table_name} ON #{EnabledModule.table_name}.project_id = #{Project.table_name}.id AND #{EnabledModule.table_name}.name = 'issue_tracking'").
-        select("DISTINCT #{Tracker.table_name}.*").
-        where("#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> #{STATUS_ARCHIVED}", lft, rgt).
-        sorted.
-        all
-  end
-
-  # Closes open and locked project versions that are completed
-  def close_completed_versions
-    Version.transaction do
-      versions.where(:status => %w(open locked)).all.each do |version|
-        if version.completed?
-          version.update_attribute(:status, 'closed')
-        end
-      end
-    end
-  end
-
-  # Returns a scope of the Versions on subprojects
-  def rolled_up_versions
-    @rolled_up_versions ||=
-      Version.
-        includes(:project).
-        where("#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> ?", lft, rgt, STATUS_ARCHIVED)
-  end
-
-  # Returns a scope of the Versions used by the project
-  def shared_versions
-    if new_record?
-      Version.
-        includes(:project).
-        where("#{Project.table_name}.status <> ? AND #{Version.table_name}.sharing = 'system'", STATUS_ARCHIVED)
-    else
-      @shared_versions ||= begin
-        r = root? ? self : root
-        Version.
-          includes(:project).
-          where("#{Project.table_name}.id = #{id}" +
-                  " OR (#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED} AND (" +
-                    " #{Version.table_name}.sharing = 'system'" +
-                    " OR (#{Project.table_name}.lft >= #{r.lft} AND #{Project.table_name}.rgt <= #{r.rgt} AND #{Version.table_name}.sharing = 'tree')" +
-                    " OR (#{Project.table_name}.lft < #{lft} AND #{Project.table_name}.rgt > #{rgt} AND #{Version.table_name}.sharing IN ('hierarchy', 'descendants'))" +
-                    " OR (#{Project.table_name}.lft > #{lft} AND #{Project.table_name}.rgt < #{rgt} AND #{Version.table_name}.sharing = 'hierarchy')" +
-                  "))")
-      end
-    end
-  end
-
-  # Returns a hash of project users grouped by role
-  def users_by_role
-    members.includes(:user, :roles).all.inject({}) do |h, m|
-      m.roles.each do |r|
-        h[r] ||= []
-        h[r] << m.user
-      end
-      h
-    end
-  end
-
-  # Deletes all project's members
-  def delete_all_members
-    me, mr = Member.table_name, MemberRole.table_name
-    connection.delete("DELETE FROM #{mr} WHERE #{mr}.member_id IN (SELECT #{me}.id FROM #{me} WHERE #{me}.project_id = #{id})")
-    Member.delete_all(['project_id = ?', id])
-  end
-
-  # Users/groups issues can be assigned to
-  def assignable_users
-    assignable = Setting.issue_group_assignment? ? member_principals : members
-    assignable.select {|m| m.roles.detect {|role| role.assignable?}}.collect {|m| m.principal}.sort
-  end
-
-  # Returns the mail adresses of users that should be always notified on project events
-  def recipients
-    notified_users.collect {|user| user.mail}
-  end
-
-  # Returns the users that should be notified on project events
-  def notified_users
-    # TODO: User part should be extracted to User#notify_about?
-    members.select {|m| m.principal.present? && (m.mail_notification? || m.principal.mail_notification == 'all')}.collect {|m| m.principal}
-  end
-
-  # Returns a scope of all custom fields enabled for project issues
-  # (explictly associated custom fields and custom fields enabled for all projects)
-  def all_issue_custom_fields
-    @all_issue_custom_fields ||= IssueCustomField.
-      sorted.
-      where("is_for_all = ? OR id IN (SELECT DISTINCT cfp.custom_field_id" +
-        " FROM #{table_name_prefix}custom_fields_projects#{table_name_suffix} cfp" +
-        " WHERE cfp.project_id = ?)", true, id)
-  end
-
-  # Returns an array of all custom fields enabled for project time entries
-  # (explictly associated custom fields and custom fields enabled for all projects)
-  def all_time_entry_custom_fields
-    @all_time_entry_custom_fields ||= (TimeEntryCustomField.for_all + time_entry_custom_fields).uniq.sort
-  end
-
-  def project
-    self
-  end
-
-  def <=>(project)
-    name.downcase <=> project.name.downcase
-  end
-
-  def to_s
-    name
-  end
-
-  # Returns a short description of the projects (first lines)
-  def short_description(length = 255)
-    description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
-  end
-
-  def css_classes
-    s = 'project'
-    s << ' root' if root?
-    s << ' child' if child?
-    s << (leaf? ? ' leaf' : ' parent')
-    unless active?
-      if archived?
-        s << ' archived'
-      else
-        s << ' closed'
-      end
-    end
-    s
-  end
-
-  # The earliest start date of a project, based on it's issues and versions
-  def start_date
-    @start_date ||= [
-     issues.minimum('start_date'),
-     shared_versions.minimum('effective_date'),
-     Issue.fixed_version(shared_versions).minimum('start_date')
-    ].compact.min
-  end
-
-  # The latest due date of an issue or version
-  def due_date
-    @due_date ||= [
-     issues.maximum('due_date'),
-     shared_versions.maximum('effective_date'),
-     Issue.fixed_version(shared_versions).maximum('due_date')
-    ].compact.max
-  end
-
-  def overdue?
-    active? && !due_date.nil? && (due_date < Date.today)
-  end
-
-  # Returns the percent completed for this project, based on the
-  # progress on it's versions.
-  def completed_percent(options={:include_subprojects => false})
-    if options.delete(:include_subprojects)
-      total = self_and_descendants.collect(&:completed_percent).sum
-
-      total / self_and_descendants.count
-    else
-      if versions.count > 0
-        total = versions.collect(&:completed_percent).sum
-
-        total / versions.count
-      else
-        100
-      end
-    end
-  end
-
-  # Return true if this project allows to do the specified action.
-  # action can be:
-  # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
-  # * a permission Symbol (eg. :edit_project)
-  def allows_to?(action)
-    if archived?
-      # No action allowed on archived projects
-      return false
-    end
-    unless active? || Redmine::AccessControl.read_action?(action)
-      # No write action allowed on closed projects
-      return false
-    end
-    # No action allowed on disabled modules
-    if action.is_a? Hash
-      allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
-    else
-      allowed_permissions.include? action
-    end
-  end
-
-  def module_enabled?(module_name)
-    module_name = module_name.to_s
-    enabled_modules.detect {|m| m.name == module_name}
-  end
-
-  def enabled_module_names=(module_names)
-    if module_names && module_names.is_a?(Array)
-      module_names = module_names.collect(&:to_s).reject(&:blank?)
-      self.enabled_modules = module_names.collect {|name| enabled_modules.detect {|mod| mod.name == name} || EnabledModule.new(:name => name)}
-    else
-      enabled_modules.clear
-    end
-  end
-
-  # Returns an array of the enabled modules names
-  def enabled_module_names
-    enabled_modules.collect(&:name)
-  end
-
-  # Enable a specific module
-  #
-  # Examples:
-  #   project.enable_module!(:issue_tracking)
-  #   project.enable_module!("issue_tracking")
-  def enable_module!(name)
-    enabled_modules << EnabledModule.new(:name => name.to_s) unless module_enabled?(name)
-  end
-
-  # Disable a module if it exists
-  #
-  # Examples:
-  #   project.disable_module!(:issue_tracking)
-  #   project.disable_module!("issue_tracking")
-  #   project.disable_module!(project.enabled_modules.first)
-  def disable_module!(target)
-    target = enabled_modules.detect{|mod| target.to_s == mod.name} unless enabled_modules.include?(target)
-    target.destroy unless target.blank?
-  end
-
-  safe_attributes 'name',
-    'description',
-    'homepage',
-    'is_public',
-    'identifier',
-    'custom_field_values',
-    'custom_fields',
-    'tracker_ids',
-    'issue_custom_field_ids'
-
-  safe_attributes 'enabled_module_names',
-    :if => lambda {|project, user| project.new_record? || user.allowed_to?(:select_project_modules, project) }
-
-  safe_attributes 'inherit_members',
-    :if => lambda {|project, user| project.parent.nil? || project.parent.visible?(user)}
-
-  # Returns an array of projects that are in this project's hierarchy
-  #
-  # Example: parents, children, siblings
-  def hierarchy
-    parents = project.self_and_ancestors || []
-    descendants = project.descendants || []
-    project_hierarchy = parents | descendants # Set union
-  end
-
-  # Returns an auto-generated project identifier based on the last identifier used
-  def self.next_identifier
-    p = Project.order('id DESC').first
-    p.nil? ? nil : p.identifier.to_s.succ
-  end
-
-  # Copies and saves the Project instance based on the +project+.
-  # Duplicates the source project's:
-  # * Wiki
-  # * Versions
-  # * Categories
-  # * Issues
-  # * Members
-  # * Queries
-  #
-  # Accepts an +options+ argument to specify what to copy
-  #
-  # Examples:
-  #   project.copy(1)                                    # => copies everything
-  #   project.copy(1, :only => 'members')                # => copies members only
-  #   project.copy(1, :only => ['members', 'versions'])  # => copies members and versions
-  def copy(project, options={})
-    project = project.is_a?(Project) ? project : Project.find(project)
-
-    to_be_copied = %w(wiki versions issue_categories issues members queries boards)
-    to_be_copied = to_be_copied & options[:only].to_a unless options[:only].nil?
-
-    Project.transaction do
-      if save
-        reload
-        to_be_copied.each do |name|
-          send "copy_#{name}", project
-        end
-        Redmine::Hook.call_hook(:model_project_copy_before_save, :source_project => project, :destination_project => self)
-        save
-      end
-    end
-  end
-
-  # Returns a new unsaved Project instance with attributes copied from +project+
-  def self.copy_from(project)
-    project = project.is_a?(Project) ? project : Project.find(project)
-    # clear unique attributes
-    attributes = project.attributes.dup.except('id', 'name', 'identifier', 'status', 'parent_id', 'lft', 'rgt')
-    copy = Project.new(attributes)
-    copy.enabled_modules = project.enabled_modules
-    copy.trackers = project.trackers
-    copy.custom_values = project.custom_values.collect {|v| v.clone}
-    copy.issue_custom_fields = project.issue_custom_fields
-    copy
-  end
-
-  # Yields the given block for each project with its level in the tree
-  def self.project_tree(projects, &block)
-    ancestors = []
-    projects.sort_by(&:lft).each do |project|
-      while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
-        ancestors.pop
-      end
-      yield project, ancestors.size
-      ancestors << project
-    end
-  end
-
-  private
-
-  def after_parent_changed(parent_was)
-    remove_inherited_member_roles
-    add_inherited_member_roles
-  end
-
-  def update_inherited_members
-    if parent
-      if inherit_members? && !inherit_members_was
-        remove_inherited_member_roles
-        add_inherited_member_roles
-      elsif !inherit_members? && inherit_members_was
-        remove_inherited_member_roles
-      end
-    end
-  end
-
-  def remove_inherited_member_roles
-    member_roles = memberships.map(&:member_roles).flatten
-    member_role_ids = member_roles.map(&:id)
-    member_roles.each do |member_role|
-      if member_role.inherited_from && !member_role_ids.include?(member_role.inherited_from)
-        member_role.destroy
-      end
-    end
-  end
-
-  def add_inherited_member_roles
-    if inherit_members? && parent
-      parent.memberships.each do |parent_member|
-        member = Member.find_or_new(self.id, parent_member.user_id)
-        parent_member.member_roles.each do |parent_member_role|
-          member.member_roles << MemberRole.new(:role => parent_member_role.role, :inherited_from => parent_member_role.id)
-        end
-        member.save!
-      end
-    end
-  end
-
-  # Copies wiki from +project+
-  def copy_wiki(project)
-    # Check that the source project has a wiki first
-    unless project.wiki.nil?
-      wiki = self.wiki || Wiki.new
-      wiki.attributes = project.wiki.attributes.dup.except("id", "project_id")
-      wiki_pages_map = {}
-      project.wiki.pages.each do |page|
-        # Skip pages without content
-        next if page.content.nil?
-        new_wiki_content = WikiContent.new(page.content.attributes.dup.except("id", "page_id", "updated_on"))
-        new_wiki_page = WikiPage.new(page.attributes.dup.except("id", "wiki_id", "created_on", "parent_id"))
-        new_wiki_page.content = new_wiki_content
-        wiki.pages << new_wiki_page
-        wiki_pages_map[page.id] = new_wiki_page
-      end
-
-      self.wiki = wiki
-      wiki.save
-      # Reproduce page hierarchy
-      project.wiki.pages.each do |page|
-        if page.parent_id && wiki_pages_map[page.id]
-          wiki_pages_map[page.id].parent = wiki_pages_map[page.parent_id]
-          wiki_pages_map[page.id].save
-        end
-      end
-    end
-  end
-
-  # Copies versions from +project+
-  def copy_versions(project)
-    project.versions.each do |version|
-      new_version = Version.new
-      new_version.attributes = version.attributes.dup.except("id", "project_id", "created_on", "updated_on")
-      self.versions << new_version
-    end
-  end
-
-  # Copies issue categories from +project+
-  def copy_issue_categories(project)
-    project.issue_categories.each do |issue_category|
-      new_issue_category = IssueCategory.new
-      new_issue_category.attributes = issue_category.attributes.dup.except("id", "project_id")
-      self.issue_categories << new_issue_category
-    end
-  end
-
-  # Copies issues from +project+
-  def copy_issues(project)
-    # Stores the source issue id as a key and the copied issues as the
-    # value.  Used to map the two togeather for issue relations.
-    issues_map = {}
-
-    # Store status and reopen locked/closed versions
-    version_statuses = versions.reject(&:open?).map {|version| [version, version.status]}
-    version_statuses.each do |version, status|
-      version.update_attribute :status, 'open'
-    end
-
-    # Get issues sorted by root_id, lft so that parent issues
-    # get copied before their children
-    project.issues.reorder('root_id, lft').all.each do |issue|
-      new_issue = Issue.new
-      new_issue.copy_from(issue, :subtasks => false, :link => false)
-      new_issue.project = self
-      # Changing project resets the custom field values
-      # TODO: handle this in Issue#project=
-      new_issue.custom_field_values = issue.custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
-      # Reassign fixed_versions by name, since names are unique per project
-      if issue.fixed_version && issue.fixed_version.project == project
-        new_issue.fixed_version = self.versions.detect {|v| v.name == issue.fixed_version.name}
-      end
-      # Reassign the category by name, since names are unique per project
-      if issue.category
-        new_issue.category = self.issue_categories.detect {|c| c.name == issue.category.name}
-      end
-      # Parent issue
-      if issue.parent_id
-        if copied_parent = issues_map[issue.parent_id]
-          new_issue.parent_issue_id = copied_parent.id
-        end
-      end
-
-      self.issues << new_issue
-      if new_issue.new_record?
-        logger.info "Project#copy_issues: issue ##{issue.id} could not be copied: #{new_issue.errors.full_messages}" if logger && logger.info
-      else
-        issues_map[issue.id] = new_issue unless new_issue.new_record?
-      end
-    end
-
-    # Restore locked/closed version statuses
-    version_statuses.each do |version, status|
-      version.update_attribute :status, status
-    end
-
-    # Relations after in case issues related each other
-    project.issues.each do |issue|
-      new_issue = issues_map[issue.id]
-      unless new_issue
-        # Issue was not copied
-        next
-      end
-
-      # Relations
-      issue.relations_from.each do |source_relation|
-        new_issue_relation = IssueRelation.new
-        new_issue_relation.attributes = source_relation.attributes.dup.except("id", "issue_from_id", "issue_to_id")
-        new_issue_relation.issue_to = issues_map[source_relation.issue_to_id]
-        if new_issue_relation.issue_to.nil? && Setting.cross_project_issue_relations?
-          new_issue_relation.issue_to = source_relation.issue_to
-        end
-        new_issue.relations_from << new_issue_relation
-      end
-
-      issue.relations_to.each do |source_relation|
-        new_issue_relation = IssueRelation.new
-        new_issue_relation.attributes = source_relation.attributes.dup.except("id", "issue_from_id", "issue_to_id")
-        new_issue_relation.issue_from = issues_map[source_relation.issue_from_id]
-        if new_issue_relation.issue_from.nil? && Setting.cross_project_issue_relations?
-          new_issue_relation.issue_from = source_relation.issue_from
-        end
-        new_issue.relations_to << new_issue_relation
-      end
-    end
-  end
-
-  # Copies members from +project+
-  def copy_members(project)
-    # Copy users first, then groups to handle members with inherited and given roles
-    members_to_copy = []
-    members_to_copy += project.memberships.select {|m| m.principal.is_a?(User)}
-    members_to_copy += project.memberships.select {|m| !m.principal.is_a?(User)}
-
-    members_to_copy.each do |member|
-      new_member = Member.new
-      new_member.attributes = member.attributes.dup.except("id", "project_id", "created_on")
-      # only copy non inherited roles
-      # inherited roles will be added when copying the group membership
-      role_ids = member.member_roles.reject(&:inherited?).collect(&:role_id)
-      next if role_ids.empty?
-      new_member.role_ids = role_ids
-      new_member.project = self
-      self.members << new_member
-    end
-  end
-
-  # Copies queries from +project+
-  def copy_queries(project)
-    project.queries.each do |query|
-      new_query = IssueQuery.new
-      new_query.attributes = query.attributes.dup.except("id", "project_id", "sort_criteria")
-      new_query.sort_criteria = query.sort_criteria if query.sort_criteria
-      new_query.project = self
-      new_query.user_id = query.user_id
-      self.queries << new_query
-    end
-  end
-
-  # Copies boards from +project+
-  def copy_boards(project)
-    project.boards.each do |board|
-      new_board = Board.new
-      new_board.attributes = board.attributes.dup.except("id", "project_id", "topics_count", "messages_count", "last_message_id")
-      new_board.project = self
-      self.boards << new_board
-    end
-  end
-
-  def allowed_permissions
-    @allowed_permissions ||= begin
-      module_names = enabled_modules.loaded? ? enabled_modules.map(&:name) : enabled_modules.pluck(:name)
-      Redmine::AccessControl.modules_permissions(module_names).collect {|p| p.name}
-    end
-  end
-
-  def allowed_actions
-    @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
-  end
-
-  # Returns all the active Systemwide and project specific activities
-  def active_activities
-    overridden_activity_ids = self.time_entry_activities.collect(&:parent_id)
-
-    if overridden_activity_ids.empty?
-      return TimeEntryActivity.shared.active
-    else
-      return system_activities_and_project_overrides
-    end
-  end
-
-  # Returns all the Systemwide and project specific activities
-  # (inactive and active)
-  def all_activities
-    overridden_activity_ids = self.time_entry_activities.collect(&:parent_id)
-
-    if overridden_activity_ids.empty?
-      return TimeEntryActivity.shared
-    else
-      return system_activities_and_project_overrides(true)
-    end
-  end
-
-  # Returns the systemwide active activities merged with the project specific overrides
-  def system_activities_and_project_overrides(include_inactive=false)
-    if include_inactive
-      return TimeEntryActivity.shared.
-        where("id NOT IN (?)", self.time_entry_activities.collect(&:parent_id)).all +
-        self.time_entry_activities
-    else
-      return TimeEntryActivity.shared.active.
-        where("id NOT IN (?)", self.time_entry_activities.collect(&:parent_id)).all +
-        self.time_entry_activities.active
-    end
-  end
-
-  # Archives subprojects recursively
-  def archive!
-    children.each do |subproject|
-      subproject.send :archive!
-    end
-    update_attribute :status, STATUS_ARCHIVED
-  end
-
-  def update_position_under_parent
-    set_or_update_position_under(parent)
-  end
-
-  # Inserts/moves the project so that target's children or root projects stay alphabetically sorted
-  def set_or_update_position_under(target_parent)
-    parent_was = parent
-    sibs = (target_parent.nil? ? self.class.roots : target_parent.children)
-    to_be_inserted_before = sibs.sort_by {|c| c.name.to_s.downcase}.detect {|c| c.name.to_s.downcase > name.to_s.downcase }
-
-    if to_be_inserted_before
-      move_to_left_of(to_be_inserted_before)
-    elsif target_parent.nil?
-      if sibs.empty?
-        # move_to_root adds the project in first (ie. left) position
-        move_to_root
-      else
-        move_to_right_of(sibs.last) unless self == sibs.last
-      end
-    else
-      # move_to_child_of adds the project in last (ie.right) position
-      move_to_child_of(target_parent)
-    end
-    if parent_was != target_parent
-      after_parent_changed(parent_was)
-    end
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/13/13f1c7e824023a07ff2178b5bb3f5f1ee4de792e.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+   "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<title>Redmine 500 error</title>
+<style>
+body{
+font-family: "Trebuchet MS",Georgia,"Times New Roman",serif;
+color:#303030;
+margin:10px;
+}
+h1{
+font-size:1.5em;
+}
+p{
+font-size:0.8em;
+}
+</style>
+<body>
+  <h1>Internal error</h1>
+  <p>An error occurred on the page you were trying to access.<br />
+  If you continue to experience problems please contact your Redmine administrator for assistance.</p>
+  <p>If you are the Redmine administrator, check your log files for details about the error.</p>
+  <p><a href="javascript:history.back()">Back</a></p>
+</body>
+</html>
--- a/.svn/pristine/13/13f3f51390f5b007f8a6b4667437b3436606259a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Acts
-    module ActivityProvider
-      def self.included(base)
-        base.extend ClassMethods
-      end
-
-      module ClassMethods
-        def acts_as_activity_provider(options = {})
-          unless self.included_modules.include?(Redmine::Acts::ActivityProvider::InstanceMethods)
-            cattr_accessor :activity_provider_options
-            send :include, Redmine::Acts::ActivityProvider::InstanceMethods
-          end
-
-          options.assert_valid_keys(:type, :permission, :timestamp, :author_key, :find_options)
-          self.activity_provider_options ||= {}
-
-          # One model can provide different event types
-          # We store these options in activity_provider_options hash
-          event_type = options.delete(:type) || self.name.underscore.pluralize
-
-          options[:timestamp] ||= "#{table_name}.created_on"
-          options[:find_options] ||= {}
-          options[:author_key] = "#{table_name}.#{options[:author_key]}" if options[:author_key].is_a?(Symbol)
-          self.activity_provider_options[event_type] = options
-        end
-      end
-
-      module InstanceMethods
-        def self.included(base)
-          base.extend ClassMethods
-        end
-
-        module ClassMethods
-          # Returns events of type event_type visible by user that occured between from and to
-          def find_events(event_type, user, from, to, options)
-            provider_options = activity_provider_options[event_type]
-            raise "#{self.name} can not provide #{event_type} events." if provider_options.nil?
-
-            scope = self
-
-            if from && to
-              scope = scope.where("#{provider_options[:timestamp]} BETWEEN ? AND ?", from, to)
-            end
-
-            if options[:author]
-              return [] if provider_options[:author_key].nil?
-              scope = scope.where("#{provider_options[:author_key]} = ?", options[:author].id)
-            end
-
-            if options[:limit]
-              # id and creation time should be in same order in most cases
-              scope = scope.reorder("#{table_name}.id DESC").limit(options[:limit])
-            end
-
-            if provider_options.has_key?(:permission)
-              scope = scope.where(Project.allowed_to_condition(user, provider_options[:permission] || :view_project, options))
-            elsif respond_to?(:visible)
-              scope = scope.visible(user, options)
-            else
-              ActiveSupport::Deprecation.warn "acts_as_activity_provider with implicit :permission option is deprecated. Add a visible scope to the #{self.name} model or use explicit :permission option."
-              scope = scope.where(Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym, options))
-            end
-
-            scope.all(provider_options[:find_options].dup)
-          end
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/15/1501976e33da8b363bb737aa1d51d7b528152400.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,262 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::I18nTest < ActiveSupport::TestCase
-  include Redmine::I18n
-  include ActionView::Helpers::NumberHelper
-
-  def setup
-    User.current.language = nil
-  end
-
-  def teardown
-    set_language_if_valid 'en'
-  end
-
-  def test_date_format_default
-    set_language_if_valid 'en'
-    today = Date.today
-    Setting.date_format = ''
-    assert_equal I18n.l(today), format_date(today)
-  end
-
-  def test_date_format
-    set_language_if_valid 'en'
-    today = Date.today
-    Setting.date_format = '%d %m %Y'
-    assert_equal today.strftime('%d %m %Y'), format_date(today)
-  end
-
-  def test_date_format_default_with_user_locale
-    set_language_if_valid 'es'
-    today = now = Time.parse('2011-02-20 14:00:00')
-    Setting.date_format = '%d %B %Y'
-    User.current.language = 'fr'
-    s1 = "20 f\xc3\xa9vrier 2011"
-    s1.force_encoding("UTF-8") if s1.respond_to?(:force_encoding)
-    assert_equal s1, format_date(today)
-    User.current.language = nil
-    assert_equal '20 Febrero 2011', format_date(today)
-  end
-
-  def test_date_and_time_for_each_language
-    Setting.date_format = ''
-    valid_languages.each do |lang|
-      set_language_if_valid lang
-      assert_nothing_raised "#{lang} failure" do
-        format_date(Date.today)
-        format_time(Time.now)
-        format_time(Time.now, false)
-        assert_not_equal 'default', ::I18n.l(Date.today, :format => :default),
-                         "date.formats.default missing in #{lang}"
-        assert_not_equal 'time',    ::I18n.l(Time.now, :format => :time),
-                         "time.formats.time missing in #{lang}"
-      end
-      assert l('date.day_names').is_a?(Array)
-      assert_equal 7, l('date.day_names').size
-
-      assert l('date.month_names').is_a?(Array)
-      assert_equal 13, l('date.month_names').size
-    end
-  end
-
-  def test_time_for_each_zone
-    ActiveSupport::TimeZone.all.each do |zone|
-      User.current.stubs(:time_zone).returns(zone.name)
-      assert_nothing_raised "#{zone} failure" do
-        format_time(Time.now)
-      end
-    end
-  end
-
-  def test_time_format
-    set_language_if_valid 'en'
-    now = Time.parse('2011-02-20 15:45:22')
-    with_settings :time_format => '%H:%M' do
-      with_settings :date_format => '' do
-        assert_equal '02/20/2011 15:45', format_time(now)
-        assert_equal '15:45', format_time(now, false)
-      end
-      with_settings :date_format => '%Y-%m-%d' do
-        assert_equal '2011-02-20 15:45', format_time(now)
-        assert_equal '15:45', format_time(now, false)
-      end
-    end
-  end
-
-  def test_time_format_default
-    set_language_if_valid 'en'
-    now = Time.parse('2011-02-20 15:45:22')
-    with_settings :time_format => '' do
-      with_settings :date_format => '' do
-        assert_equal '02/20/2011 03:45 PM', format_time(now)
-        assert_equal '03:45 PM', format_time(now, false)
-      end
-      with_settings :date_format => '%Y-%m-%d' do
-        assert_equal '2011-02-20 03:45 PM', format_time(now)
-        assert_equal '03:45 PM', format_time(now, false)
-      end
-    end
-  end
-
-  def test_time_format_default_with_user_locale
-    set_language_if_valid 'en'
-    User.current.language = 'fr'
-    now = Time.parse('2011-02-20 15:45:22')
-    with_settings :time_format => '' do
-      with_settings :date_format => '' do
-        assert_equal '20/02/2011 15:45', format_time(now)
-        assert_equal '15:45', format_time(now, false)
-      end
-      with_settings :date_format => '%Y-%m-%d' do
-        assert_equal '2011-02-20 15:45', format_time(now)
-        assert_equal '15:45', format_time(now, false)
-      end
-    end
-  end
-
-  def test_utc_time_format
-    set_language_if_valid 'en'
-    now = Time.now
-    Setting.date_format = '%d %m %Y'
-    Setting.time_format = '%H %M'
-    assert_equal now.strftime('%d %m %Y %H %M'), format_time(now.utc)
-    assert_equal now.strftime('%H %M'), format_time(now.utc, false)
-  end
-
-  def test_number_to_human_size_for_each_language
-    valid_languages.each do |lang|
-      set_language_if_valid lang
-      assert_nothing_raised "#{lang} failure" do
-        size = number_to_human_size(257024)
-        assert_match /251/, size
-      end
-    end
-  end
-
-  def test_day_name
-    set_language_if_valid 'fr'
-    assert_equal 'dimanche', day_name(0)
-    assert_equal 'jeudi', day_name(4)
-  end
-
-  def test_day_letter
-    set_language_if_valid 'fr'
-    assert_equal 'd', day_letter(0)
-    assert_equal 'j', day_letter(4)
-  end
-
-  def test_number_to_currency_for_each_language
-    valid_languages.each do |lang|
-      set_language_if_valid lang
-      assert_nothing_raised "#{lang} failure" do
-        number_to_currency(-1000.2)
-      end
-    end
-  end
-
-  def test_number_to_currency_default
-    set_language_if_valid 'bs'
-    assert_equal "KM -1000,20", number_to_currency(-1000.2)
-    set_language_if_valid 'de'
-    euro_sign = "\xe2\x82\xac"
-    euro_sign.force_encoding('UTF-8') if euro_sign.respond_to?(:force_encoding)
-    assert_equal "-1000,20 #{euro_sign}", number_to_currency(-1000.2)
-  end
-
-  def test_valid_languages
-    assert valid_languages.is_a?(Array)
-    assert valid_languages.first.is_a?(Symbol)
-  end
-
-  def test_languages_options
-    options = languages_options
-    assert options.is_a?(Array)
-    assert_equal valid_languages.size, options.size
-    assert_nil options.detect {|option| !option.is_a?(Array)}
-    assert_nil options.detect {|option| option.size != 2}
-    assert_nil options.detect {|option| !option.first.is_a?(String) || !option.last.is_a?(String)}
-    assert_include ["English", "en"], options
-    ja = "Japanese (\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e)"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
-    assert_include [ja, "ja"], options
-  end
-
-  def test_locales_validness
-    lang_files_count = Dir["#{Rails.root}/config/locales/*.yml"].size
-    assert_equal lang_files_count, valid_languages.size
-    valid_languages.each do |lang|
-      assert set_language_if_valid(lang)
-    end
-    set_language_if_valid('en')
-  end
-
-  def test_valid_language
-    to_test = {'fr' => :fr,
-               'Fr' => :fr,
-               'zh' => :zh,
-               'zh-tw' => :"zh-TW",
-               'zh-TW' => :"zh-TW",
-               'zh-ZZ' => nil }
-    to_test.each {|lang, expected| assert_equal expected, find_language(lang)}
-  end
-
-  def test_fallback
-    ::I18n.backend.store_translations(:en, {:untranslated => "Untranslated string"})
-    ::I18n.locale = 'en'
-    assert_equal "Untranslated string", l(:untranslated)
-    ::I18n.locale = 'fr'
-    assert_equal "Untranslated string", l(:untranslated)
-
-    ::I18n.backend.store_translations(:fr, {:untranslated => "Pas de traduction"})
-    ::I18n.locale = 'en'
-    assert_equal "Untranslated string", l(:untranslated)
-    ::I18n.locale = 'fr'
-    assert_equal "Pas de traduction", l(:untranslated)
-  end
-
-  def test_utf8
-    set_language_if_valid 'ja'
-    str_ja_yes  = "\xe3\x81\xaf\xe3\x81\x84"
-    i18n_ja_yes = l(:general_text_Yes)
-    if str_ja_yes.respond_to?(:force_encoding)
-      str_ja_yes.force_encoding('UTF-8')
-      assert_equal "UTF-8", i18n_ja_yes.encoding.to_s
-    end
-    assert_equal str_ja_yes, i18n_ja_yes
-  end
-
-  def test_traditional_chinese_locale
-    set_language_if_valid 'zh-TW'
-    str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)"
-    if str_tw.respond_to?(:force_encoding)
-      str_tw.force_encoding('UTF-8')
-    end
-    assert_equal str_tw, l(:general_lang_name)
-  end
-
-  def test_french_locale
-    set_language_if_valid 'fr'
-    str_fr = "Fran\xc3\xa7ais"
-    if str_fr.respond_to?(:force_encoding)
-      str_fr.force_encoding('UTF-8')
-    end
-    assert_equal str_fr, l(:general_lang_name)
-  end
-end
--- a/.svn/pristine/15/15b7222cb6b5695205873370eda995f4170a4d8e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class MemberTest < ActiveSupport::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :groups_users,
-           :watchers,
-           :journals, :journal_details,
-           :messages,
-           :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
-           :boards
-
-  include Redmine::I18n
-
-  def setup
-    @jsmith = Member.find(1)
-  end
-
-  def test_create
-    member = Member.new(:project_id => 1, :user_id => 4, :role_ids => [1, 2])
-    assert member.save
-    member.reload
-
-    assert_equal 2, member.roles.size
-    assert_equal Role.find(1), member.roles.sort.first
-  end
-
-  def test_update
-    assert_equal "eCookbook", @jsmith.project.name
-    assert_equal "Manager", @jsmith.roles.first.name
-    assert_equal "jsmith", @jsmith.user.login
-
-    @jsmith.mail_notification = !@jsmith.mail_notification
-    assert @jsmith.save
-  end
-
-  def test_update_roles
-    assert_equal 1, @jsmith.roles.size
-    @jsmith.role_ids = [1, 2]
-    assert @jsmith.save
-    assert_equal 2, @jsmith.reload.roles.size
-  end
-
-  def test_validate
-    member = Member.new(:project_id => 1, :user_id => 2, :role_ids => [2])
-    # same use can't have more than one membership for a project
-    assert !member.save
-
-    # must have one role at least
-    user = User.new(:firstname => "new1", :lastname => "user1", :mail => "test_validate@somenet.foo")
-    user.login = "test_validate"
-    user.password, user.password_confirmation = "password", "password"
-    assert user.save
-
-    set_language_if_valid 'fr'
-    member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [])
-    assert !member.save
-    assert_include I18n.translate('activerecord.errors.messages.empty'), member.errors[:role]
-    str = "R\xc3\xb4le doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    assert_equal str, [member.errors.full_messages].flatten.join
-  end
-
-  def test_validate_member_role
-    user = User.new(:firstname => "new1", :lastname => "user1", :mail => "test_validate@somenet.foo")
-    user.login = "test_validate_member_role"
-    user.password, user.password_confirmation = "password", "password"
-    assert user.save
-    member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [5])
-    assert !member.save
-  end
-
-  def test_destroy
-    category1 = IssueCategory.find(1)
-    assert_equal @jsmith.user.id, category1.assigned_to_id
-    assert_difference 'Member.count', -1 do
-      assert_difference 'MemberRole.count', -1 do
-        @jsmith.destroy
-      end
-    end
-    assert_raise(ActiveRecord::RecordNotFound) { Member.find(@jsmith.id) }
-    category1.reload
-    assert_nil category1.assigned_to_id
-  end
-
-  def test_sort_without_roles
-    a = Member.new(:roles => [Role.first])
-    b = Member.new
-
-    assert_equal -1, a <=> b
-    assert_equal 1,  b <=> a
-  end
-
-  def test_sort_without_principal
-    role = Role.first
-    a = Member.new(:roles => [role], :principal => User.first)
-    b = Member.new(:roles => [role])
-
-    assert_equal -1, a <=> b
-    assert_equal 1,  b <=> a
-  end
-end
--- a/.svn/pristine/15/15c19f10a4e2450833d4d36fd99f66518ba44283.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::CustomFieldsTest < Redmine::ApiTest::Base
-  fixtures :users, :custom_fields
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /custom_fields.xml should return custom fields" do
-    get '/custom_fields.xml', {}, credentials('admin')
-    assert_response :success
-    assert_equal 'application/xml', response.content_type
-
-    assert_select 'custom_fields' do
-      assert_select 'custom_field' do
-        assert_select 'name', :text => 'Database'
-        assert_select 'id', :text => '2'
-        assert_select 'customized_type', :text => 'issue'
-        assert_select 'possible_values[type=array]' do
-          assert_select 'possible_value>value', :text => 'PostgreSQL'
-        end
-      end
-    end
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/15/15d709b3f6a05dc0aade44cd45030b0d995c1fdc.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+   "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<title>Redmine 404 error</title>
+<style>
+body{
+font-family: "Trebuchet MS",Georgia,"Times New Roman",serif;
+color:#303030;
+margin:10px;
+}
+h1{
+font-size:1.5em;
+}
+p{
+font-size:0.8em;
+}
+</style>
+<body>
+  <h1>Page not found</h1>
+  <p>The page you were trying to access doesn't exist or has been removed.</p>
+  <p><a href="javascript:history.back()">Back</a></p>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/16/1611dde1fb0ec5f844a52d9ac947a7c023328e24.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,38 @@
+# Redmine runs tests on own continuous integration server.
+# http://www.redmine.org/projects/redmine/wiki/Continuous_integration
+# You can also run tests on your environment.
+language: ruby
+rvm:
+  - 1.8.7
+  - 1.9.2
+  - 1.9.3
+  - 2.0
+  - jruby
+matrix:
+  allow_failures:
+    # SCM tests fail randomly due to IO.popen().
+    # https://github.com/jruby/jruby/issues/779
+    - rvm: jruby
+env:
+  - "TEST_SUITE=units       DATABASE_ADAPTER=postgresql"
+  - "TEST_SUITE=functionals DATABASE_ADAPTER=postgresql"
+  - "TEST_SUITE=integration DATABASE_ADAPTER=postgresql"
+  - "TEST_SUITE=units       DATABASE_ADAPTER=mysql"
+  - "TEST_SUITE=functionals DATABASE_ADAPTER=mysql"
+  - "TEST_SUITE=integration DATABASE_ADAPTER=mysql"
+  - "TEST_SUITE=units       DATABASE_ADAPTER=sqlite3"
+  - "TEST_SUITE=functionals DATABASE_ADAPTER=sqlite3"
+  - "TEST_SUITE=integration DATABASE_ADAPTER=sqlite3"
+before_install:
+  - "sudo apt-get update -qq"
+  - "sudo apt-get --no-install-recommends install bzr cvs git mercurial subversion"
+script:
+  - "SCMS=bazaar,cvs,subversion,git,mercurial,filesystem"
+  - "export SCMS"
+  - "git --version"
+  - "bundle install"
+  - "RUN_ON_NOT_OFFICIAL='' RUBY_VER=1.9 BRANCH=trunk bundle exec rake config/database.yml"
+  - "bundle install"
+  - "JRUBY_OPTS=-J-Xmx1024m bundle exec rake ci"
+notifications:
+  email: false
--- a/.svn/pristine/16/163200e35f1d8c0484dc12a3ebb2256afa7733a8.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,437 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module MenuManager
-    class MenuError < StandardError #:nodoc:
-    end
-
-    module MenuController
-      def self.included(base)
-        base.extend(ClassMethods)
-      end
-
-      module ClassMethods
-        @@menu_items = Hash.new {|hash, key| hash[key] = {:default => key, :actions => {}}}
-        mattr_accessor :menu_items
-
-        # Set the menu item name for a controller or specific actions
-        # Examples:
-        #   * menu_item :tickets # => sets the menu name to :tickets for the whole controller
-        #   * menu_item :tickets, :only => :list # => sets the menu name to :tickets for the 'list' action only
-        #   * menu_item :tickets, :only => [:list, :show] # => sets the menu name to :tickets for 2 actions only
-        #
-        # The default menu item name for a controller is controller_name by default
-        # Eg. the default menu item name for ProjectsController is :projects
-        def menu_item(id, options = {})
-          if actions = options[:only]
-            actions = [] << actions unless actions.is_a?(Array)
-            actions.each {|a| menu_items[controller_name.to_sym][:actions][a.to_sym] = id}
-          else
-            menu_items[controller_name.to_sym][:default] = id
-          end
-        end
-      end
-
-      def menu_items
-        self.class.menu_items
-      end
-
-      # Returns the menu item name according to the current action
-      def current_menu_item
-        @current_menu_item ||= menu_items[controller_name.to_sym][:actions][action_name.to_sym] ||
-                                 menu_items[controller_name.to_sym][:default]
-      end
-
-      # Redirects user to the menu item of the given project
-      # Returns false if user is not authorized
-      def redirect_to_project_menu_item(project, name)
-        item = Redmine::MenuManager.items(:project_menu).detect {|i| i.name.to_s == name.to_s}
-        if item && User.current.allowed_to?(item.url, project) && (item.condition.nil? || item.condition.call(project))
-          redirect_to({item.param => project}.merge(item.url))
-          return true
-        end
-        false
-      end
-    end
-
-    module MenuHelper
-      # Returns the current menu item name
-      def current_menu_item
-        controller.current_menu_item
-      end
-
-      # Renders the application main menu
-      def render_main_menu(project)
-        render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
-      end
-
-      def display_main_menu?(project)
-        menu_name = project && !project.new_record? ? :project_menu : :application_menu
-        Redmine::MenuManager.items(menu_name).children.present?
-      end
-
-      def render_menu(menu, project=nil)
-        links = []
-        menu_items_for(menu, project) do |node|
-          links << render_menu_node(node, project)
-        end
-        links.empty? ? nil : content_tag('ul', links.join("\n").html_safe)
-      end
-
-      def render_menu_node(node, project=nil)
-        if node.children.present? || !node.child_menus.nil?
-          return render_menu_node_with_children(node, project)
-        else
-          caption, url, selected = extract_node_details(node, project)
-          return content_tag('li',
-                               render_single_menu_node(node, caption, url, selected))
-        end
-      end
-
-      def render_menu_node_with_children(node, project=nil)
-        caption, url, selected = extract_node_details(node, project)
-
-        html = [].tap do |html|
-          html << '<li>'
-          # Parent
-          html << render_single_menu_node(node, caption, url, selected)
-
-          # Standard children
-          standard_children_list = "".html_safe.tap do |child_html|
-            node.children.each do |child|
-              child_html << render_menu_node(child, project)
-            end
-          end
-
-          html << content_tag(:ul, standard_children_list, :class => 'menu-children') unless standard_children_list.empty?
-
-          # Unattached children
-          unattached_children_list = render_unattached_children_menu(node, project)
-          html << content_tag(:ul, unattached_children_list, :class => 'menu-children unattached') unless unattached_children_list.blank?
-
-          html << '</li>'
-        end
-        return html.join("\n").html_safe
-      end
-
-      # Returns a list of unattached children menu items
-      def render_unattached_children_menu(node, project)
-        return nil unless node.child_menus
-
-        "".html_safe.tap do |child_html|
-          unattached_children = node.child_menus.call(project)
-          # Tree nodes support #each so we need to do object detection
-          if unattached_children.is_a? Array
-            unattached_children.each do |child|
-              child_html << content_tag(:li, render_unattached_menu_item(child, project))
-            end
-          else
-            raise MenuError, ":child_menus must be an array of MenuItems"
-          end
-        end
-      end
-
-      def render_single_menu_node(item, caption, url, selected)
-        link_to(h(caption), url, item.html_options(:selected => selected))
-      end
-
-      def render_unattached_menu_item(menu_item, project)
-        raise MenuError, ":child_menus must be an array of MenuItems" unless menu_item.is_a? MenuItem
-
-        if User.current.allowed_to?(menu_item.url, project)
-          link_to(h(menu_item.caption),
-                  menu_item.url,
-                  menu_item.html_options)
-        end
-      end
-
-      def menu_items_for(menu, project=nil)
-        items = []
-        Redmine::MenuManager.items(menu).root.children.each do |node|
-          if allowed_node?(node, User.current, project)
-            if block_given?
-              yield node
-            else
-              items << node  # TODO: not used?
-            end
-          end
-        end
-        return block_given? ? nil : items
-      end
-
-      def extract_node_details(node, project=nil)
-        item = node
-        url = case item.url
-        when Hash
-          project.nil? ? item.url : {item.param => project}.merge(item.url)
-        when Symbol
-          send(item.url)
-        else
-          item.url
-        end
-        caption = item.caption(project)
-        return [caption, url, (current_menu_item == item.name)]
-      end
-
-      # Checks if a user is allowed to access the menu item by:
-      #
-      # * Checking the url target (project only)
-      # * Checking the conditions of the item
-      def allowed_node?(node, user, project)
-        if project && user && !user.allowed_to?(node.url, project)
-          return false
-        end
-        if node.condition && !node.condition.call(project)
-          # Condition that doesn't pass
-          return false
-        end
-        return true
-      end
-    end
-
-    class << self
-      def map(menu_name)
-        @items ||= {}
-        mapper = Mapper.new(menu_name.to_sym, @items)
-        if block_given?
-          yield mapper
-        else
-          mapper
-        end
-      end
-
-      def items(menu_name)
-        @items[menu_name.to_sym] || MenuNode.new(:root, {})
-      end
-    end
-
-    class Mapper
-      attr_reader :menu, :menu_items
-
-      def initialize(menu, items)
-        items[menu] ||= MenuNode.new(:root, {})
-        @menu = menu
-        @menu_items = items[menu]
-      end
-
-      # Adds an item at the end of the menu. Available options:
-      # * param: the parameter name that is used for the project id (default is :id)
-      # * if: a Proc that is called before rendering the item, the item is displayed only if it returns true
-      # * caption that can be:
-      #   * a localized string Symbol
-      #   * a String
-      #   * a Proc that can take the project as argument
-      # * before, after: specify where the menu item should be inserted (eg. :after => :activity)
-      # * parent: menu item will be added as a child of another named menu (eg. :parent => :issues)
-      # * children: a Proc that is called before rendering the item. The Proc should return an array of MenuItems, which will be added as children to this item.
-      #   eg. :children => Proc.new {|project| [Redmine::MenuManager::MenuItem.new(...)] }
-      # * last: menu item will stay at the end (eg. :last => true)
-      # * html_options: a hash of html options that are passed to link_to
-      def push(name, url, options={})
-        options = options.dup
-
-        if options[:parent]
-          subtree = self.find(options[:parent])
-          if subtree
-            target_root = subtree
-          else
-            target_root = @menu_items.root
-          end
-
-        else
-          target_root = @menu_items.root
-        end
-
-        # menu item position
-        if first = options.delete(:first)
-          target_root.prepend(MenuItem.new(name, url, options))
-        elsif before = options.delete(:before)
-
-          if exists?(before)
-            target_root.add_at(MenuItem.new(name, url, options), position_of(before))
-          else
-            target_root.add(MenuItem.new(name, url, options))
-          end
-
-        elsif after = options.delete(:after)
-
-          if exists?(after)
-            target_root.add_at(MenuItem.new(name, url, options), position_of(after) + 1)
-          else
-            target_root.add(MenuItem.new(name, url, options))
-          end
-
-        elsif options[:last] # don't delete, needs to be stored
-          target_root.add_last(MenuItem.new(name, url, options))
-        else
-          target_root.add(MenuItem.new(name, url, options))
-        end
-      end
-
-      # Removes a menu item
-      def delete(name)
-        if found = self.find(name)
-          @menu_items.remove!(found)
-        end
-      end
-
-      # Checks if a menu item exists
-      def exists?(name)
-        @menu_items.any? {|node| node.name == name}
-      end
-
-      def find(name)
-        @menu_items.find {|node| node.name == name}
-      end
-
-      def position_of(name)
-        @menu_items.each do |node|
-          if node.name == name
-            return node.position
-          end
-        end
-      end
-    end
-
-    class MenuNode
-      include Enumerable
-      attr_accessor :parent
-      attr_reader :last_items_count, :name
-
-      def initialize(name, content = nil)
-        @name = name
-        @children = []
-        @last_items_count = 0
-      end
-
-      def children
-        if block_given?
-          @children.each {|child| yield child}
-        else
-          @children
-        end
-      end
-
-      # Returns the number of descendants + 1
-      def size
-        @children.inject(1) {|sum, node| sum + node.size}
-      end
-
-      def each &block
-        yield self
-        children { |child| child.each(&block) }
-      end
-
-      # Adds a child at first position
-      def prepend(child)
-        add_at(child, 0)
-      end
-
-      # Adds a child at given position
-      def add_at(child, position)
-        raise "Child already added" if find {|node| node.name == child.name}
-
-        @children = @children.insert(position, child)
-        child.parent = self
-        child
-      end
-
-      # Adds a child as last child
-      def add_last(child)
-        add_at(child, -1)
-        @last_items_count += 1
-        child
-      end
-
-      # Adds a child
-      def add(child)
-        position = @children.size - @last_items_count
-        add_at(child, position)
-      end
-      alias :<< :add
-
-      # Removes a child
-      def remove!(child)
-        @children.delete(child)
-        @last_items_count -= +1 if child && child.last
-        child.parent = nil
-        child
-      end
-
-      # Returns the position for this node in it's parent
-      def position
-        self.parent.children.index(self)
-      end
-
-      # Returns the root for this node
-      def root
-        root = self
-        root = root.parent while root.parent
-        root
-      end
-    end
-
-    class MenuItem < MenuNode
-      include Redmine::I18n
-      attr_reader :name, :url, :param, :condition, :parent, :child_menus, :last
-
-      def initialize(name, url, options)
-        raise ArgumentError, "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
-        raise ArgumentError, "Invalid option :html for menu item '#{name}'" if options[:html] && !options[:html].is_a?(Hash)
-        raise ArgumentError, "Cannot set the :parent to be the same as this item" if options[:parent] == name.to_sym
-        raise ArgumentError, "Invalid option :children for menu item '#{name}'" if options[:children] && !options[:children].respond_to?(:call)
-        @name = name
-        @url = url
-        @condition = options[:if]
-        @param = options[:param] || :id
-        @caption = options[:caption]
-        @html_options = options[:html] || {}
-        # Adds a unique class to each menu item based on its name
-        @html_options[:class] = [@html_options[:class], @name.to_s.dasherize].compact.join(' ')
-        @parent = options[:parent]
-        @child_menus = options[:children]
-        @last = options[:last] || false
-        super @name.to_sym
-      end
-
-      def caption(project=nil)
-        if @caption.is_a?(Proc)
-          c = @caption.call(project).to_s
-          c = @name.to_s.humanize if c.blank?
-          c
-        else
-          if @caption.nil?
-            l_or_humanize(name, :prefix => 'label_')
-          else
-            @caption.is_a?(Symbol) ? l(@caption) : @caption
-          end
-        end
-      end
-
-      def html_options(options={})
-        if options[:selected]
-          o = @html_options.dup
-          o[:class] += ' selected'
-          o
-        else
-          @html_options
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/17/17aa6f42b9915157fc191f136c4be06527af6f55.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::TrackersTest < Redmine::ApiTest::Base
-  fixtures :trackers
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /trackers.xml should return trackers" do
-    get '/trackers.xml'
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'trackers',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'tracker',
-        :child => {
-          :tag => 'id',
-          :content => '2',
-          :sibling => {
-            :tag => 'name',
-            :content => 'Feature request'
-          }
-        }
-      }
-  end
-end
--- a/.svn/pristine/17/17eeb63ea895552f87458a07894df799f570d379.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module RolesHelper
-end
--- a/.svn/pristine/18/182957517dcdfdb9bed4a7cc03f63aeef4b1c15d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class UserPreference < ActiveRecord::Base
-  belongs_to :user
-  serialize :others
-
-  attr_protected :others, :user_id
-
-  before_save :set_others_hash
-
-  def initialize(attributes=nil, *args)
-    super
-    self.others ||= {}
-  end
-
-  def set_others_hash
-    self.others ||= {}
-  end
-
-  def [](attr_name)
-    if has_attribute? attr_name
-      super
-    else
-      others ? others[attr_name] : nil
-    end
-  end
-
-  def []=(attr_name, value)
-    if has_attribute? attr_name
-      super
-    else
-      h = (read_attribute(:others) || {}).dup
-      h.update(attr_name => value)
-      write_attribute(:others, h)
-      value
-    end
-  end
-
-  def comments_sorting; self[:comments_sorting] end
-  def comments_sorting=(order); self[:comments_sorting]=order end
-
-  def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end
-  def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end
-
-  def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
-  def no_self_notified=(value); self[:no_self_notified]=value; end
-end
--- a/.svn/pristine/18/183dca49dc870131da0c794df1c3f5f569d0e6e5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module IssueStatusesHelper
-end
--- a/.svn/pristine/18/18aaa55b2d77150962ade434e4a8c39b73c97814.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesFilesystemControllerTest < ActionController::TestCase
-  tests RepositoriesController
-
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :repositories, :enabled_modules
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s
-  PRJ_ID = 3
-
-  def setup
-    @ruby19_non_utf8_pass =
-        (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
-    User.current = nil
-    Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem')
-    @project = Project.find(PRJ_ID)
-    @repository = Repository::Filesystem.create(
-                      :project       => @project,
-                      :url           => REPOSITORY_PATH,
-                      :path_encoding => ''
-                      )
-    assert @repository
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    def test_get_new
-      @request.session[:user_id] = 1
-      @project.repository.destroy
-      get :new, :project_id => 'subproject1', :repository_scm => 'Filesystem'
-      assert_response :success
-      assert_template 'new'
-      assert_kind_of Repository::Filesystem, assigns(:repository)
-      assert assigns(:repository).new_record?
-    end
-
-    def test_browse_root
-      @repository.fetch_changesets
-      @repository.reload
-      get :show, :id => PRJ_ID
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert assigns(:entries).size > 0
-      assert_not_nil assigns(:changesets)
-      assert assigns(:changesets).size == 0
-
-      assert_no_tag 'input', :attributes => {:name => 'rev'}
-      assert_no_tag 'a', :content => 'Statistics'
-      assert_no_tag 'a', :content => 'Atom'
-    end
-
-    def test_show_no_extension
-      get :entry, :id => PRJ_ID, :path => repository_path_hash(['test'])[:param]
-      assert_response :success
-      assert_template 'entry'
-      assert_tag :tag => 'th',
-                 :content => '1',
-                 :attributes => { :class => 'line-num' },
-                 :sibling => { :tag => 'td', :content => /TEST CAT/ }
-    end
-
-    def test_entry_download_no_extension
-      get :raw, :id => PRJ_ID, :path => repository_path_hash(['test'])[:param]
-      assert_response :success
-      assert_equal 'application/octet-stream', @response.content_type
-    end
-
-    def test_show_non_ascii_contents
-      with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
-        get :entry, :id => PRJ_ID,
-            :path => repository_path_hash(['japanese', 'euc-jp.txt'])[:param]
-        assert_response :success
-        assert_template 'entry'
-        assert_tag :tag => 'th',
-                   :content => '2',
-                   :attributes => { :class => 'line-num' },
-                   :sibling => { :tag => 'td', :content => /japanese/ }
-        if @ruby19_non_utf8_pass
-          puts "TODO: show repository file contents test fails in Ruby 1.9 " +
-               "and Encoding.default_external is not UTF-8. " +
-               "Current value is '#{Encoding.default_external.to_s}'"
-        else
-          str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
-          str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
-          assert_tag :tag => 'th',
-                     :content => '3',
-                     :attributes => { :class => 'line-num' },
-                     :sibling => { :tag => 'td', :content => /#{str_japanese}/ }
-        end
-      end
-    end
-
-    def test_show_utf16
-      enc = (RUBY_VERSION == "1.9.2" ? 'UTF-16LE' : 'UTF-16')
-      with_settings :repositories_encodings => enc do
-        get :entry, :id => PRJ_ID,
-            :path => repository_path_hash(['japanese', 'utf-16.txt'])[:param]
-        assert_response :success
-        assert_tag :tag => 'th',
-                   :content => '2',
-                   :attributes => { :class => 'line-num' },
-                   :sibling => { :tag => 'td', :content => /japanese/ }
-      end
-    end
-
-    def test_show_text_file_should_send_if_too_big
-      with_settings :file_max_size_displayed => 1 do
-        get :entry, :id => PRJ_ID,
-            :path => repository_path_hash(['japanese', 'big-file.txt'])[:param]
-        assert_response :success
-        assert_equal 'text/plain', @response.content_type
-      end
-    end
-
-    def test_destroy_valid_repository
-      @request.session[:user_id] = 1 # admin
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-
-    def test_destroy_invalid_repository
-      @request.session[:user_id] = 1 # admin
-      @project.repository.destroy
-      @repository = Repository::Filesystem.create!(
-                      :project       => @project,
-                      :url           => "/invalid",
-                      :path_encoding => ''
-                      )
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-  else
-    puts "Filesystem test repository NOT FOUND. Skipping functional tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/18/18af7ca4dac0c217561ab69b8406264b81adb03a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class UserCustomField < CustomField
-  def type_name
-    :label_user_plural
-  end
-end
-
--- a/.svn/pristine/19/190e5bea2d5dc9984a86fa22ae8cc4dd749898ab.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Search
-
-    mattr_accessor :available_search_types
-
-    @@available_search_types = []
-
-    class << self
-      def map(&block)
-        yield self
-      end
-
-      # Registers a search provider
-      def register(search_type, options={})
-        search_type = search_type.to_s
-        @@available_search_types << search_type unless @@available_search_types.include?(search_type)
-      end
-    end
-
-    module Controller
-      def self.included(base)
-        base.extend(ClassMethods)
-      end
-
-      module ClassMethods
-        @@default_search_scopes = Hash.new {|hash, key| hash[key] = {:default => nil, :actions => {}}}
-        mattr_accessor :default_search_scopes
-
-        # Set the default search scope for a controller or specific actions
-        # Examples:
-        #   * search_scope :issues # => sets the search scope to :issues for the whole controller
-        #   * search_scope :issues, :only => :index
-        #   * search_scope :issues, :only => [:index, :show]
-        def default_search_scope(id, options = {})
-          if actions = options[:only]
-            actions = [] << actions unless actions.is_a?(Array)
-            actions.each {|a| default_search_scopes[controller_name.to_sym][:actions][a.to_sym] = id.to_s}
-          else
-            default_search_scopes[controller_name.to_sym][:default] = id.to_s
-          end
-        end
-      end
-
-      def default_search_scopes
-        self.class.default_search_scopes
-      end
-
-      # Returns the default search scope according to the current action
-      def default_search_scope
-        @default_search_scope ||= default_search_scopes[controller_name.to_sym][:actions][action_name.to_sym] ||
-                                  default_search_scopes[controller_name.to_sym][:default]
-      end
-    end
-  end
-end
--- a/.svn/pristine/19/191c54aa364bc303830fb03453b541edfd9e5945.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Configuration
-
-    # Configuration default values
-    @defaults = {
-      'email_delivery' => nil,
-      'max_concurrent_ajax_uploads' => 2
-    }
-
-    @config = nil
-
-    class << self
-      # Loads the Redmine configuration file
-      # Valid options:
-      # * <tt>:file</tt>: the configuration file to load (default: config/configuration.yml)
-      # * <tt>:env</tt>: the environment to load the configuration for (default: Rails.env)
-      def load(options={})
-        filename = options[:file] || File.join(Rails.root, 'config', 'configuration.yml')
-        env = options[:env] || Rails.env
-
-        @config = @defaults.dup
-
-        load_deprecated_email_configuration(env)
-        if File.file?(filename)
-          @config.merge!(load_from_yaml(filename, env))
-        end
-
-        # Compatibility mode for those who copy email.yml over configuration.yml
-        %w(delivery_method smtp_settings sendmail_settings).each do |key|
-          if value = @config.delete(key)
-            @config['email_delivery'] ||= {}
-            @config['email_delivery'][key] = value
-          end
-        end
-
-        if @config['email_delivery']
-          ActionMailer::Base.perform_deliveries = true
-          @config['email_delivery'].each do |k, v|
-            v.symbolize_keys! if v.respond_to?(:symbolize_keys!)
-            ActionMailer::Base.send("#{k}=", v)
-          end
-        end
-
-        @config
-      end
-
-      # Returns a configuration setting
-      def [](name)
-        load unless @config
-        @config[name]
-      end
-
-      # Yields a block with the specified hash configuration settings
-      def with(settings)
-        settings.stringify_keys!
-        load unless @config
-        was = settings.keys.inject({}) {|h,v| h[v] = @config[v]; h}
-        @config.merge! settings
-        yield if block_given?
-        @config.merge! was
-      end
-
-      private
-
-      def load_from_yaml(filename, env)
-        yaml = nil
-        begin
-          yaml = YAML::load_file(filename)
-        rescue ArgumentError
-          $stderr.puts "Your Redmine configuration file located at #{filename} is not a valid YAML file and could not be loaded."
-          exit 1
-        end
-        conf = {}
-        if yaml.is_a?(Hash)
-          if yaml['default']
-            conf.merge!(yaml['default'])
-          end
-          if yaml[env]
-            conf.merge!(yaml[env])
-          end
-        else
-          $stderr.puts "Your Redmine configuration file located at #{filename} is not a valid Redmine configuration file."
-          exit 1
-        end
-        conf
-      end
-
-      def load_deprecated_email_configuration(env)
-        deprecated_email_conf = File.join(Rails.root, 'config', 'email.yml')
-        if File.file?(deprecated_email_conf)
-          warn "Storing outgoing emails configuration in config/email.yml is deprecated. You should now store it in config/configuration.yml using the email_delivery setting."
-          @config.merge!({'email_delivery' => load_from_yaml(deprecated_email_conf, env)})
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/1a/1a3135bf503a709c26b5156223514133ddf98de3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'diff'
-
-module Redmine
-  module Helpers
-    class Diff
-      include ERB::Util
-      include ActionView::Helpers::TagHelper
-      include ActionView::Helpers::TextHelper
-      attr_reader :diff, :words
-
-      def initialize(content_to, content_from)
-        @words = content_to.to_s.split(/(\s+)/)
-        @words = @words.select {|word| word != ' '}
-        words_from = content_from.to_s.split(/(\s+)/)
-        words_from = words_from.select {|word| word != ' '}
-        @diff = words_from.diff @words
-      end
-
-      def to_html
-        words = self.words.collect{|word| h(word)}
-        words_add = 0
-        words_del = 0
-        dels = 0
-        del_off = 0
-        diff.diffs.each do |diff|
-          add_at = nil
-          add_to = nil
-          del_at = nil
-          deleted = ""
-          diff.each do |change|
-            pos = change[1]
-            if change[0] == "+"
-              add_at = pos + dels unless add_at
-              add_to = pos + dels
-              words_add += 1
-            else
-              del_at = pos unless del_at
-              deleted << ' ' unless deleted.empty?
-              deleted << h(change[2])
-              words_del  += 1
-            end
-          end
-          if add_at
-            words[add_at] = '<span class="diff_in">'.html_safe + words[add_at]
-            words[add_to] = words[add_to] + '</span>'.html_safe
-          end
-          if del_at
-            words.insert del_at - del_off + dels + words_add, '<span class="diff_out">'.html_safe + deleted + '</span>'.html_safe
-            dels += 1
-            del_off += words_del
-            words_del = 0
-          end
-        end
-        words.join(' ').html_safe
-      end
-    end
-  end
-end
--- a/.svn/pristine/1a/1a57484f351c2899093aa4b926665fc8327667ab.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class LayoutTest < ActionController::IntegrationTest
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  test "browsing to a missing page should render the base layout" do
-    get "/users/100000000"
-
-    assert_response :not_found
-
-    # UsersController uses the admin layout by default
-    assert_select "#admin-menu", :count => 0
-  end
-
-  test "browsing to an unauthorized page should render the base layout" do
-    change_user_password('miscuser9', 'test1234')
-
-    log_user('miscuser9','test1234')
-
-    get "/admin"
-    assert_response :forbidden
-    assert_select "#admin-menu", :count => 0
-  end
-
-  def test_top_menu_and_search_not_visible_when_login_required
-    with_settings :login_required => '1' do
-      get '/'
-      assert_select "#top-menu > ul", 0
-      assert_select "#quick-search", 0
-    end
-  end
-
-  def test_top_menu_and_search_visible_when_login_not_required
-    with_settings :login_required => '0' do
-      get '/'
-      assert_select "#top-menu > ul"
-      assert_select "#quick-search"
-    end
-  end
-
-  def test_wiki_formatter_header_tags
-    Role.anonymous.add_permission! :add_issues
-
-    get '/projects/ecookbook/issues/new'
-    assert_tag :script,
-      :attributes => {:src => %r{^/javascripts/jstoolbar/jstoolbar-textile.min.js}},
-      :parent => {:tag => 'head'}
-  end
-
-  def test_calendar_header_tags
-    with_settings :default_language => 'fr' do
-      get '/issues'
-      assert_include "/javascripts/i18n/jquery.ui.datepicker-fr.js", response.body
-    end
-
-    with_settings :default_language => 'en-GB' do
-      get '/issues'
-      assert_include "/javascripts/i18n/jquery.ui.datepicker-en-GB.js", response.body
-    end
-
-    with_settings :default_language => 'en' do
-      get '/issues'
-      assert_not_include "/javascripts/i18n/jquery.ui.datepicker", response.body
-    end
-
-    with_settings :default_language => 'zh' do
-      get '/issues'
-      assert_include "/javascripts/i18n/jquery.ui.datepicker-zh-CN.js", response.body
-    end
-
-    with_settings :default_language => 'zh-TW' do
-      get '/issues'
-      assert_include "/javascripts/i18n/jquery.ui.datepicker-zh-TW.js", response.body
-    end
-
-    with_settings :default_language => 'pt' do
-      get '/issues'
-      assert_include "/javascripts/i18n/jquery.ui.datepicker-pt.js", response.body
-    end
-
-    with_settings :default_language => 'pt-BR' do
-      get '/issues'
-      assert_include "/javascripts/i18n/jquery.ui.datepicker-pt-BR.js", response.body
-    end
-  end
-
-  def test_search_field_outside_project_should_link_to_global_search
-    get '/'
-    assert_select 'div#quick-search form[action=/search]'
-  end
-
-  def test_search_field_inside_project_should_link_to_project_search
-    get '/projects/ecookbook'
-    assert_select 'div#quick-search form[action=/projects/ecookbook/search]'
-  end
-end
--- a/.svn/pristine/1a/1a5ac9a1d7cbc1a58738649fabccca79dc7633e5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingWikisTest < ActionController::IntegrationTest
-  def test_wikis_plural_admin_setup
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/projects/ladida/wiki/destroy" },
-          { :controller => 'wikis', :action => 'destroy', :id => 'ladida' }
-        )
-    end
-    assert_routing(
-        { :method => 'post', :path => "/projects/ladida/wiki" },
-        { :controller => 'wikis', :action => 'edit', :id => 'ladida' }
-      )
-  end
-end
--- a/.svn/pristine/1a/1a8020fad87f2bec2c86c62dc30a6bf033a7c796.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1268 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class ApplicationHelperTest < ActionView::TestCase
-  include Redmine::I18n
-  include ERB::Util
-  include Rails.application.routes.url_helpers
-
-  fixtures :projects, :roles, :enabled_modules, :users,
-           :repositories, :changesets,
-           :trackers, :issue_statuses, :issues, :versions, :documents,
-           :wikis, :wiki_pages, :wiki_contents,
-           :boards, :messages, :news,
-           :attachments, :enumerations
-
-  def setup
-    super
-    set_tmp_attachments_directory
-    @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82"
-    if @russian_test.respond_to?(:force_encoding)
-      @russian_test.force_encoding('UTF-8')
-    end
-  end
-
-  test "#link_to_if_authorized for authorized user should allow using the :controller and :action for the target link" do
-    User.current = User.find_by_login('admin')
-
-    @project = Issue.first.project # Used by helper
-    response = link_to_if_authorized('By controller/actionr',
-                                    {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
-    assert_match /href/, response
-  end
-
-  test "#link_to_if_authorized for unauthorized user should display nothing if user isn't authorized" do
-    User.current = User.find_by_login('dlopper')
-    @project = Project.find('private-child')
-    issue = @project.issues.first
-    assert !issue.visible?
-
-    response = link_to_if_authorized('Never displayed',
-                                    {:controller => 'issues', :action => 'show', :id => issue})
-    assert_nil response
-  end
-
-  def test_auto_links
-    to_test = {
-      'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
-      'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
-      'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
-      'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
-      'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
-      'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
-      'http://foo.bar/foo.bar#foo.bar.' => '<a class="external" href="http://foo.bar/foo.bar#foo.bar">http://foo.bar/foo.bar#foo.bar</a>.',
-      'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
-      '(see inline link : http://www.foo.bar/Test_(foobar))' => '(see inline link : <a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>)',
-      '(see inline link : http://www.foo.bar/Test)' => '(see inline link : <a class="external" href="http://www.foo.bar/Test">http://www.foo.bar/Test</a>)',
-      '(see inline link : http://www.foo.bar/Test).' => '(see inline link : <a class="external" href="http://www.foo.bar/Test">http://www.foo.bar/Test</a>).',
-      '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
-      '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
-      '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
-      'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
-      'http://foo.bar/page?p=1&t=z&s=' => '<a class="external" href="http://foo.bar/page?p=1&#38;t=z&#38;s=">http://foo.bar/page?p=1&#38;t=z&#38;s=</a>',
-      'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
-      'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
-      'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
-      'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
-      'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
-      'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
-      # two exclamation marks
-      'http://example.net/path!602815048C7B5C20!302.html' => '<a class="external" href="http://example.net/path!602815048C7B5C20!302.html">http://example.net/path!602815048C7B5C20!302.html</a>',
-      # escaping
-      'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo&quot;bar</a>',
-      # wrap in angle brackets
-      '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;',
-      # invalid urls
-      'http://' => 'http://',
-      'www.' => 'www.',
-      'test-www.bar.com' => 'test-www.bar.com',
-    }
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-  end
-
-  if 'ruby'.respond_to?(:encoding)
-    def test_auto_links_with_non_ascii_characters
-      to_test = {
-        "http://foo.bar/#{@russian_test}" =>
-          %|<a class="external" href="http://foo.bar/#{@russian_test}">http://foo.bar/#{@russian_test}</a>|
-      }
-      to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-    end
-  else
-    puts 'Skipping test_auto_links_with_non_ascii_characters, unsupported ruby version'
-  end
-
-  def test_auto_mailto
-    to_test = {
-      'test@foo.bar' => '<a class="email" href="mailto:test@foo.bar">test@foo.bar</a>',
-      'test@www.foo.bar' => '<a class="email" href="mailto:test@www.foo.bar">test@www.foo.bar</a>',
-    }
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-  end
-
-  def test_inline_images
-    to_test = {
-      '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
-      'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
-      'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
-      'with style !{width:100px;height:100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" style="width:100px;height:100px;" alt="" />',
-      'with title !http://foo.bar/image.jpg(This is a title)!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a title" alt="This is a title" />',
-      'with title !http://foo.bar/image.jpg(This is a double-quoted "title")!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a double-quoted &quot;title&quot;" alt="This is a double-quoted &quot;title&quot;" />',
-    }
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-  end
-
-  def test_inline_images_inside_tags
-    raw = <<-RAW
-h1. !foo.png! Heading
-
-Centered image:
-
-p=. !bar.gif!
-RAW
-
-    assert textilizable(raw).include?('<img src="foo.png" alt="" />')
-    assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
-  end
-
-  def test_attached_images
-    to_test = {
-      'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
-      'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
-      'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
-      'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
-      # link image
-      '!logo.gif!:http://foo.bar/' => '<a href="http://foo.bar/"><img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" /></a>',
-    }
-    attachments = Attachment.all
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
-  end
-
-  def test_attached_images_filename_extension
-    set_tmp_attachments_directory
-    a1 = Attachment.new(
-            :container => Issue.find(1),
-            :file => mock_file_with_options({:original_filename => "testtest.JPG"}),
-            :author => User.find(1))
-    assert a1.save
-    assert_equal "testtest.JPG", a1.filename
-    assert_equal "image/jpeg", a1.content_type
-    assert a1.image?
-
-    a2 = Attachment.new(
-            :container => Issue.find(1),
-            :file => mock_file_with_options({:original_filename => "testtest.jpeg"}),
-            :author => User.find(1))
-    assert a2.save
-    assert_equal "testtest.jpeg", a2.filename
-    assert_equal "image/jpeg", a2.content_type
-    assert a2.image?
-
-    a3 = Attachment.new(
-            :container => Issue.find(1),
-            :file => mock_file_with_options({:original_filename => "testtest.JPE"}),
-            :author => User.find(1))
-    assert a3.save
-    assert_equal "testtest.JPE", a3.filename
-    assert_equal "image/jpeg", a3.content_type
-    assert a3.image?
-
-    a4 = Attachment.new(
-            :container => Issue.find(1),
-            :file => mock_file_with_options({:original_filename => "Testtest.BMP"}),
-            :author => User.find(1))
-    assert a4.save
-    assert_equal "Testtest.BMP", a4.filename
-    assert_equal "image/x-ms-bmp", a4.content_type
-    assert a4.image?
-
-    to_test = {
-      'Inline image: !testtest.jpg!' =>
-        'Inline image: <img src="/attachments/download/' + a1.id.to_s + '/testtest.JPG" alt="" />',
-      'Inline image: !testtest.jpeg!' =>
-        'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testtest.jpeg" alt="" />',
-      'Inline image: !testtest.jpe!' =>
-        'Inline image: <img src="/attachments/download/' + a3.id.to_s + '/testtest.JPE" alt="" />',
-      'Inline image: !testtest.bmp!' =>
-        'Inline image: <img src="/attachments/download/' + a4.id.to_s + '/Testtest.BMP" alt="" />',
-    }
-
-    attachments = [a1, a2, a3, a4]
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
-  end
-
-  def test_attached_images_should_read_later
-    set_fixtures_attachments_directory
-    a1 = Attachment.find(16)
-    assert_equal "testfile.png", a1.filename
-    assert a1.readable?
-    assert (! a1.visible?(User.anonymous))
-    assert a1.visible?(User.find(2))
-    a2 = Attachment.find(17)
-    assert_equal "testfile.PNG", a2.filename
-    assert a2.readable?
-    assert (! a2.visible?(User.anonymous))
-    assert a2.visible?(User.find(2))
-    assert a1.created_on < a2.created_on
-
-    to_test = {
-      'Inline image: !testfile.png!' =>
-        'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
-      'Inline image: !Testfile.PNG!' =>
-        'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
-    }
-    attachments = [a1, a2]
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
-    set_tmp_attachments_directory
-  end
-
-  def test_textile_external_links
-    to_test = {
-      'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
-      'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
-      '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
-      '"link (Link title with "double-quotes")":http://foo.bar' => '<a href="http://foo.bar" title="Link title with &quot;double-quotes&quot;" class="external">link</a>',
-      "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
-      # no multiline link text
-      "This is a double quote \"on the first line\nand another on a second line\":test" => "This is a double quote \"on the first line<br />and another on a second line\":test",
-      # mailto link
-      "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
-      # two exclamation marks
-      '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
-      # escaping
-      '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
-    }
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-  end
-
-  if 'ruby'.respond_to?(:encoding)
-    def test_textile_external_links_with_non_ascii_characters
-      to_test = {
-        %|This is a "link":http://foo.bar/#{@russian_test}| =>
-          %|This is a <a href="http://foo.bar/#{@russian_test}" class="external">link</a>|
-      }
-      to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-    end
-  else
-    puts 'Skipping test_textile_external_links_with_non_ascii_characters, unsupported ruby version'
-  end
-
-  def test_redmine_links
-    issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
-                               :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
-    note_link = link_to('#3-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
-                               :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
-    note_link2 = link_to('#3#note-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
-                               :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
-
-    revision_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
-                                   :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
-    revision_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
-                                    :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
-
-    changeset_link2 = link_to('691322a8eb01e11fd7',
-                              {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
-                               :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
-
-    document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
-                                             :class => 'document')
-
-    version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
-                                  :class => 'version')
-
-    board_url = {:controller => 'boards', :action => 'show', :id => 2, :project_id => 'ecookbook'}
-
-    message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
-    
-    news_url = {:controller => 'news', :action => 'show', :id => 1}
-
-    project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
-
-    source_url = '/projects/ecookbook/repository/entry/some/file'
-    source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file'
-    source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext'
-    source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext'
-    source_url_with_branch = '/projects/ecookbook/repository/revisions/branch/entry/some/file'
-
-    export_url = '/projects/ecookbook/repository/raw/some/file'
-    export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file'
-    export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext'
-    export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext'
-    export_url_with_branch = '/projects/ecookbook/repository/revisions/branch/raw/some/file'
-
-    to_test = {
-      # tickets
-      '#3, [#3], (#3) and #3.'      => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
-      # ticket notes
-      '#3-14'                       => note_link,
-      '#3#note-14'                  => note_link2,
-      # should not ignore leading zero
-      '#03'                         => '#03',
-      # changesets
-      'r1'                          => revision_link,
-      'r1.'                         => "#{revision_link}.",
-      'r1, r2'                      => "#{revision_link}, #{revision_link2}",
-      'r1,r2'                       => "#{revision_link},#{revision_link2}",
-      'commit:691322a8eb01e11fd7'   => changeset_link2,
-      # documents
-      'document#1'                  => document_link,
-      'document:"Test document"'    => document_link,
-      # versions
-      'version#2'                   => version_link,
-      'version:1.0'                 => version_link,
-      'version:"1.0"'               => version_link,
-      # source
-      'source:some/file'            => link_to('source:some/file', source_url, :class => 'source'),
-      'source:/some/file'           => link_to('source:/some/file', source_url, :class => 'source'),
-      'source:/some/file.'          => link_to('source:/some/file', source_url, :class => 'source') + ".",
-      'source:/some/file.ext.'      => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
-      'source:/some/file. '         => link_to('source:/some/file', source_url, :class => 'source') + ".",
-      'source:/some/file.ext. '     => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
-      'source:/some/file, '         => link_to('source:/some/file', source_url, :class => 'source') + ",",
-      'source:/some/file@52'        => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'),
-      'source:/some/file@branch'    => link_to('source:/some/file@branch', source_url_with_branch, :class => 'source'),
-      'source:/some/file.ext@52'    => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'),
-      'source:/some/file#L110'      => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'),
-      'source:/some/file.ext#L110'  => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'),
-      'source:/some/file@52#L110'   => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'),
-      # export
-      'export:/some/file'           => link_to('export:/some/file', export_url, :class => 'source download'),
-      'export:/some/file.ext'       => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'),
-      'export:/some/file@52'        => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'),
-      'export:/some/file.ext@52'    => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'),
-      'export:/some/file@branch'    => link_to('export:/some/file@branch', export_url_with_branch, :class => 'source download'),
-      # forum
-      'forum#2'                     => link_to('Discussion', board_url, :class => 'board'),
-      'forum:Discussion'            => link_to('Discussion', board_url, :class => 'board'),
-      # message
-      'message#4'                   => link_to('Post 2', message_url, :class => 'message'),
-      'message#5'                   => link_to('RE: post 2', message_url.merge(:anchor => 'message-5', :r => 5), :class => 'message'),
-      # news
-      'news#1'                      => link_to('eCookbook first release !', news_url, :class => 'news'),
-      'news:"eCookbook first release !"'        => link_to('eCookbook first release !', news_url, :class => 'news'),
-      # project
-      'project#3'                   => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
-      'project:subproject1'         => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
-      'project:"eCookbook subProject 1"'        => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
-      # not found
-      '#0123456789'                 => '#0123456789',
-      # invalid expressions
-      'source:'                     => 'source:',
-      # url hash
-      "http://foo.bar/FAQ#3"       => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
-    }
-    @project = Project.find(1)
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
-  end
-
-  def test_redmine_links_with_a_different_project_before_current_project
-    vp1 = Version.generate!(:project_id => 1, :name => '1.4.4')
-    vp3 = Version.generate!(:project_id => 3, :name => '1.4.4')
-
-    @project = Project.find(3)
-    assert_equal %(<p><a href="/versions/#{vp1.id}" class="version">1.4.4</a> <a href="/versions/#{vp3.id}" class="version">1.4.4</a></p>),
-      textilizable("ecookbook:version:1.4.4 version:1.4.4")
-  end
-
-  def test_escaped_redmine_links_should_not_be_parsed
-    to_test = [
-      '#3.',
-      '#3-14.',
-      '#3#-note14.',
-      'r1',
-      'document#1',
-      'document:"Test document"',
-      'version#2',
-      'version:1.0',
-      'version:"1.0"',
-      'source:/some/file'
-    ]
-    @project = Project.find(1)
-    to_test.each { |text| assert_equal "<p>#{text}</p>", textilizable("!" + text), "#{text} failed" }
-  end
-
-  def test_cross_project_redmine_links
-    source_link = link_to('ecookbook:source:/some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']},
-      :class => 'source')
-
-    changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
-      :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
-
-    to_test = {
-      # documents
-      'document:"Test document"'              => 'document:"Test document"',
-      'ecookbook:document:"Test document"'    => '<a href="/documents/1" class="document">Test document</a>',
-      'invalid:document:"Test document"'      => 'invalid:document:"Test document"',
-      # versions
-      'version:"1.0"'                         => 'version:"1.0"',
-      'ecookbook:version:"1.0"'               => '<a href="/versions/2" class="version">1.0</a>',
-      'invalid:version:"1.0"'                 => 'invalid:version:"1.0"',
-      # changeset
-      'r2'                                    => 'r2',
-      'ecookbook:r2'                          => changeset_link,
-      'invalid:r2'                            => 'invalid:r2',
-      # source
-      'source:/some/file'                     => 'source:/some/file',
-      'ecookbook:source:/some/file'           => source_link,
-      'invalid:source:/some/file'             => 'invalid:source:/some/file',
-    }
-    @project = Project.find(3)
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
-  end
-
-  def test_multiple_repositories_redmine_links
-    svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg')
-    Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
-    hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
-    Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
-
-    changeset_link = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
-                                    :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
-    svn_changeset_link = link_to('svn_repo-1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn_repo-1', :rev => 123},
-                                    :class => 'changeset', :title => '')
-    hg_changeset_link = link_to('hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
-                                    :class => 'changeset', :title => '')
-
-    source_link = link_to('source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
-    hg_source_link = link_to('source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
-
-    to_test = {
-      'r2'                          => changeset_link,
-      'svn_repo-1|r123'             => svn_changeset_link,
-      'invalid|r123'                => 'invalid|r123',
-      'commit:hg1|abcd'             => hg_changeset_link,
-      'commit:invalid|abcd'         => 'commit:invalid|abcd',
-      # source
-      'source:some/file'            => source_link,
-      'source:hg1|some/file'        => hg_source_link,
-      'source:invalid|some/file'    => 'source:invalid|some/file',
-    }
-
-    @project = Project.find(1)
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
-  end
-
-  def test_cross_project_multiple_repositories_redmine_links
-    svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///foo/hg')
-    Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
-    hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
-    Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
-
-    changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
-                                    :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
-    svn_changeset_link = link_to('ecookbook:svn1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn1', :rev => 123},
-                                    :class => 'changeset', :title => '')
-    hg_changeset_link = link_to('ecookbook:hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
-                                    :class => 'changeset', :title => '')
-
-    source_link = link_to('ecookbook:source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
-    hg_source_link = link_to('ecookbook:source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
-
-    to_test = {
-      'ecookbook:r2'                           => changeset_link,
-      'ecookbook:svn1|r123'                    => svn_changeset_link,
-      'ecookbook:invalid|r123'                 => 'ecookbook:invalid|r123',
-      'ecookbook:commit:hg1|abcd'              => hg_changeset_link,
-      'ecookbook:commit:invalid|abcd'          => 'ecookbook:commit:invalid|abcd',
-      'invalid:commit:invalid|abcd'            => 'invalid:commit:invalid|abcd',
-      # source
-      'ecookbook:source:some/file'             => source_link,
-      'ecookbook:source:hg1|some/file'         => hg_source_link,
-      'ecookbook:source:invalid|some/file'     => 'ecookbook:source:invalid|some/file',
-      'invalid:source:invalid|some/file'       => 'invalid:source:invalid|some/file',
-    }
-
-    @project = Project.find(3)
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
-  end
-
-  def test_redmine_links_git_commit
-    changeset_link = link_to('abcd',
-                               {
-                                 :controller => 'repositories',
-                                 :action     => 'revision',
-                                 :id         => 'subproject1',
-                                 :rev        => 'abcd',
-                                },
-                              :class => 'changeset', :title => 'test commit')
-    to_test = {
-      'commit:abcd' => changeset_link,
-     }
-    @project = Project.find(3)
-    r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
-    assert r
-    c = Changeset.new(:repository => r,
-                      :committed_on => Time.now,
-                      :revision => 'abcd',
-                      :scmid => 'abcd',
-                      :comments => 'test commit')
-    assert( c.save )
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-  end
-
-  # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
-  def test_redmine_links_darcs_commit
-    changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
-                               {
-                                 :controller => 'repositories',
-                                 :action     => 'revision',
-                                 :id         => 'subproject1',
-                                 :rev        => '123',
-                                },
-                              :class => 'changeset', :title => 'test commit')
-    to_test = {
-      'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
-     }
-    @project = Project.find(3)
-    r = Repository::Darcs.create!(
-            :project => @project, :url => '/tmp/test/darcs',
-            :log_encoding => 'UTF-8')
-    assert r
-    c = Changeset.new(:repository => r,
-                      :committed_on => Time.now,
-                      :revision => '123',
-                      :scmid => '20080308225258-98289-abcd456efg.gz',
-                      :comments => 'test commit')
-    assert( c.save )
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-  end
-
-  def test_redmine_links_mercurial_commit
-    changeset_link_rev = link_to('r123',
-                                  {
-                                     :controller => 'repositories',
-                                     :action     => 'revision',
-                                     :id         => 'subproject1',
-                                     :rev        => '123' ,
-                                  },
-                              :class => 'changeset', :title => 'test commit')
-    changeset_link_commit = link_to('abcd',
-                                  {
-                                        :controller => 'repositories',
-                                        :action     => 'revision',
-                                        :id         => 'subproject1',
-                                        :rev        => 'abcd' ,
-                                  },
-                              :class => 'changeset', :title => 'test commit')
-    to_test = {
-      'r123' => changeset_link_rev,
-      'commit:abcd' => changeset_link_commit,
-     }
-    @project = Project.find(3)
-    r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
-    assert r
-    c = Changeset.new(:repository => r,
-                      :committed_on => Time.now,
-                      :revision => '123',
-                      :scmid => 'abcd',
-                      :comments => 'test commit')
-    assert( c.save )
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-  end
-
-  def test_attachment_links
-    to_test = {
-      'attachment:error281.txt' => '<a href="/attachments/download/1/error281.txt" class="attachment">error281.txt</a>'
-    }
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" }
-  end
-
-  def test_attachment_link_should_link_to_latest_attachment
-    set_tmp_attachments_directory
-    a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
-    a2 = Attachment.generate!(:filename => "test.txt")
-
-    assert_equal %(<p><a href="/attachments/download/#{a2.id}/test.txt" class="attachment">test.txt</a></p>),
-      textilizable('attachment:test.txt', :attachments => [a1, a2])
-  end
-
-  def test_wiki_links
-    russian_eacape = CGI.escape(@russian_test)
-    to_test = {
-      '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
-      '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
-      # title content should be formatted
-      '[[Another page|With _styled_ *title*]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">With <em>styled</em> <strong>title</strong></a>',
-      '[[Another page|With title containing <strong>HTML entities &amp; markups</strong>]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">With title containing &lt;strong&gt;HTML entities &amp; markups&lt;/strong&gt;</a>',
-      # link with anchor
-      '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
-      '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>',
-      # UTF8 anchor
-      "[[Another_page##{@russian_test}|#{@russian_test}]]" =>
-         %|<a href="/projects/ecookbook/wiki/Another_page##{russian_eacape}" class="wiki-page">#{@russian_test}</a>|,
-      # page that doesn't exist
-      '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
-      '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
-      # link to another project wiki
-      '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">onlinestore</a>',
-      '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">Wiki</a>',
-      '[[onlinestore:Start page]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Start page</a>',
-      '[[onlinestore:Start page|Text]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Text</a>',
-      '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
-      # striked through link
-      '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>',
-      '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>',
-      # escaping
-      '![[Another page|Page]]' => '[[Another page|Page]]',
-      # project does not exist
-      '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
-      '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
-    }
-
-    @project = Project.find(1)
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-  end
-
-  def test_wiki_links_within_local_file_generation_context
-
-    to_test = {
-      # link to a page
-      '[[CookBook documentation]]' => '<a href="CookBook_documentation.html" class="wiki-page">CookBook documentation</a>',
-      '[[CookBook documentation|documentation]]' => '<a href="CookBook_documentation.html" class="wiki-page">documentation</a>',
-      '[[CookBook documentation#One-section]]' => '<a href="CookBook_documentation.html#One-section" class="wiki-page">CookBook documentation</a>',
-      '[[CookBook documentation#One-section|documentation]]' => '<a href="CookBook_documentation.html#One-section" class="wiki-page">documentation</a>',
-      # page that doesn't exist
-      '[[Unknown page]]' => '<a href="Unknown_page.html" class="wiki-page new">Unknown page</a>',
-      '[[Unknown page|404]]' => '<a href="Unknown_page.html" class="wiki-page new">404</a>',
-      '[[Unknown page#anchor]]' => '<a href="Unknown_page.html#anchor" class="wiki-page new">Unknown page</a>',
-      '[[Unknown page#anchor|404]]' => '<a href="Unknown_page.html#anchor" class="wiki-page new">404</a>',
-    }
-
-    @project = Project.find(1)
-
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local) }
-  end
-
-  def test_wiki_links_within_wiki_page_context
-
-    page = WikiPage.find_by_title('Another_page' )
-
-    to_test = {
-      # link to another page
-      '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
-      '[[CookBook documentation|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">documentation</a>',
-      '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
-      '[[CookBook documentation#One-section|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">documentation</a>',
-      # link to the current page
-      '[[Another page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Another page</a>',
-      '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
-      '[[Another page#anchor]]' => '<a href="#anchor" class="wiki-page">Another page</a>',
-      '[[Another page#anchor|Page]]' => '<a href="#anchor" class="wiki-page">Page</a>',
-      # page that doesn't exist
-      '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page" class="wiki-page new">Unknown page</a>',
-      '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page" class="wiki-page new">404</a>',
-      '[[Unknown page#anchor]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor" class="wiki-page new">Unknown page</a>',
-      '[[Unknown page#anchor|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor" class="wiki-page new">404</a>',
-    }
-
-    @project = Project.find(1)
-
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(WikiContent.new( :text => text, :page => page ), :text) }
-  end
-
-  def test_wiki_links_anchor_option_should_prepend_page_title_to_href
-
-    to_test = {
-      # link to a page
-      '[[CookBook documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">CookBook documentation</a>',
-      '[[CookBook documentation|documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">documentation</a>',
-      '[[CookBook documentation#One-section]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">CookBook documentation</a>',
-      '[[CookBook documentation#One-section|documentation]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">documentation</a>',
-      # page that doesn't exist
-      '[[Unknown page]]' => '<a href="#Unknown_page" class="wiki-page new">Unknown page</a>',
-      '[[Unknown page|404]]' => '<a href="#Unknown_page" class="wiki-page new">404</a>',
-      '[[Unknown page#anchor]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">Unknown page</a>',
-      '[[Unknown page#anchor|404]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">404</a>',
-    }
-
-    @project = Project.find(1)
-
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor) }
-  end
-
-  def test_html_tags
-    to_test = {
-      "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
-      "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
-      "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
-      # do not escape pre/code tags
-      "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
-      "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
-      "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
-      "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
-      "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
-      # remove attributes except class
-      "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
-      '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
-      "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
-      '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
-      "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
-      # xss
-      '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
-      '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
-    }
-    to_test.each { |text, result| assert_equal result, textilizable(text) }
-  end
-
-  def test_allowed_html_tags
-    to_test = {
-      "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
-      "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
-      "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
-    }
-    to_test.each { |text, result| assert_equal result, textilizable(text) }
-  end
-
-  def test_pre_tags
-    raw = <<-RAW
-Before
-
-<pre>
-<prepared-statement-cache-size>32</prepared-statement-cache-size>
-</pre>
-
-After
-RAW
-
-    expected = <<-EXPECTED
-<p>Before</p>
-<pre>
-&lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
-</pre>
-<p>After</p>
-EXPECTED
-
-    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
-  end
-
-  def test_pre_content_should_not_parse_wiki_and_redmine_links
-    raw = <<-RAW
-[[CookBook documentation]]
-  
-#1
-
-<pre>
-[[CookBook documentation]]
-  
-#1
-</pre>
-RAW
-
-    expected = <<-EXPECTED
-<p><a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a></p>
-<p><a href="/issues/1" class="#{Issue.find(1).css_classes}" title="Can&#x27;t print recipes (New)">#1</a></p>
-<pre>
-[[CookBook documentation]]
-
-#1
-</pre>
-EXPECTED
-
-    @project = Project.find(1)
-    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
-  end
-
-  def test_non_closing_pre_blocks_should_be_closed
-    raw = <<-RAW
-<pre><code>
-RAW
-
-    expected = <<-EXPECTED
-<pre><code>
-</code></pre>
-EXPECTED
-
-    @project = Project.find(1)
-    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
-  end
-
-  def test_syntax_highlight
-    raw = <<-RAW
-<pre><code class="ruby">
-# Some ruby code here
-</code></pre>
-RAW
-
-    expected = <<-EXPECTED
-<pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="comment"># Some ruby code here</span></span>
-</code></pre>
-EXPECTED
-
-    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
-  end
-
-  def test_to_path_param
-    assert_equal 'test1/test2', to_path_param('test1/test2')
-    assert_equal 'test1/test2', to_path_param('/test1/test2/')
-    assert_equal 'test1/test2', to_path_param('//test1/test2/')
-    assert_equal nil, to_path_param('/')
-  end
-
-  def test_wiki_links_in_tables
-    to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" =>
-                 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' +
-                 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' +
-                 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>'
-    }
-    @project = Project.find(1)
-    to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
-  end
-
-  def test_text_formatting
-    to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
-               '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
-               'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
-               'a H *umane* W *eb* T *ext* G *enerator*' => 'a H <strong>umane</strong> W <strong>eb</strong> T <strong>ext</strong> G <strong>enerator</strong>',
-               'a *H* umane *W* eb *T* ext *G* enerator' => 'a <strong>H</strong> umane <strong>W</strong> eb <strong>T</strong> ext <strong>G</strong> enerator',
-              }
-    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-  end
-
-  def test_wiki_horizontal_rule
-    assert_equal '<hr />', textilizable('---')
-    assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
-  end
-
-  def test_footnotes
-    raw = <<-RAW
-This is some text[1].
-
-fn1. This is the foot note
-RAW
-
-    expected = <<-EXPECTED
-<p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
-<p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
-EXPECTED
-
-    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
-  end
-
-  def test_headings
-    raw = 'h1. Some heading'
-    expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
-
-    assert_equal expected, textilizable(raw)
-  end
-
-  def test_headings_with_special_chars
-    # This test makes sure that the generated anchor names match the expected
-    # ones even if the heading text contains unconventional characters
-    raw = 'h1. Some heading related to version 0.5'
-    anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
-    expected = %|<a name="#{anchor}"></a>\n<h1 >Some heading related to version 0.5<a href="##{anchor}" class="wiki-anchor">&para;</a></h1>|
-
-    assert_equal expected, textilizable(raw)
-  end
-
-  def test_headings_in_wiki_single_page_export_should_be_prepended_with_page_title
-    page = WikiPage.new( :title => 'Page Title', :wiki_id => 1 )
-    content = WikiContent.new( :text => 'h1. Some heading', :page => page )
-
-    expected = %|<a name="Page_Title_Some-heading"></a>\n<h1 >Some heading<a href="#Page_Title_Some-heading" class="wiki-anchor">&para;</a></h1>|
-
-    assert_equal expected, textilizable(content, :text, :wiki_links => :anchor )
-  end
-
-  def test_table_of_content
-    raw = <<-RAW
-{{toc}}
-
-h1. Title
-
-Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
-
-h2. Subtitle with a [[Wiki]] link
-
-Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
-
-h2. Subtitle with [[Wiki|another Wiki]] link
-
-h2. Subtitle with %{color:red}red text%
-
-<pre>
-some code
-</pre>
-
-h3. Subtitle with *some* _modifiers_
-
-h3. Subtitle with @inline code@
-
-h1. Another title
-
-h3. An "Internet link":http://www.redmine.org/ inside subtitle
-
-h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
-
-RAW
-
-    expected =  '<ul class="toc">' +
-                  '<li><a href="#Title">Title</a>' +
-                    '<ul>' +
-                      '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
-                      '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
-                      '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
-                        '<ul>' +
-                          '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
-                          '<li><a href="#Subtitle-with-inline-code">Subtitle with inline code</a></li>' +
-                        '</ul>' +
-                      '</li>' +
-                    '</ul>' +
-                  '</li>' +
-                  '<li><a href="#Another-title">Another title</a>' +
-                    '<ul>' +
-                      '<li>' +
-                        '<ul>' +
-                          '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
-                        '</ul>' +
-                      '</li>' +
-                      '<li><a href="#Project-Name">Project Name</a></li>' +
-                    '</ul>' +
-                  '</li>' +
-               '</ul>'
-
-    @project = Project.find(1)
-    assert textilizable(raw).gsub("\n", "").include?(expected)
-  end
-
-  def test_table_of_content_should_generate_unique_anchors
-    raw = <<-RAW
-{{toc}}
-
-h1. Title
-
-h2. Subtitle
-
-h2. Subtitle
-RAW
-
-    expected =  '<ul class="toc">' +
-                  '<li><a href="#Title">Title</a>' +
-                    '<ul>' +
-                      '<li><a href="#Subtitle">Subtitle</a></li>' +
-                      '<li><a href="#Subtitle-2">Subtitle</a></li>'
-                    '</ul>'
-                  '</li>' +
-               '</ul>'
-
-    @project = Project.find(1)
-    result = textilizable(raw).gsub("\n", "")
-    assert_include expected, result
-    assert_include '<a name="Subtitle">', result
-    assert_include '<a name="Subtitle-2">', result
-  end
-
-  def test_table_of_content_should_contain_included_page_headings
-    raw = <<-RAW
-{{toc}}
-
-h1. Included
-
-{{include(Child_1)}}
-RAW
-
-    expected = '<ul class="toc">' +
-               '<li><a href="#Included">Included</a></li>' +
-               '<li><a href="#Child-page-1">Child page 1</a></li>' +
-               '</ul>'
-
-    @project = Project.find(1)
-    assert textilizable(raw).gsub("\n", "").include?(expected)
-  end
-
-  def test_section_edit_links
-    raw = <<-RAW
-h1. Title
-
-Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
-
-h2. Subtitle with a [[Wiki]] link
-
-h2. Subtitle with *some* _modifiers_
-
-h2. Subtitle with @inline code@
-
-<pre>
-some code
-
-h2. heading inside pre
-
-<h2>html heading inside pre</h2>
-</pre>
-
-h2. Subtitle after pre tag
-RAW
-
-    @project = Project.find(1)
-    set_language_if_valid 'en'
-    result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
-
-    # heading that contains inline code
-    assert_match Regexp.new('<div class="contextual" id="section-4" title="Edit this section">' +
-      '<a href="/projects/1/wiki/Test/edit\?section=4"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
-      '<a name="Subtitle-with-inline-code"></a>' +
-      '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'),
-      result
-
-    # last heading
-    assert_match Regexp.new('<div class="contextual" id="section-5" title="Edit this section">' +
-      '<a href="/projects/1/wiki/Test/edit\?section=5"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
-      '<a name="Subtitle-after-pre-tag"></a>' +
-      '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'),
-      result
-  end
-
-  def test_default_formatter
-    with_settings :text_formatting => 'unknown' do
-      text = 'a *link*: http://www.example.net/'
-      assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
-    end
-  end
-
-  def test_due_date_distance_in_words
-    to_test = { Date.today => 'Due in 0 days',
-                Date.today + 1 => 'Due in 1 day',
-                Date.today + 100 => 'Due in about 3 months',
-                Date.today + 20000 => 'Due in over 54 years',
-                Date.today - 1 => '1 day late',
-                Date.today - 100 => 'about 3 months late',
-                Date.today - 20000 => 'over 54 years late',
-               }
-    ::I18n.locale = :en
-    to_test.each do |date, expected|
-      assert_equal expected, due_date_distance_in_words(date)
-    end
-  end
-
-  def test_avatar_enabled
-    with_settings :gravatar_enabled => '1' do
-      assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
-      assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
-      # Default size is 50
-      assert avatar('jsmith <jsmith@somenet.foo>').include?('size=50')
-      assert avatar('jsmith <jsmith@somenet.foo>', :size => 24).include?('size=24')
-      # Non-avatar options should be considered html options
-      assert avatar('jsmith <jsmith@somenet.foo>', :title => 'John Smith').include?('title="John Smith"')
-      # The default class of the img tag should be gravatar
-      assert avatar('jsmith <jsmith@somenet.foo>').include?('class="gravatar"')
-      assert !avatar('jsmith <jsmith@somenet.foo>', :class => 'picture').include?('class="gravatar"')
-      assert_nil avatar('jsmith')
-      assert_nil avatar(nil)
-    end
-  end
-
-  def test_avatar_disabled
-    with_settings :gravatar_enabled => '0' do
-      assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
-    end
-  end
-
-  def test_link_to_user
-    user = User.find(2)
-    assert_equal '<a href="/users/2" class="user active">John Smith</a>', link_to_user(user)
-  end
-
-  def test_link_to_user_should_not_link_to_locked_user
-    with_current_user nil do
-      user = User.find(5)
-      assert user.locked?
-      assert_equal 'Dave2 Lopper2', link_to_user(user)
-    end
-  end
-
-  def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
-    with_current_user User.find(1) do
-      user = User.find(5)
-      assert user.locked?
-      assert_equal '<a href="/users/5" class="user locked">Dave2 Lopper2</a>', link_to_user(user)
-    end
-  end
-
-  def test_link_to_user_should_not_link_to_anonymous
-    user = User.anonymous
-    assert user.anonymous?
-    t = link_to_user(user)
-    assert_equal ::I18n.t(:label_user_anonymous), t
-  end
-
-  def test_link_to_attachment
-    a = Attachment.find(3)
-    assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
-      link_to_attachment(a)
-    assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
-      link_to_attachment(a, :text => 'Text')
-    assert_equal '<a href="/attachments/3/logo.gif" class="foo">logo.gif</a>',
-      link_to_attachment(a, :class => 'foo')
-    assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
-      link_to_attachment(a, :download => true)
-    assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
-      link_to_attachment(a, :only_path => false)
-  end
-
-  def test_thumbnail_tag
-    a = Attachment.find(3)
-    assert_equal '<a href="/attachments/3/logo.gif" title="logo.gif"><img alt="3" src="/attachments/thumbnail/3" /></a>',
-      thumbnail_tag(a)
-  end
-
-  def test_link_to_project
-    project = Project.find(1)
-    assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
-                 link_to_project(project)
-    assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
-                 link_to_project(project, :action => 'settings')
-    assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
-                 link_to_project(project, {:only_path => false, :jump => 'blah'})
-    assert_equal %(<a href="/projects/ecookbook/settings" class="project">eCookbook</a>),
-                 link_to_project(project, {:action => 'settings'}, :class => "project")
-  end
-
-  def test_link_to_project_settings
-    project = Project.find(1)
-    assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
-
-    project.status = Project::STATUS_CLOSED
-    assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
-
-    project.status = Project::STATUS_ARCHIVED
-    assert_equal 'eCookbook', link_to_project_settings(project)
-  end
-
-  def test_link_to_legacy_project_with_numerical_identifier_should_use_id
-    # numeric identifier are no longer allowed
-    Project.update_all "identifier=25", "id=1"
-
-    assert_equal '<a href="/projects/1">eCookbook</a>',
-                 link_to_project(Project.find(1))
-  end
-
-  def test_principals_options_for_select_with_users
-    User.current = nil
-    users = [User.find(2), User.find(4)]
-    assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
-      principals_options_for_select(users)
-  end
-
-  def test_principals_options_for_select_with_selected
-    User.current = nil
-    users = [User.find(2), User.find(4)]
-    assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
-      principals_options_for_select(users, User.find(4))
-  end
-
-  def test_principals_options_for_select_with_users_and_groups
-    User.current = nil
-    users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
-    assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
-      %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
-      principals_options_for_select(users)
-  end
-
-  def test_principals_options_for_select_with_empty_collection
-    assert_equal '', principals_options_for_select([])
-  end
-
-  def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
-    users = [User.find(2), User.find(4)]
-    User.current = User.find(4)
-    assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
-  end
-
-  def test_stylesheet_link_tag_should_pick_the_default_stylesheet
-    assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
-  end
-
-  def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
-    assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
-  end
-
-  def test_image_tag_should_pick_the_default_image
-    assert_match 'src="/images/image.png"', image_tag("image.png")
-  end
-
-  def test_image_tag_should_pick_the_theme_image_if_it_exists
-    theme = Redmine::Themes.themes.last
-    theme.images << 'image.png'
-
-    with_settings :ui_theme => theme.id do
-      assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
-      assert_match %|src="/images/other.png"|, image_tag("other.png")
-    end
-  ensure
-    theme.images.delete 'image.png'
-  end
-
-  def test_image_tag_sfor_plugin_should_pick_the_plugin_image
-    assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
-  end
-
-  def test_javascript_include_tag_should_pick_the_default_javascript
-    assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
-  end
-
-  def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
-    assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
-  end
-
-  def test_raw_json_should_escape_closing_tags
-    s = raw_json(["<foo>bar</foo>"])
-    assert_equal '["<foo>bar<\/foo>"]', s
-  end
-
-  def test_raw_json_should_be_html_safe
-    s = raw_json(["foo"])
-    assert s.html_safe?
-  end
-
-  def test_html_title_should_app_title_if_not_set
-    assert_equal 'Redmine', html_title
-  end
-
-  def test_html_title_should_join_items
-    html_title 'Foo', 'Bar'
-    assert_equal 'Foo - Bar - Redmine', html_title
-  end
-
-  def test_html_title_should_append_current_project_name
-    @project = Project.find(1)
-    html_title 'Foo', 'Bar'
-    assert_equal 'Foo - Bar - eCookbook - Redmine', html_title
-  end
-
-  def test_title_should_return_a_h2_tag
-    assert_equal '<h2>Foo</h2>', title('Foo')
-  end
-
-  def test_title_should_set_html_title
-    title('Foo')
-    assert_equal 'Foo - Redmine', html_title
-  end
-
-  def test_title_should_turn_arrays_into_links
-    assert_equal '<h2><a href="/foo">Foo</a></h2>', title(['Foo', '/foo'])
-    assert_equal 'Foo - Redmine', html_title
-  end
-
-  def test_title_should_join_items
-    assert_equal '<h2>Foo &#187; Bar</h2>', title('Foo', 'Bar')
-    assert_equal 'Bar - Foo - Redmine', html_title
-  end
-end
--- a/.svn/pristine/1a/1ae3258fdcdf6aa143d4aa4fdfd79484152c6554.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module MembersHelper
-  def render_principals_for_new_members(project)
-    scope = Principal.active.sorted.not_member_of(project).like(params[:q])
-    principal_count = scope.count
-    principal_pages = Redmine::Pagination::Paginator.new principal_count, 100, params['page']
-    principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
-
-    s = content_tag('div', principals_check_box_tags('membership[user_ids][]', principals), :id => 'principals')
-
-    links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
-      link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
-    }
-
-    s + content_tag('p', links, :class => 'pagination')
-  end
-end
--- a/.svn/pristine/1b/1b56f9a09e214e641bcc7750244e8fb8e49ba7c3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class BoardsControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles, :boards, :messages, :enabled_modules
-
-  def setup
-    User.current = nil
-  end
-
-  def test_index
-    get :index, :project_id => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:boards)
-    assert_not_nil assigns(:project)
-  end
-
-  def test_index_not_found
-    get :index, :project_id => 97
-    assert_response 404
-  end
-
-  def test_index_should_show_messages_if_only_one_board
-    Project.find(1).boards.slice(1..-1).each(&:destroy)
-
-    get :index, :project_id => 1
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:topics)
-  end
-
-  def test_show
-    get :show, :project_id => 1, :id => 1
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:board)
-    assert_not_nil assigns(:project)
-    assert_not_nil assigns(:topics)
-  end
-
-  def test_show_should_display_sticky_messages_first
-    Message.update_all(:sticky => 0)
-    Message.update_all({:sticky => 1}, {:id => 1})
-
-    get :show, :project_id => 1, :id => 1
-    assert_response :success
-
-    topics = assigns(:topics)
-    assert_not_nil topics
-    assert topics.size > 1, "topics size was #{topics.size}"
-    assert topics.first.sticky?
-    assert topics.first.updated_on < topics.second.updated_on
-  end
-
-  def test_show_should_display_message_with_last_reply_first
-    Message.update_all(:sticky => 0)
-
-    # Reply to an old topic
-    old_topic = Message.where(:board_id => 1, :parent_id => nil).order('created_on ASC').first
-    reply = Message.new(:board_id => 1, :subject => 'New reply', :content => 'New reply', :author_id => 2)
-    old_topic.children << reply
-
-    get :show, :project_id => 1, :id => 1
-    assert_response :success
-    topics = assigns(:topics)
-    assert_not_nil topics
-    assert_equal old_topic, topics.first
-  end
-
-  def test_show_with_permission_should_display_the_new_message_form
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :id => 1
-    assert_response :success
-    assert_template 'show'
-
-    assert_select 'form#message-form' do
-      assert_select 'input[name=?]', 'message[subject]'
-    end
-  end
-
-  def test_show_atom
-    get :show, :project_id => 1, :id => 1, :format => 'atom'
-    assert_response :success
-    assert_template 'common/feed'
-    assert_not_nil assigns(:board)
-    assert_not_nil assigns(:project)
-    assert_not_nil assigns(:messages)
-  end
-
-  def test_show_not_found
-    get :index, :project_id => 1, :id => 97
-    assert_response 404
-  end
-
-  def test_new
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'select[name=?]', 'board[parent_id]' do
-      assert_select 'option', (Project.find(1).boards.size + 1)
-      assert_select 'option[value=]', :text => '&nbsp;'
-      assert_select 'option[value=1]', :text => 'Help'
-    end
-  end
-
-  def test_new_without_project_boards
-    Project.find(1).boards.delete_all
-    @request.session[:user_id] = 2
-
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'select[name=?]', 'board[parent_id]', 0
-  end
-
-  def test_create
-    @request.session[:user_id] = 2
-    assert_difference 'Board.count' do
-      post :create, :project_id => 1, :board => { :name => 'Testing', :description => 'Testing board creation'}
-    end
-    assert_redirected_to '/projects/ecookbook/settings/boards'
-    board = Board.first(:order => 'id DESC')
-    assert_equal 'Testing', board.name
-    assert_equal 'Testing board creation', board.description
-  end
-
-  def test_create_with_parent
-    @request.session[:user_id] = 2
-    assert_difference 'Board.count' do
-      post :create, :project_id => 1, :board => { :name => 'Testing', :description => 'Testing', :parent_id => 2}
-    end
-    assert_redirected_to '/projects/ecookbook/settings/boards'
-    board = Board.first(:order => 'id DESC')
-    assert_equal Board.find(2), board.parent
-  end
-
-  def test_create_with_failure
-    @request.session[:user_id] = 2
-    assert_no_difference 'Board.count' do
-      post :create, :project_id => 1, :board => { :name => '', :description => 'Testing board creation'}
-    end
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_edit
-    @request.session[:user_id] = 2
-    get :edit, :project_id => 1, :id => 2
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_edit_with_parent
-    board = Board.generate!(:project_id => 1, :parent_id => 2)
-    @request.session[:user_id] = 2
-    get :edit, :project_id => 1, :id => board.id
-    assert_response :success
-    assert_template 'edit'
-
-    assert_select 'select[name=?]', 'board[parent_id]' do
-      assert_select 'option[value=2][selected=selected]'
-    end
-  end
-
-  def test_update
-    @request.session[:user_id] = 2
-    assert_no_difference 'Board.count' do
-      put :update, :project_id => 1, :id => 2, :board => { :name => 'Testing', :description => 'Testing board update'}
-    end
-    assert_redirected_to '/projects/ecookbook/settings/boards'
-    assert_equal 'Testing', Board.find(2).name
-  end
-
-  def test_update_position
-    @request.session[:user_id] = 2
-    put :update, :project_id => 1, :id => 2, :board => { :move_to => 'highest'}
-    assert_redirected_to '/projects/ecookbook/settings/boards'
-    board = Board.find(2)
-    assert_equal 1, board.position
-  end
-
-  def test_update_with_failure
-    @request.session[:user_id] = 2
-    put :update, :project_id => 1, :id => 2, :board => { :name => '', :description => 'Testing board update'}
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_destroy
-    @request.session[:user_id] = 2
-    assert_difference 'Board.count', -1 do
-      delete :destroy, :project_id => 1, :id => 2
-    end
-    assert_redirected_to '/projects/ecookbook/settings/boards'
-    assert_nil Board.find_by_id(2)
-  end
-end
--- a/.svn/pristine/1c/1c27182fa8ab48906fb7a4d556796242f651644e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Pagination
-    class Paginator
-      attr_reader :item_count, :per_page, :page, :page_param
-
-      def initialize(*args)
-        if args.first.is_a?(ActionController::Base)
-          args.shift
-          ActiveSupport::Deprecation.warn "Paginator no longer takes a controller instance as the first argument. Remove it from #new arguments."
-        end
-        item_count, per_page, page, page_param = *args
-
-        @item_count = item_count
-        @per_page = per_page
-        page = (page || 1).to_i
-        if page < 1
-          page = 1
-        end
-        @page = page
-        @page_param = page_param || :page
-      end
-
-      def offset
-        (page - 1) * per_page
-      end
-
-      def first_page
-        if item_count > 0
-          1
-        end
-      end
-
-      def previous_page
-        if page > 1
-          page - 1
-        end
-      end
-
-      def next_page
-        if last_item < item_count
-          page + 1
-        end
-      end
-
-      def last_page
-        if item_count > 0
-          (item_count - 1) / per_page + 1
-        end
-      end
-
-      def first_item
-        item_count == 0 ? 0 : (offset + 1)
-      end
-
-      def last_item
-        l = first_item + per_page - 1
-        l > item_count ? item_count : l
-      end
-
-      def linked_pages
-        pages = []
-        if item_count > 0
-          pages += [first_page, page, last_page]
-          pages += ((page-2)..(page+2)).to_a.select {|p| p > first_page && p < last_page}
-        end
-        pages = pages.compact.uniq.sort
-        if pages.size > 1
-          pages
-        else
-          []
-        end
-      end
-
-      def items_per_page
-        ActiveSupport::Deprecation.warn "Paginator#items_per_page will be removed. Use #per_page instead."
-        per_page
-      end
-
-      def current
-        ActiveSupport::Deprecation.warn "Paginator#current will be removed. Use .offset instead of .current.offset."
-        self
-      end
-    end
-
-    # Paginates the given scope or model. Returns a Paginator instance and
-    # the collection of objects for the current page.
-    #
-    # Options:
-    #   :parameter     name of the page parameter
-    #
-    # Examples:
-    #   @user_pages, @users = paginate User.where(:status => 1)
-    #
-    def paginate(scope, options={})
-      options = options.dup
-      finder_options = options.extract!(
-        :conditions,
-        :order,
-        :joins,
-        :include,
-        :select
-      )
-      if scope.is_a?(Symbol) || finder_options.values.compact.any?
-        return deprecated_paginate(scope, finder_options, options)
-      end
-
-      paginator = paginator(scope.count, options)
-      collection = scope.limit(paginator.per_page).offset(paginator.offset).to_a
-
-      return paginator, collection
-    end
-
-    def deprecated_paginate(arg, finder_options, options={})
-      ActiveSupport::Deprecation.warn "#paginate with a Symbol and/or find options is depreceted and will be removed. Use a scope instead."
-      klass = arg.is_a?(Symbol) ? arg.to_s.classify.constantize : arg
-      scope = klass.scoped(finder_options)
-      paginate(scope, options)
-    end
-
-    def paginator(item_count, options={})
-      options.assert_valid_keys :parameter, :per_page
-
-      page_param = options[:parameter] || :page
-      page = (params[page_param] || 1).to_i
-      per_page = options[:per_page] || per_page_option
-      Paginator.new(item_count, per_page, page, page_param)
-    end
-
-    module Helper
-      include Redmine::I18n
-
-      # Renders the pagination links for the given paginator.
-      #
-      # Options:
-      #   :per_page_links    if set to false, the "Per page" links are not rendered
-      #
-      def pagination_links_full(*args)
-        pagination_links_each(*args) do |text, parameters, options|
-          if block_given?
-            yield text, parameters, options
-          else
-            link_to text, params.merge(parameters), options
-          end
-        end
-      end
-
-      # Yields the given block with the text and parameters
-      # for each pagination link and returns a string that represents the links
-      def pagination_links_each(paginator, count=nil, options={}, &block)
-        options.assert_valid_keys :per_page_links
-
-        per_page_links = options.delete(:per_page_links)
-        per_page_links = false if count.nil?
-        page_param = paginator.page_param
-
-        html = ''
-        if paginator.previous_page
-          # \xc2\xab(utf-8) = &#171;
-          text = "\xc2\xab " + l(:label_previous)
-          html << yield(text, {page_param => paginator.previous_page}, :class => 'previous') + ' '
-        end
-
-        previous = nil
-        paginator.linked_pages.each do |page|
-          if previous && previous != page - 1
-            html << content_tag('span', '...', :class => 'spacer') + ' '
-          end
-          if page == paginator.page
-            html << content_tag('span', page.to_s, :class => 'current page')
-          else
-            html << yield(page.to_s, {page_param => page}, :class => 'page')
-          end
-          html << ' '
-          previous = page
-        end
-
-        if paginator.next_page
-          # \xc2\xbb(utf-8) = &#187;
-          text = l(:label_next) + " \xc2\xbb"
-          html << yield(text, {page_param => paginator.next_page}, :class => 'next') + ' '
-        end
-
-        html << content_tag('span', "(#{paginator.first_item}-#{paginator.last_item}/#{paginator.item_count})", :class => 'items') + ' '
-
-        if per_page_links != false && links = per_page_links(paginator, &block)
-          html << content_tag('span', links.to_s, :class => 'per-page')
-        end
-
-        html.html_safe
-      end
-
-      # Renders the "Per page" links.
-      def per_page_links(paginator, &block)
-        values = per_page_options(paginator.per_page, paginator.item_count)
-        if values.any?
-          links = values.collect do |n|
-            if n == paginator.per_page
-              content_tag('span', n.to_s)
-            else
-              yield(n, :per_page => n, paginator.page_param => nil)
-            end
-          end
-          l(:label_display_per_page, links.join(', ')).html_safe
-        end
-      end
-
-      def per_page_options(selected=nil, item_count=nil)
-        options = Setting.per_page_options_array
-        if item_count && options.any?
-          if item_count > options.first
-            max = options.detect {|value| value >= item_count} || item_count
-          else
-            max = item_count
-          end
-          options = options.select {|value| value <= max || value == selected}
-        end
-        if options.empty? || (options.size == 1 && options.first == selected)
-          []
-        else
-          options
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/1d/1d8c43c17d3233bffb7ec0f72aeb2fc2a1c616a9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class CustomValueTest < ActiveSupport::TestCase
-  fixtures :custom_fields, :custom_values, :users
-
-  def test_default_value
-    field = CustomField.find_by_default_value('Default string')
-    assert_not_nil field
-
-    v = CustomValue.new(:custom_field => field)
-    assert_equal 'Default string', v.value
-
-    v = CustomValue.new(:custom_field => field, :value => 'Not empty')
-    assert_equal 'Not empty', v.value
-  end
-
-  def test_sti_polymorphic_association
-    # Rails uses top level sti class for polymorphic association. See #3978.
-    assert !User.find(4).custom_values.empty?
-    assert !CustomValue.find(2).customized.nil?
-  end
-end
--- a/.svn/pristine/1e/1e23a74057f558ab69d6074a0eabbe9696b5a8db.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Acts
-    module Searchable
-      def self.included(base)
-        base.extend ClassMethods
-      end
-
-      module ClassMethods
-        # Options:
-        # * :columns - a column or an array of columns to search
-        # * :project_key - project foreign key (default to project_id)
-        # * :date_column - name of the datetime column (default to created_on)
-        # * :sort_order - name of the column used to sort results (default to :date_column or created_on)
-        # * :permission - permission required to search the model (default to :view_"objects")
-        def acts_as_searchable(options = {})
-          return if self.included_modules.include?(Redmine::Acts::Searchable::InstanceMethods)
-
-          cattr_accessor :searchable_options
-          self.searchable_options = options
-
-          if searchable_options[:columns].nil?
-            raise 'No searchable column defined.'
-          elsif !searchable_options[:columns].is_a?(Array)
-            searchable_options[:columns] = [] << searchable_options[:columns]
-          end
-
-          searchable_options[:project_key] ||= "#{table_name}.project_id"
-          searchable_options[:date_column] ||= "#{table_name}.created_on"
-          searchable_options[:order_column] ||= searchable_options[:date_column]
-
-          # Should we search custom fields on this model ?
-          searchable_options[:search_custom_fields] = !reflect_on_association(:custom_values).nil?
-
-          send :include, Redmine::Acts::Searchable::InstanceMethods
-        end
-      end
-
-      module InstanceMethods
-        def self.included(base)
-          base.extend ClassMethods
-        end
-
-        module ClassMethods
-          # Searches the model for the given tokens
-          # projects argument can be either nil (will search all projects), a project or an array of projects
-          # Returns the results and the results count
-          def search(tokens, projects=nil, options={})
-            if projects.is_a?(Array) && projects.empty?
-              # no results
-              return [[], 0]
-            end
-
-            # TODO: make user an argument
-            user = User.current
-            tokens = [] << tokens unless tokens.is_a?(Array)
-            projects = [] << projects unless projects.nil? || projects.is_a?(Array)
-
-            limit_options = {}
-            limit_options[:limit] = options[:limit] if options[:limit]
-
-            columns = searchable_options[:columns]
-            columns = columns[0..0] if options[:titles_only]
-
-            token_clauses = columns.collect {|column| "(LOWER(#{column}) LIKE ?)"}
-
-            if !options[:titles_only] && searchable_options[:search_custom_fields]
-              searchable_custom_fields = CustomField.where(:type => "#{self.name}CustomField", :searchable => true)
-              searchable_custom_fields.each do |field|
-                sql = "#{table_name}.id IN (SELECT customized_id FROM #{CustomValue.table_name}" +
-                  " WHERE customized_type='#{self.name}' AND customized_id=#{table_name}.id AND LOWER(value) LIKE ?" +
-                  " AND #{CustomValue.table_name}.custom_field_id = #{field.id})" +
-                  " AND #{field.visibility_by_project_condition(searchable_options[:project_key], user)}"
-                token_clauses << sql
-              end
-            end
-
-            sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(options[:all_words] ? ' AND ' : ' OR ')
-
-            tokens_conditions = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort]
-
-            scope = self.scoped
-            project_conditions = []
-            if searchable_options.has_key?(:permission)
-              project_conditions << Project.allowed_to_condition(user, searchable_options[:permission] || :view_project)
-            elsif respond_to?(:visible)
-              scope = scope.visible(user)
-            else
-              ActiveSupport::Deprecation.warn "acts_as_searchable with implicit :permission option is deprecated. Add a visible scope to the #{self.name} model or use explicit :permission option."
-              project_conditions << Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym)
-            end
-            # TODO: use visible scope options instead
-            project_conditions << "#{searchable_options[:project_key]} IN (#{projects.collect(&:id).join(',')})" unless projects.nil?
-            project_conditions = project_conditions.empty? ? nil : project_conditions.join(' AND ')
-
-            results = []
-            results_count = 0
-
-            scope = scope.
-              includes(searchable_options[:include]).
-              order("#{searchable_options[:order_column]} " + (options[:before] ? 'DESC' : 'ASC')).
-              where(project_conditions).
-              where(tokens_conditions)
-
-            results_count = scope.count
-
-            scope_with_limit = scope.limit(options[:limit])
-            if options[:offset]
-              scope_with_limit = scope_with_limit.where("#{searchable_options[:date_column]} #{options[:before] ? '<' : '>'} ?", options[:offset])
-            end
-            results = scope_with_limit.all
-
-            [results, results_count]
-          end
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/1e/1e54d19d4970142ec949fe4202f5ffe30b1f8dbf.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::DisabledRestApiTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def setup
-    Setting.rest_api_enabled = '0'
-    Setting.login_required = '1'
-  end
-
-  def teardown
-    Setting.rest_api_enabled = '1'
-    Setting.login_required = '0'
-  end
-
-  def test_with_a_valid_api_token
-    @user = User.generate!
-    @token = Token.create!(:user => @user, :action => 'api')
-
-    get "/news.xml?key=#{@token.value}"
-    assert_response :unauthorized
-    assert_equal User.anonymous, User.current
-
-    get "/news.json?key=#{@token.value}"
-    assert_response :unauthorized
-    assert_equal User.anonymous, User.current
-  end
-
-  def test_with_valid_username_password_http_authentication
-    @user = User.generate! do |user|
-      user.password = 'my_password'
-    end
-
-    get "/news.xml", nil, credentials(@user.login, 'my_password')
-    assert_response :unauthorized
-    assert_equal User.anonymous, User.current
-
-    get "/news.json", nil, credentials(@user.login, 'my_password')
-    assert_response :unauthorized
-    assert_equal User.anonymous, User.current
-  end
-
-  def test_with_valid_token_http_authentication
-    @user = User.generate!
-    @token = Token.create!(:user => @user, :action => 'api')
-
-    get "/news.xml", nil, credentials(@token.value, 'X')
-    assert_response :unauthorized
-    assert_equal User.anonymous, User.current
-
-    get "/news.json", nil, credentials(@token.value, 'X')
-    assert_response :unauthorized
-    assert_equal User.anonymous, User.current
-  end
-end
--- a/.svn/pristine/1f/1f46b0be9dff718da9b5754753e6d89331b5e22e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module AuthSourcesHelper
-  def auth_source_partial_name(auth_source)
-    "form_#{auth_source.class.name.underscore}"
-  end
-end
--- a/.svn/pristine/1f/1f882abb5f1807e56ffd3445088d6c8aa33ef8e5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,593 +0,0 @@
-/* Redmine - project management software
-   Copyright (C) 2006-2013  Jean-Philippe Lang */
-
-function checkAll(id, checked) {
-  $('#'+id).find('input[type=checkbox]:enabled').attr('checked', checked);
-}
-
-function toggleCheckboxesBySelector(selector) {
-  var all_checked = true;
-  $(selector).each(function(index) {
-    if (!$(this).is(':checked')) { all_checked = false; }
-  });
-  $(selector).attr('checked', !all_checked);
-}
-
-function showAndScrollTo(id, focus) {
-  $('#'+id).show();
-  if (focus !== null) {
-    $('#'+focus).focus();
-  }
-  $('html, body').animate({scrollTop: $('#'+id).offset().top}, 100);
-}
-
-function toggleRowGroup(el) {
-  var tr = $(el).parents('tr').first();
-  var n = tr.next();
-  tr.toggleClass('open');
-  while (n.length && !n.hasClass('group')) {
-    n.toggle();
-    n = n.next('tr');
-  }
-}
-
-function collapseAllRowGroups(el) {
-  var tbody = $(el).parents('tbody').first();
-  tbody.children('tr').each(function(index) {
-    if ($(this).hasClass('group')) {
-      $(this).removeClass('open');
-    } else {
-      $(this).hide();
-    }
-  });
-}
-
-function expandAllRowGroups(el) {
-  var tbody = $(el).parents('tbody').first();
-  tbody.children('tr').each(function(index) {
-    if ($(this).hasClass('group')) {
-      $(this).addClass('open');
-    } else {
-      $(this).show();
-    }
-  });
-}
-
-function toggleAllRowGroups(el) {
-  var tr = $(el).parents('tr').first();
-  if (tr.hasClass('open')) {
-    collapseAllRowGroups(el);
-  } else {
-    expandAllRowGroups(el);
-  }
-}
-
-function toggleFieldset(el) {
-  var fieldset = $(el).parents('fieldset').first();
-  fieldset.toggleClass('collapsed');
-  fieldset.children('div').toggle();
-}
-
-function hideFieldset(el) {
-  var fieldset = $(el).parents('fieldset').first();
-  fieldset.toggleClass('collapsed');
-  fieldset.children('div').hide();
-}
-
-function initFilters() {
-  $('#add_filter_select').change(function() {
-    addFilter($(this).val(), '', []);
-  });
-  $('#filters-table td.field input[type=checkbox]').each(function() {
-    toggleFilter($(this).val());
-  });
-  $('#filters-table td.field input[type=checkbox]').live('click', function() {
-    toggleFilter($(this).val());
-  });
-  $('#filters-table .toggle-multiselect').live('click', function() {
-    toggleMultiSelect($(this).siblings('select'));
-  });
-  $('#filters-table input[type=text]').live('keypress', function(e) {
-    if (e.keyCode == 13) submit_query_form("query_form");
-  });
-}
-
-function addFilter(field, operator, values) {
-  var fieldId = field.replace('.', '_');
-  var tr = $('#tr_'+fieldId);
-  if (tr.length > 0) {
-    tr.show();
-  } else {
-    buildFilterRow(field, operator, values);
-  }
-  $('#cb_'+fieldId).attr('checked', true);
-  toggleFilter(field);
-  $('#add_filter_select').val('').children('option').each(function() {
-    if ($(this).attr('value') == field) {
-      $(this).attr('disabled', true);
-    }
-  });
-}
-
-function buildFilterRow(field, operator, values) {
-  var fieldId = field.replace('.', '_');
-  var filterTable = $("#filters-table");
-  var filterOptions = availableFilters[field];
-  if (!filterOptions) return;
-  var operators = operatorByType[filterOptions['type']];
-  var filterValues = filterOptions['values'];
-  var i, select;
-
-  var tr = $('<tr class="filter">').attr('id', 'tr_'+fieldId).html(
-    '<td class="field"><input checked="checked" id="cb_'+fieldId+'" name="f[]" value="'+field+'" type="checkbox"><label for="cb_'+fieldId+'"> '+filterOptions['name']+'</label></td>' +
-    '<td class="operator"><select id="operators_'+fieldId+'" name="op['+field+']"></td>' +
-    '<td class="values"></td>'
-  );
-  filterTable.append(tr);
-
-  select = tr.find('td.operator select');
-  for (i = 0; i < operators.length; i++) {
-    var option = $('<option>').val(operators[i]).text(operatorLabels[operators[i]]);
-    if (operators[i] == operator) { option.attr('selected', true); }
-    select.append(option);
-  }
-  select.change(function(){ toggleOperator(field); });
-
-  switch (filterOptions['type']) {
-  case "list":
-  case "list_optional":
-  case "list_status":
-  case "list_subprojects":
-    tr.find('td.values').append(
-      '<span style="display:none;"><select class="value" id="values_'+fieldId+'_1" name="v['+field+'][]"></select>' +
-      ' <span class="toggle-multiselect">&nbsp;</span></span>'
-    );
-    select = tr.find('td.values select');
-    if (values.length > 1) { select.attr('multiple', true); }
-    for (i = 0; i < filterValues.length; i++) {
-      var filterValue = filterValues[i];
-      var option = $('<option>');
-      if ($.isArray(filterValue)) {
-        option.val(filterValue[1]).text(filterValue[0]);
-        if ($.inArray(filterValue[1], values) > -1) {option.attr('selected', true);}
-      } else {
-        option.val(filterValue).text(filterValue);
-        if ($.inArray(filterValue, values) > -1) {option.attr('selected', true);}
-      }
-      select.append(option);
-    }
-    break;
-  case "date":
-  case "date_past":
-    tr.find('td.values').append(
-      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="10" class="value date_value" /></span>' +
-      ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="10" class="value date_value" /></span>' +
-      ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="3" class="value" /> '+labelDayPlural+'</span>'
-    );
-    $('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions);
-    $('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions);
-    $('#values_'+fieldId).val(values[0]);
-    break;
-  case "string":
-  case "text":
-    tr.find('td.values').append(
-      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="30" class="value" /></span>'
-    );
-    $('#values_'+fieldId).val(values[0]);
-    break;
-  case "relation":
-    tr.find('td.values').append(
-      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="6" class="value" /></span>' +
-      '<span style="display:none;"><select class="value" name="v['+field+'][]" id="values_'+fieldId+'_1"></select></span>'
-    );
-    $('#values_'+fieldId).val(values[0]);
-    select = tr.find('td.values select');
-    for (i = 0; i < allProjects.length; i++) {
-      var filterValue = allProjects[i];
-      var option = $('<option>');
-      option.val(filterValue[1]).text(filterValue[0]);
-      if (values[0] == filterValue[1]) { option.attr('selected', true); }
-      select.append(option);
-    }
-  case "integer":
-  case "float":
-    tr.find('td.values').append(
-      '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' +
-      ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>'
-    );
-    $('#values_'+fieldId+'_1').val(values[0]);
-    $('#values_'+fieldId+'_2').val(values[1]);
-    break;
-  }
-}
-
-function toggleFilter(field) {
-  var fieldId = field.replace('.', '_');
-  if ($('#cb_' + fieldId).is(':checked')) {
-    $("#operators_" + fieldId).show().removeAttr('disabled');
-    toggleOperator(field);
-  } else {
-    $("#operators_" + fieldId).hide().attr('disabled', true);
-    enableValues(field, []);
-  }
-}
-
-function enableValues(field, indexes) {
-  var fieldId = field.replace('.', '_');
-  $('#tr_'+fieldId+' td.values .value').each(function(index) {
-    if ($.inArray(index, indexes) >= 0) {
-      $(this).removeAttr('disabled');
-      $(this).parents('span').first().show();
-    } else {
-      $(this).val('');
-      $(this).attr('disabled', true);
-      $(this).parents('span').first().hide();
-    }
-
-    if ($(this).hasClass('group')) {
-      $(this).addClass('open');
-    } else {
-      $(this).show();
-    }
-  });
-}
-
-function toggleOperator(field) {
-  var fieldId = field.replace('.', '_');
-  var operator = $("#operators_" + fieldId);
-  switch (operator.val()) {
-    case "!*":
-    case "*":
-    case "t":
-    case "ld":
-    case "w":
-    case "lw":
-    case "l2w":
-    case "m":
-    case "lm":
-    case "y":
-    case "o":
-    case "c":
-      enableValues(field, []);
-      break;
-    case "><":
-      enableValues(field, [0,1]);
-      break;
-    case "<t+":
-    case ">t+":
-    case "><t+":
-    case "t+":
-    case ">t-":
-    case "<t-":
-    case "><t-":
-    case "t-":
-      enableValues(field, [2]);
-      break;
-    case "=p":
-    case "=!p":
-    case "!p":
-      enableValues(field, [1]);
-      break;
-    default:
-      enableValues(field, [0]);
-      break;
-  }
-}
-
-function toggleMultiSelect(el) {
-  if (el.attr('multiple')) {
-    el.removeAttr('multiple');
-    el.attr('size', 1);
-  } else {
-    el.attr('multiple', true);
-    if (el.children().length > 10)
-      el.attr('size', 10);
-    else
-      el.attr('size', 4);
-  }
-}
-
-function submit_query_form(id) {
-  selectAllOptions("selected_columns");
-  $('#'+id).submit();
-}
-
-function showTab(name, url) {
-  $('div#content .tab-content').hide();
-  $('div.tabs a').removeClass('selected');
-  $('#tab-content-' + name).show();
-  $('#tab-' + name).addClass('selected');
-  //replaces current URL with the "href" attribute of the current link
-  //(only triggered if supported by browser)
-  if ("replaceState" in window.history) {
-    window.history.replaceState(null, document.title, url);
-  }
-  return false;
-}
-
-function moveTabRight(el) {
-  var lis = $(el).parents('div.tabs').first().find('ul').children();
-  var tabsWidth = 0;
-  var i = 0;
-  lis.each(function() {
-    if ($(this).is(':visible')) {
-      tabsWidth += $(this).width() + 6;
-    }
-  });
-  if (tabsWidth < $(el).parents('div.tabs').first().width() - 60) { return; }
-  while (i<lis.length && !lis.eq(i).is(':visible')) { i++; }
-  lis.eq(i).hide();
-}
-
-function moveTabLeft(el) {
-  var lis = $(el).parents('div.tabs').first().find('ul').children();
-  var i = 0;
-  while (i < lis.length && !lis.eq(i).is(':visible')) { i++; }
-  if (i > 0) {
-    lis.eq(i-1).show();
-  }
-}
-
-function displayTabsButtons() {
-  var lis;
-  var tabsWidth = 0;
-  var el;
-  $('div.tabs').each(function() {
-    el = $(this);
-    lis = el.find('ul').children();
-    lis.each(function(){
-      if ($(this).is(':visible')) {
-        tabsWidth += $(this).width() + 6;
-      }
-    });
-    if ((tabsWidth < el.width() - 60) && (lis.first().is(':visible'))) {
-      el.find('div.tabs-buttons').hide();
-    } else {
-      el.find('div.tabs-buttons').show();
-    }
-  });
-}
-
-function setPredecessorFieldsVisibility() {
-  var relationType = $('#relation_relation_type');
-  if (relationType.val() == "precedes" || relationType.val() == "follows") {
-    $('#predecessor_fields').show();
-  } else {
-    $('#predecessor_fields').hide();
-  }
-}
-
-function showModal(id, width) {
-  var el = $('#'+id).first();
-  if (el.length === 0 || el.is(':visible')) {return;}
-  var title = el.find('h3.title').text();
-  el.dialog({
-    width: width,
-    modal: true,
-    resizable: false,
-    dialogClass: 'modal',
-    title: title
-  });
-  el.find("input[type=text], input[type=submit]").first().focus();
-}
-
-function hideModal(el) {
-  var modal;
-  if (el) {
-    modal = $(el).parents('.ui-dialog-content');
-  } else {
-    modal = $('#ajax-modal');
-  }
-  modal.dialog("close");
-}
-
-function submitPreview(url, form, target) {
-  $.ajax({
-    url: url,
-    type: 'post',
-    data: $('#'+form).serialize(),
-    success: function(data){
-      $('#'+target).html(data);
-    }
-  });
-}
-
-function collapseScmEntry(id) {
-  $('.'+id).each(function() {
-    if ($(this).hasClass('open')) {
-      collapseScmEntry($(this).attr('id'));
-    }
-    $(this).hide();
-  });
-  $('#'+id).removeClass('open');
-}
-
-function expandScmEntry(id) {
-  $('.'+id).each(function() {
-    $(this).show();
-    if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) {
-      expandScmEntry($(this).attr('id'));
-    }
-  });
-  $('#'+id).addClass('open');
-}
-
-function scmEntryClick(id, url) {
-    var el = $('#'+id);
-    if (el.hasClass('open')) {
-        collapseScmEntry(id);
-        el.addClass('collapsed');
-        return false;
-    } else if (el.hasClass('loaded')) {
-        expandScmEntry(id);
-        el.removeClass('collapsed');
-        return false;
-    }
-    if (el.hasClass('loading')) {
-        return false;
-    }
-    el.addClass('loading');
-    $.ajax({
-      url: url,
-      success: function(data) {
-        el.after(data);
-        el.addClass('open').addClass('loaded').removeClass('loading');
-      }
-    });
-    return true;
-}
-
-function randomKey(size) {
-  var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
-  var key = '';
-  for (var i = 0; i < size; i++) {
-    key += chars.charAt(Math.floor(Math.random() * chars.length));
-  }
-  return key;
-}
-
-function updateIssueFrom(url) {
-  $('#all_attributes input, #all_attributes textarea, #all_attributes select').each(function(){
-    $(this).data('valuebeforeupdate', $(this).val());
-  });
-  $.ajax({
-    url: url,
-    type: 'post',
-    data: $('#issue-form').serialize()
-  });
-}
-
-function replaceIssueFormWith(html){
-  var replacement = $(html);
-  $('#all_attributes input, #all_attributes textarea, #all_attributes select').each(function(){
-    var object_id = $(this).attr('id');
-    if (object_id && $(this).data('valuebeforeupdate')!=$(this).val()) {
-      replacement.find('#'+object_id).val($(this).val());
-    }
-  });
-  $('#all_attributes').empty();
-  $('#all_attributes').prepend(replacement);
-}
-
-function updateBulkEditFrom(url) {
-  $.ajax({
-    url: url,
-    type: 'post',
-    data: $('#bulk_edit_form').serialize()
-  });
-}
-
-function observeAutocompleteField(fieldId, url, options) {
-  $(document).ready(function() {
-    $('#'+fieldId).autocomplete($.extend({
-      source: url,
-      minLength: 2,
-      search: function(){$('#'+fieldId).addClass('ajax-loading');},
-      response: function(){$('#'+fieldId).removeClass('ajax-loading');}
-    }, options));
-    $('#'+fieldId).addClass('autocomplete');
-  });
-}
-
-function observeSearchfield(fieldId, targetId, url) {
-  $('#'+fieldId).each(function() {
-    var $this = $(this);
-    $this.addClass('autocomplete');
-    $this.attr('data-value-was', $this.val());
-    var check = function() {
-      var val = $this.val();
-      if ($this.attr('data-value-was') != val){
-        $this.attr('data-value-was', val);
-        $.ajax({
-          url: url,
-          type: 'get',
-          data: {q: $this.val()},
-          success: function(data){ if(targetId) $('#'+targetId).html(data); },
-          beforeSend: function(){ $this.addClass('ajax-loading'); },
-          complete: function(){ $this.removeClass('ajax-loading'); }
-        });
-      }
-    };
-    var reset = function() {
-      if (timer) {
-        clearInterval(timer);
-        timer = setInterval(check, 300);
-      }
-    };
-    var timer = setInterval(check, 300);
-    $this.bind('keyup click mousemove', reset);
-  });
-}
-
-function initMyPageSortable(list, url) {
-  $('#list-'+list).sortable({
-    connectWith: '.block-receiver',
-    tolerance: 'pointer',
-    update: function(){
-      $.ajax({
-        url: url,
-        type: 'post',
-        data: {'blocks': $.map($('#list-'+list).children(), function(el){return $(el).attr('id');})}
-      });
-    }
-  });
-  $("#list-top, #list-left, #list-right").disableSelection();
-}
-
-var warnLeavingUnsavedMessage;
-function warnLeavingUnsaved(message) {
-  warnLeavingUnsavedMessage = message;
-  $('form').live('submit', function(){
-    $('textarea').removeData('changed');
-  });
-  $('textarea').live('change', function(){
-    $(this).data('changed', 'changed');
-  });
-  window.onbeforeunload = function(){
-    var warn = false;
-    $('textarea').blur().each(function(){
-      if ($(this).data('changed')) {
-        warn = true;
-      }
-    });
-    if (warn) {return warnLeavingUnsavedMessage;}
-  };
-}
-
-function setupAjaxIndicator() {
-  $('#ajax-indicator').bind('ajaxSend', function(event, xhr, settings) {
-    if ($('.ajax-loading').length === 0 && settings.contentType != 'application/octet-stream') {
-      $('#ajax-indicator').show();
-    }
-  });
-  $('#ajax-indicator').bind('ajaxStop', function() {
-    $('#ajax-indicator').hide();
-  });
-}
-
-function hideOnLoad() {
-  $('.hol').hide();
-}
-
-function addFormObserversForDoubleSubmit() {
-  $('form[method=post]').each(function() {
-    if (!$(this).hasClass('multiple-submit')) {
-      $(this).submit(function(form_submission) {
-        if ($(form_submission.target).attr('data-submitted')) {
-          form_submission.preventDefault();
-        } else {
-          $(form_submission.target).attr('data-submitted', true);
-        }
-      });
-    }
-  });
-}
-
-function blockEventPropagation(event) {
-  event.stopPropagation();
-  event.preventDefault();
-}
-
-$(document).ready(setupAjaxIndicator);
-$(document).ready(hideOnLoad);
-$(document).ready(addFormObserversForDoubleSubmit);
--- a/.svn/pristine/20/20576c20e326be9d43917cbd74b999241edc31c3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class ProjectsHelperTest < ActionView::TestCase
-  include ApplicationHelper
-  include ProjectsHelper
-  include Redmine::I18n
-  include ERB::Util
-
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :versions,
-           :projects_trackers,
-           :member_roles,
-           :members,
-           :groups_users,
-           :enabled_modules
-
-  def setup
-    super
-    set_language_if_valid('en')
-    User.current = nil
-  end
-
-  def test_link_to_version_within_project
-    @project = Project.find(2)
-    User.current = User.find(1)
-    assert_equal '<a href="/versions/5">Alpha</a>', link_to_version(Version.find(5))
-  end
-
-  def test_link_to_version
-    User.current = User.find(1)
-    assert_equal '<a href="/versions/5">OnlineStore - Alpha</a>', link_to_version(Version.find(5))
-  end
-
-  def test_link_to_private_version
-    assert_equal 'OnlineStore - Alpha', link_to_version(Version.find(5))
-  end
-
-  def test_link_to_version_invalid_version
-    assert_equal '', link_to_version(Object)
-  end
-
-  def test_format_version_name_within_project
-    @project = Project.find(1)
-    assert_equal "0.1", format_version_name(Version.find(1))
-  end
-
-  def test_format_version_name
-    assert_equal "eCookbook - 0.1", format_version_name(Version.find(1))
-  end
-
-  def test_format_version_name_for_system_version
-    assert_equal "OnlineStore - Systemwide visible version", format_version_name(Version.find(7))
-  end
-
-  def test_version_options_for_select_with_no_versions
-    assert_equal '', version_options_for_select([])
-    assert_equal '', version_options_for_select([], Version.find(1))
-  end
-end
--- a/.svn/pristine/20/2087b528196b7332c8234e9ab56b21a9c4114103.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class DefaultDataTest < ActiveSupport::TestCase
-  include Redmine::I18n
-  fixtures :roles
-
-  def test_no_data
-    assert !Redmine::DefaultData::Loader::no_data?
-    Role.delete_all("builtin = 0")
-    Tracker.delete_all
-    IssueStatus.delete_all
-    Enumeration.delete_all
-    assert Redmine::DefaultData::Loader::no_data?
-  end
-
-  def test_load
-    valid_languages.each do |lang|
-      begin
-        Role.delete_all("builtin = 0")
-        Tracker.delete_all
-        IssueStatus.delete_all
-        Enumeration.delete_all
-        assert Redmine::DefaultData::Loader::load(lang)
-        assert_not_nil DocumentCategory.first
-        assert_not_nil IssuePriority.first
-        assert_not_nil TimeEntryActivity.first
-      rescue ActiveRecord::RecordInvalid => e
-        assert false, ":#{lang} default data is invalid (#{e.message})."
-      end
-    end
-  end
-end
--- a/.svn/pristine/20/20a6292c961b1184d69b8461d3e60b34dcd95f04.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/bazaar_adapter'
-
-class Repository::Bazaar < Repository
-  attr_protected :root_url
-  validates_presence_of :url, :log_encoding
-
-  def self.human_attribute_name(attribute_key_name, *args)
-    attr_name = attribute_key_name.to_s
-    if attr_name == "url"
-      attr_name = "path_to_repository"
-    end
-    super(attr_name, *args)
-  end
-
-  def self.scm_adapter_class
-    Redmine::Scm::Adapters::BazaarAdapter
-  end
-
-  def self.scm_name
-    'Bazaar'
-  end
-
-  def entry(path=nil, identifier=nil)
-    scm.bzr_path_encodig = log_encoding
-    scm.entry(path, identifier)
-  end
-
-  def cat(path, identifier=nil)
-    scm.bzr_path_encodig = log_encoding
-    scm.cat(path, identifier)
-  end
-
-  def annotate(path, identifier=nil)
-    scm.bzr_path_encodig = log_encoding
-    scm.annotate(path, identifier)
-  end
-
-  def diff(path, rev, rev_to)
-    scm.bzr_path_encodig = log_encoding
-    scm.diff(path, rev, rev_to)
-  end
-
-  def entries(path=nil, identifier=nil)
-    scm.bzr_path_encodig = log_encoding
-    entries = scm.entries(path, identifier)
-    if entries
-      entries.each do |e|
-        next if e.lastrev.revision.blank?
-        # Set the filesize unless browsing a specific revision
-        if identifier.nil? && e.is_file?
-          full_path = File.join(root_url, e.path)
-          e.size = File.stat(full_path).size if File.file?(full_path)
-        end
-        c = Change.
-              includes(:changeset).
-              where("#{Change.table_name}.revision = ? and #{Changeset.table_name}.repository_id = ?", e.lastrev.revision, id).
-              order("#{Changeset.table_name}.revision DESC").
-              first
-        if c
-          e.lastrev.identifier = c.changeset.revision
-          e.lastrev.name       = c.changeset.revision
-          e.lastrev.author     = c.changeset.committer
-        end
-      end
-    end
-    load_entries_changesets(entries)
-    entries
-  end
-
-  def fetch_changesets
-    scm.bzr_path_encodig = log_encoding
-    scm_info = scm.info
-    if scm_info
-      # latest revision found in database
-      db_revision = latest_changeset ? latest_changeset.revision.to_i : 0
-      # latest revision in the repository
-      scm_revision = scm_info.lastrev.identifier.to_i
-      if db_revision < scm_revision
-        logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
-        identifier_from = db_revision + 1
-        while (identifier_from <= scm_revision)
-          # loads changesets by batches of 200
-          identifier_to = [identifier_from + 199, scm_revision].min
-          revisions = scm.revisions('', identifier_to, identifier_from)
-          transaction do
-            revisions.reverse_each do |revision|
-              changeset = Changeset.create(:repository   => self,
-                                           :revision     => revision.identifier,
-                                           :committer    => revision.author,
-                                           :committed_on => revision.time,
-                                           :scmid        => revision.scmid,
-                                           :comments     => revision.message)
-
-              revision.paths.each do |change|
-                Change.create(:changeset => changeset,
-                              :action    => change[:action],
-                              :path      => change[:path],
-                              :revision  => change[:revision])
-              end
-            end
-          end unless revisions.nil?
-          identifier_from = identifier_to + 1
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/20/20aee30a3886ed67fbcf2637dc7c9a63361c83fd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Group < Principal
-  include Redmine::SafeAttributes
-
-  has_and_belongs_to_many :users, :after_add => :user_added,
-                                  :after_remove => :user_removed
-
-  acts_as_customizable
-
-  validates_presence_of :lastname
-  validates_uniqueness_of :lastname, :case_sensitive => false
-  validates_length_of :lastname, :maximum => 255
-
-  before_destroy :remove_references_before_destroy
-
-  scope :sorted, lambda { order("#{table_name}.lastname ASC") }
-  scope :named, lambda {|arg| where("LOWER(#{table_name}.lastname) = LOWER(?)", arg.to_s.strip)}
-
-  safe_attributes 'name',
-    'user_ids',
-    'custom_field_values',
-    'custom_fields',
-    :if => lambda {|group, user| user.admin?}
-
-  def to_s
-    lastname.to_s
-  end
-
-  def name
-    lastname
-  end
-
-  def name=(arg)
-    self.lastname = arg
-  end
-
-  def user_added(user)
-    members.each do |member|
-      next if member.project.nil?
-      user_member = Member.find_by_project_id_and_user_id(member.project_id, user.id) || Member.new(:project_id => member.project_id, :user_id => user.id)
-      member.member_roles.each do |member_role|
-        user_member.member_roles << MemberRole.new(:role => member_role.role, :inherited_from => member_role.id)
-      end
-      user_member.save!
-    end
-  end
-
-  def user_removed(user)
-    members.each do |member|
-      MemberRole.
-        includes(:member).
-        where("#{Member.table_name}.user_id = ? AND #{MemberRole.table_name}.inherited_from IN (?)", user.id, member.member_role_ids).
-        all.
-        each(&:destroy)
-    end
-  end
-
-  def self.human_attribute_name(attribute_key_name, *args)
-    attr_name = attribute_key_name.to_s
-    if attr_name == 'lastname'
-      attr_name = "name"
-    end
-    super(attr_name, *args)
-  end
-
-  private
-
-  # Removes references that are not handled by associations
-  def remove_references_before_destroy
-    return if self.id.nil?
-
-    Issue.update_all 'assigned_to_id = NULL', ['assigned_to_id = ?', id]
-  end
-end
--- a/.svn/pristine/21/210434ccffe59c9bbad805f6aeb0141711b6bd46.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::ApiTest < Redmine::ApiTest::Base
-  fixtures :users
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  def test_api_should_work_with_protect_from_forgery
-    ActionController::Base.allow_forgery_protection = true
-    assert_difference('User.count') do
-      post '/users.xml', {
-        :user => {
-          :login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
-          :mail => 'foo@example.net', :password => 'secret123'}
-        },
-        credentials('admin')
-      assert_response 201
-    end
-  ensure
-    ActionController::Base.allow_forgery_protection = false
-  end
-end
\ No newline at end of file
--- a/.svn/pristine/21/21b08aea1ac3dbc27c974e37d3d3c4f6952cdffd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'blankslate'
-
-module Redmine
-  module Views
-    module Builders
-      class Structure < BlankSlate
-        attr_accessor :request, :response
-
-        def initialize(request, response)
-          @struct = [{}]
-          self.request = request
-          self.response = response
-        end
-
-        def array(tag, options={}, &block)
-          @struct << []
-          block.call(self)
-          ret = @struct.pop
-          @struct.last[tag] = ret
-          @struct.last.merge!(options) if options
-        end
-
-        def method_missing(sym, *args, &block)
-          if args.any?
-            if args.first.is_a?(Hash)
-              if @struct.last.is_a?(Array)
-                @struct.last << args.first unless block
-              else
-                @struct.last[sym] = args.first
-              end
-            else
-              if @struct.last.is_a?(Array)
-                if args.size == 1 && !block_given?
-                  @struct.last << args.first
-                else
-                  @struct.last << (args.last || {}).merge(:value => args.first)
-                end
-              else
-                @struct.last[sym] = args.first
-              end
-            end
-          end
-
-          if block
-            @struct << (args.first.is_a?(Hash) ? args.first : {})
-            block.call(self)
-            ret = @struct.pop
-            if @struct.last.is_a?(Array)
-              @struct.last << ret
-            else
-              if @struct.last.has_key?(sym) && @struct.last[sym].is_a?(Hash)
-                @struct.last[sym].merge! ret
-              else
-                @struct.last[sym] = ret
-              end
-            end
-          end
-        end
-
-        def output
-          raise "Need to implement #{self.class.name}#output"
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/22/2231a90d74735e9a796f1508f0e2f1bfd1774f24.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Member < ActiveRecord::Base
-  belongs_to :user
-  belongs_to :principal, :foreign_key => 'user_id'
-  has_many :member_roles, :dependent => :destroy
-  has_many :roles, :through => :member_roles
-  belongs_to :project
-
-  validates_presence_of :principal, :project
-  validates_uniqueness_of :user_id, :scope => :project_id
-  validate :validate_role
-
-  before_destroy :set_issue_category_nil
-
-  def role
-  end
-
-  def role=
-  end
-
-  def name
-    self.user.name
-  end
-
-  alias :base_role_ids= :role_ids=
-  def role_ids=(arg)
-    ids = (arg || []).collect(&:to_i) - [0]
-    # Keep inherited roles
-    ids += member_roles.select {|mr| !mr.inherited_from.nil?}.collect(&:role_id)
-
-    new_role_ids = ids - role_ids
-    # Add new roles
-    new_role_ids.each {|id| member_roles << MemberRole.new(:role_id => id) }
-    # Remove roles (Rails' #role_ids= will not trigger MemberRole#on_destroy)
-    member_roles_to_destroy = member_roles.select {|mr| !ids.include?(mr.role_id)}
-    if member_roles_to_destroy.any?
-      member_roles_to_destroy.each(&:destroy)
-    end
-  end
-
-  def <=>(member)
-    a, b = roles.sort.first, member.roles.sort.first
-    if a == b
-      if principal
-        principal <=> member.principal
-      else
-        1
-      end
-    elsif a
-      a <=> b
-    else
-      1
-    end
-  end
-
-  def deletable?
-    member_roles.detect {|mr| mr.inherited_from}.nil?
-  end
-
-  def include?(user)
-    if principal.is_a?(Group)
-      !user.nil? && user.groups.include?(principal)
-    else
-      self.user == user
-    end
-  end
-
-  def set_issue_category_nil
-    if user
-      # remove category based auto assignments for this member
-      IssueCategory.update_all "assigned_to_id = NULL", ["project_id = ? AND assigned_to_id = ?", project.id, user.id]
-    end
-  end
-
-  # Find or initilize a Member with an id, attributes, and for a Principal
-  def self.edit_membership(id, new_attributes, principal=nil)
-    @membership = id.present? ? Member.find(id) : Member.new(:principal => principal)
-    @membership.attributes = new_attributes
-    @membership
-  end
-
-  # Finds or initilizes a Member for the given project and principal
-  def self.find_or_new(project, principal)
-    project_id = project.is_a?(Project) ? project.id : project
-    principal_id = principal.is_a?(Principal) ? principal.id : principal
-
-    member = Member.find_by_project_id_and_user_id(project_id, principal_id)
-    member ||= Member.new(:project_id => project_id, :user_id => principal_id)
-    member
-  end
-
-  protected
-
-  def validate_role
-    errors.add_on_empty :role if member_roles.empty? && roles.empty?
-  end
-end
--- a/.svn/pristine/22/2254c6ada14f9698b9a4320070c88983213e381b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingCalendarsTest < ActionController::IntegrationTest
-  def test_calendars
-    assert_routing(
-        { :method => 'get', :path => "/issues/calendar" },
-        { :controller => 'calendars', :action => 'show' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/project-name/issues/calendar" },
-        { :controller => 'calendars', :action => 'show',
-          :project_id => 'project-name' }
-      )
-  end
-end
--- a/.svn/pristine/22/22a7851f8ede366924cba144fbbe8879121ee70d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingWelcomeTest < ActionController::IntegrationTest
-  def test_welcome
-    assert_routing(
-        { :method => 'get', :path => "/" },
-        { :controller => 'welcome', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/robots.txt" },
-        { :controller => 'welcome', :action => 'robots' }
-      )
-  end
-end
--- a/.svn/pristine/22/22e2e1f53cc1372b24c8bb03f573ceefbdb7fa57.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,263 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ProjectMembersInheritanceTest < ActiveSupport::TestCase
-  fixtures :roles, :users
-
-  def setup
-    @parent = Project.generate!
-    @member = Member.create!(:principal => User.find(2), :project => @parent, :role_ids => [1, 2])
-    assert_equal 2, @member.reload.roles.size
-  end
-
-  def test_project_created_with_inherit_members_disabled_should_not_inherit_members
-    assert_no_difference 'Member.count' do
-      project = Project.generate_with_parent!(@parent, :inherit_members => false)
-
-      assert_equal 0, project.memberships.count
-    end
-  end
-
-  def test_project_created_with_inherit_members_should_inherit_members
-    assert_difference 'Member.count', 1 do
-      project = Project.generate_with_parent!(@parent, :inherit_members => true)
-      project.reload
-
-      assert_equal 1, project.memberships.count
-      member = project.memberships.first
-      assert_equal @member.principal, member.principal
-      assert_equal @member.roles.sort, member.roles.sort
-    end
-  end
-
-  def test_turning_on_inherit_members_should_inherit_members
-    Project.generate_with_parent!(@parent, :inherit_members => false)
-
-    assert_difference 'Member.count', 1 do
-      project = Project.order('id desc').first
-      project.inherit_members = true
-      project.save!
-      project.reload
-
-      assert_equal 1, project.memberships.count
-      member = project.memberships.first
-      assert_equal @member.principal, member.principal
-      assert_equal @member.roles.sort, member.roles.sort
-    end
-  end
-
-  def test_turning_off_inherit_members_should_remove_inherited_members
-    Project.generate_with_parent!(@parent, :inherit_members => true)
-
-    assert_difference 'Member.count', -1 do
-      project = Project.order('id desc').first
-      project.inherit_members = false
-      project.save!
-      project.reload
-
-      assert_equal 0, project.memberships.count
-    end
-  end
-
-  def test_moving_a_root_project_under_a_parent_should_inherit_members
-    Project.generate!(:inherit_members => true)
-    project = Project.order('id desc').first
-
-    assert_difference 'Member.count', 1 do
-      project.set_parent!(@parent)
-      project.reload
-
-      assert_equal 1, project.memberships.count
-      member = project.memberships.first
-      assert_equal @member.principal, member.principal
-      assert_equal @member.roles.sort, member.roles.sort
-    end
-  end
-
-  def test_moving_a_subproject_as_root_should_loose_inherited_members
-    Project.generate_with_parent!(@parent, :inherit_members => true)
-    project = Project.order('id desc').first
-
-    assert_difference 'Member.count', -1 do
-      project.set_parent!(nil)
-      project.reload
-
-      assert_equal 0, project.memberships.count
-    end
-  end
-
-  def test_moving_a_subproject_to_another_parent_should_change_inherited_members
-    other_parent = Project.generate!
-    other_member = Member.create!(:principal => User.find(4), :project => other_parent, :role_ids => [3])
-    other_member.reload
-
-    Project.generate_with_parent!(@parent, :inherit_members => true)
-    project = Project.order('id desc').first
-    project.set_parent!(other_parent.reload)
-    project.reload
-
-    assert_equal 1, project.memberships.count
-    member = project.memberships.first
-    assert_equal other_member.principal, member.principal
-    assert_equal other_member.roles.sort, member.roles.sort
-  end
-
-  def test_inheritance_should_propagate_to_subprojects
-    project = Project.generate_with_parent!(@parent, :inherit_members => false)
-    subproject = Project.generate_with_parent!(project, :inherit_members => true)
-    project.reload
-
-    assert_difference 'Member.count', 2 do
-      project.inherit_members = true
-      project.save
-      project.reload
-      subproject.reload
-
-      assert_equal 1, project.memberships.count
-      assert_equal 1, subproject.memberships.count
-      member = subproject.memberships.first
-      assert_equal @member.principal, member.principal
-      assert_equal @member.roles.sort, member.roles.sort
-    end
-  end
-
-  def test_inheritance_removal_should_propagate_to_subprojects
-    project = Project.generate_with_parent!(@parent, :inherit_members => true)
-    subproject = Project.generate_with_parent!(project, :inherit_members => true)
-    project.reload
-
-    assert_difference 'Member.count', -2 do
-      project.inherit_members = false
-      project.save
-      project.reload
-      subproject.reload
-
-      assert_equal 0, project.memberships.count
-      assert_equal 0, subproject.memberships.count
-    end
-  end
-
-  def test_adding_a_member_should_propagate
-    project = Project.generate_with_parent!(@parent, :inherit_members => true)
-
-    assert_difference 'Member.count', 2 do
-      member = Member.create!(:principal => User.find(4), :project => @parent, :role_ids => [1, 3])
-      member.reload
-
-      inherited_member = project.memberships.order('id desc').first
-      assert_equal member.principal, inherited_member.principal
-      assert_equal member.roles.sort, inherited_member.roles.sort
-    end
-  end
-
-  def test_adding_a_member_should_not_propagate_if_child_does_not_inherit
-    project = Project.generate_with_parent!(@parent, :inherit_members => false)
-
-    assert_difference 'Member.count', 1 do
-      member = Member.create!(:principal => User.find(4), :project => @parent, :role_ids => [1, 3])
-
-      assert_nil project.reload.memberships.detect {|m| m.principal == member.principal}
-    end
-  end
-
-  def test_removing_a_member_should_propagate
-    project = Project.generate_with_parent!(@parent, :inherit_members => true)
-
-    assert_difference 'Member.count', -2 do
-      @member.reload.destroy
-      project.reload
-
-      assert_equal 0, project.memberships.count
-    end
-  end
-
-  def test_adding_a_group_member_should_propagate_with_its_users
-    project = Project.generate_with_parent!(@parent, :inherit_members => true)
-    group = Group.generate!
-    user = User.find(4)
-    group.users << user
-
-    assert_difference 'Member.count', 4 do
-      assert_difference 'MemberRole.count', 8 do
-        member = Member.create!(:principal => group, :project => @parent, :role_ids => [1, 3])
-        project.reload
-        member.reload
-
-        inherited_group_member = project.memberships.detect {|m| m.principal == group}
-        assert_not_nil inherited_group_member
-        assert_equal member.roles.sort, inherited_group_member.roles.sort
-
-        inherited_user_member = project.memberships.detect {|m| m.principal == user}
-        assert_not_nil inherited_user_member
-        assert_equal member.roles.sort, inherited_user_member.roles.sort
-      end
-    end
-  end
-
-  def test_removing_a_group_member_should_propagate
-    project = Project.generate_with_parent!(@parent, :inherit_members => true)
-    group = Group.generate!
-    user = User.find(4)
-    group.users << user
-    member = Member.create!(:principal => group, :project => @parent, :role_ids => [1, 3])
-
-    assert_difference 'Member.count', -4 do
-      assert_difference 'MemberRole.count', -8 do
-        member.destroy
-        project.reload
-
-        inherited_group_member = project.memberships.detect {|m| m.principal == group}
-        assert_nil inherited_group_member
-
-        inherited_user_member = project.memberships.detect {|m| m.principal == user}
-        assert_nil inherited_user_member
-      end
-    end
-  end
-
-  def test_adding_user_who_use_is_already_a_member_to_parent_project_should_merge_roles
-    project = Project.generate_with_parent!(@parent, :inherit_members => true)
-    user = User.find(4)
-    Member.create!(:principal => user, :project => project, :role_ids => [1, 2])
-
-    assert_difference 'Member.count', 1 do
-      Member.create!(:principal => User.find(4), :project => @parent.reload, :role_ids => [1, 3])
-
-      member = project.reload.memberships.detect {|m| m.principal == user}
-      assert_not_nil member
-      assert_equal [1, 2, 3], member.roles.uniq.sort.map(&:id)
-    end
-  end
-
-  def test_turning_on_inheritance_with_user_who_is_already_a_member_should_merge_roles
-    project = Project.generate_with_parent!(@parent)
-    user = @member.user
-    Member.create!(:principal => user, :project => project, :role_ids => [1, 3])
-    project.reload
-
-    assert_no_difference 'Member.count' do
-      project.inherit_members = true
-      project.save!
-
-      member = project.reload.memberships.detect {|m| m.principal == user}
-      assert_not_nil member
-      assert_equal [1, 2, 3], member.roles.uniq.sort.map(&:id)
-    end
-  end
-end
--- a/.svn/pristine/23/23d24e0346024a68e636758e1fe724435ac78a94.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,388 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class CustomField < ActiveRecord::Base
-  include Redmine::SubclassFactory
-
-  has_many :custom_values, :dependent => :delete_all
-  has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}custom_fields_roles#{table_name_suffix}", :foreign_key => "custom_field_id"
-  acts_as_list :scope => 'type = \'#{self.class}\''
-  serialize :possible_values
-
-  validates_presence_of :name, :field_format
-  validates_uniqueness_of :name, :scope => :type
-  validates_length_of :name, :maximum => 30
-  validates_inclusion_of :field_format, :in => Proc.new { Redmine::CustomFieldFormat.available_formats }
-  validate :validate_custom_field
-
-  before_validation :set_searchable
-  after_save :handle_multiplicity_change
-  after_save do |field|
-    if field.visible_changed? && field.visible
-      field.roles.clear
-    end
-  end
-
-  scope :sorted, lambda { order("#{table_name}.position ASC") }
-  scope :visible, lambda {|*args|
-    user = args.shift || User.current
-    if user.admin?
-      # nop
-    elsif user.memberships.any?
-      where("#{table_name}.visible = ? OR #{table_name}.id IN (SELECT DISTINCT cfr.custom_field_id FROM #{Member.table_name} m" +
-        " INNER JOIN #{MemberRole.table_name} mr ON mr.member_id = m.id" +
-        " INNER JOIN #{table_name_prefix}custom_fields_roles#{table_name_suffix} cfr ON cfr.role_id = mr.role_id" +
-        " WHERE m.user_id = ?)",
-        true, user.id)
-    else
-      where(:visible => true)
-    end
-  }
-
-  def visible_by?(project, user=User.current)
-    visible? || user.admin?
-  end
-
-  def field_format=(arg)
-    # cannot change format of a saved custom field
-    super if new_record?
-  end
-
-  def set_searchable
-    # make sure these fields are not searchable
-    self.searchable = false if %w(int float date bool).include?(field_format)
-    # make sure only these fields can have multiple values
-    self.multiple = false unless %w(list user version).include?(field_format)
-    true
-  end
-
-  def validate_custom_field
-    if self.field_format == "list"
-      errors.add(:possible_values, :blank) if self.possible_values.nil? || self.possible_values.empty?
-      errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array
-    end
-
-    if regexp.present?
-      begin
-        Regexp.new(regexp)
-      rescue
-        errors.add(:regexp, :invalid)
-      end
-    end
-
-    if default_value.present? && !valid_field_value?(default_value)
-      errors.add(:default_value, :invalid)
-    end
-  end
-
-  def possible_values_options(obj=nil)
-    case field_format
-    when 'user', 'version'
-      if obj.respond_to?(:project) && obj.project
-        case field_format
-        when 'user'
-          obj.project.users.sort.collect {|u| [u.to_s, u.id.to_s]}
-        when 'version'
-          obj.project.shared_versions.sort.collect {|u| [u.to_s, u.id.to_s]}
-        end
-      elsif obj.is_a?(Array)
-        obj.collect {|o| possible_values_options(o)}.reduce(:&)
-      else
-        []
-      end
-    when 'bool'
-      [[l(:general_text_Yes), '1'], [l(:general_text_No), '0']]
-    else
-      possible_values || []
-    end
-  end
-
-  def possible_values(obj=nil)
-    case field_format
-    when 'user', 'version'
-      possible_values_options(obj).collect(&:last)
-    when 'bool'
-      ['1', '0']
-    else
-      values = super()
-      if values.is_a?(Array)
-        values.each do |value|
-          value.force_encoding('UTF-8') if value.respond_to?(:force_encoding)
-        end
-        values
-      else
-        []
-      end
-    end
-  end
-
-  # Makes possible_values accept a multiline string
-  def possible_values=(arg)
-    if arg.is_a?(Array)
-      super(arg.compact.collect(&:strip).select {|v| !v.blank?})
-    else
-      self.possible_values = arg.to_s.split(/[\n\r]+/)
-    end
-  end
-
-  def cast_value(value)
-    casted = nil
-    unless value.blank?
-      case field_format
-      when 'string', 'text', 'list'
-        casted = value
-      when 'date'
-        casted = begin; value.to_date; rescue; nil end
-      when 'bool'
-        casted = (value == '1' ? true : false)
-      when 'int'
-        casted = value.to_i
-      when 'float'
-        casted = value.to_f
-      when 'user', 'version'
-        casted = (value.blank? ? nil : field_format.classify.constantize.find_by_id(value.to_i))
-      end
-    end
-    casted
-  end
-
-  def value_from_keyword(keyword, customized)
-    possible_values_options = possible_values_options(customized)
-    if possible_values_options.present?
-      keyword = keyword.to_s.downcase
-      if v = possible_values_options.detect {|text, id| text.downcase == keyword}
-        if v.is_a?(Array)
-          v.last
-        else
-          v
-        end
-      end
-    else
-      keyword
-    end
-  end
-
-  # Returns a ORDER BY clause that can used to sort customized
-  # objects by their value of the custom field.
-  # Returns nil if the custom field can not be used for sorting.
-  def order_statement
-    return nil if multiple?
-    case field_format
-      when 'string', 'text', 'list', 'date', 'bool'
-        # COALESCE is here to make sure that blank and NULL values are sorted equally
-        "COALESCE(#{join_alias}.value, '')"
-      when 'int', 'float'
-        # Make the database cast values into numeric
-        # Postgresql will raise an error if a value can not be casted!
-        # CustomValue validations should ensure that it doesn't occur
-        "CAST(CASE #{join_alias}.value WHEN '' THEN '0' ELSE #{join_alias}.value END AS decimal(30,3))"
-      when 'user', 'version'
-        value_class.fields_for_order_statement(value_join_alias)
-      else
-        nil
-    end
-  end
-
-  # Returns a GROUP BY clause that can used to group by custom value
-  # Returns nil if the custom field can not be used for grouping.
-  def group_statement
-    return nil if multiple?
-    case field_format
-      when 'list', 'date', 'bool', 'int'
-        order_statement
-      when 'user', 'version'
-        "COALESCE(#{join_alias}.value, '')"
-      else
-        nil
-    end
-  end
-
-  def join_for_order_statement
-    case field_format
-      when 'user', 'version'
-        "LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
-          " ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
-          " AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
-          " AND #{join_alias}.custom_field_id = #{id}" +
-          " AND (#{visibility_by_project_condition})" +
-          " AND #{join_alias}.value <> ''" +
-          " AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
-            " WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
-            " AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
-            " AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)" +
-          " LEFT OUTER JOIN #{value_class.table_name} #{value_join_alias}" +
-          " ON CAST(CASE #{join_alias}.value WHEN '' THEN '0' ELSE #{join_alias}.value END AS decimal(30,0)) = #{value_join_alias}.id"
-      when 'int', 'float'
-        "LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
-          " ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
-          " AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
-          " AND #{join_alias}.custom_field_id = #{id}" +
-          " AND (#{visibility_by_project_condition})" +
-          " AND #{join_alias}.value <> ''" +
-          " AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
-            " WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
-            " AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
-            " AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)"
-      when 'string', 'text', 'list', 'date', 'bool'
-        "LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
-          " ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
-          " AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
-          " AND #{join_alias}.custom_field_id = #{id}" +
-          " AND (#{visibility_by_project_condition})" +
-          " AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
-            " WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
-            " AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
-            " AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)"
-      else
-        nil
-    end
-  end
-
-  def join_alias
-    "cf_#{id}"
-  end
-
-  def value_join_alias
-    join_alias + "_" + field_format
-  end
-
-  def visibility_by_project_condition(project_key=nil, user=User.current)
-    if visible? || user.admin?
-      "1=1"
-    elsif user.anonymous?
-      "1=0"
-    else
-      project_key ||= "#{self.class.customized_class.table_name}.project_id"
-      "#{project_key} IN (SELECT DISTINCT m.project_id FROM #{Member.table_name} m" +
-        " INNER JOIN #{MemberRole.table_name} mr ON mr.member_id = m.id" +
-        " INNER JOIN #{table_name_prefix}custom_fields_roles#{table_name_suffix} cfr ON cfr.role_id = mr.role_id" +
-        " WHERE m.user_id = #{user.id} AND cfr.custom_field_id = #{id})"
-    end
-  end
-
-  def self.visibility_condition
-    if user.admin?
-      "1=1"
-    elsif user.anonymous?
-      "#{table_name}.visible"
-    else
-      "#{project_key} IN (SELECT DISTINCT m.project_id FROM #{Member.table_name} m" +
-        " INNER JOIN #{MemberRole.table_name} mr ON mr.member_id = m.id" +
-        " INNER JOIN #{table_name_prefix}custom_fields_roles#{table_name_suffix} cfr ON cfr.role_id = mr.role_id" +
-        " WHERE m.user_id = #{user.id} AND cfr.custom_field_id = #{id})"
-    end
-  end
-
-  def <=>(field)
-    position <=> field.position
-  end
-
-  # Returns the class that values represent
-  def value_class
-    case field_format
-      when 'user', 'version'
-        field_format.classify.constantize
-      else
-        nil
-    end
-  end
-
-  def self.customized_class
-    self.name =~ /^(.+)CustomField$/
-    $1.constantize rescue nil
-  end
-
-  # to move in project_custom_field
-  def self.for_all
-    where(:is_for_all => true).order('position').all
-  end
-
-  def type_name
-    nil
-  end
-
-  # Returns the error messages for the given value
-  # or an empty array if value is a valid value for the custom field
-  def validate_field_value(value)
-    errs = []
-    if value.is_a?(Array)
-      if !multiple?
-        errs << ::I18n.t('activerecord.errors.messages.invalid')
-      end
-      if is_required? && value.detect(&:present?).nil?
-        errs << ::I18n.t('activerecord.errors.messages.blank')
-      end
-      value.each {|v| errs += validate_field_value_format(v)}
-    else
-      if is_required? && value.blank?
-        errs << ::I18n.t('activerecord.errors.messages.blank')
-      end
-      errs += validate_field_value_format(value)
-    end
-    errs
-  end
-
-  # Returns true if value is a valid value for the custom field
-  def valid_field_value?(value)
-    validate_field_value(value).empty?
-  end
-
-  def format_in?(*args)
-    args.include?(field_format)
-  end
-
-  protected
-
-  # Returns the error message for the given value regarding its format
-  def validate_field_value_format(value)
-    errs = []
-    if value.present?
-      errs << ::I18n.t('activerecord.errors.messages.invalid') unless regexp.blank? or value =~ Regexp.new(regexp)
-      errs << ::I18n.t('activerecord.errors.messages.too_short', :count => min_length) if min_length > 0 and value.length < min_length
-      errs << ::I18n.t('activerecord.errors.messages.too_long', :count => max_length) if max_length > 0 and value.length > max_length
-
-      # Format specific validations
-      case field_format
-      when 'int'
-        errs << ::I18n.t('activerecord.errors.messages.not_a_number') unless value =~ /^[+-]?\d+$/
-      when 'float'
-        begin; Kernel.Float(value); rescue; errs << ::I18n.t('activerecord.errors.messages.invalid') end
-      when 'date'
-        errs << ::I18n.t('activerecord.errors.messages.not_a_date') unless value =~ /^\d{4}-\d{2}-\d{2}$/ && begin; value.to_date; rescue; false end
-      when 'list'
-        errs << ::I18n.t('activerecord.errors.messages.inclusion') unless possible_values.include?(value)
-      end
-    end
-    errs
-  end
-
-  # Removes multiple values for the custom field after setting the multiple attribute to false
-  # We kepp the value with the highest id for each customized object
-  def handle_multiplicity_change
-    if !new_record? && multiple_was && !multiple
-      ids = custom_values.
-        where("EXISTS(SELECT 1 FROM #{CustomValue.table_name} cve WHERE cve.custom_field_id = #{CustomValue.table_name}.custom_field_id" +
-          " AND cve.customized_type = #{CustomValue.table_name}.customized_type AND cve.customized_id = #{CustomValue.table_name}.customized_id" +
-          " AND cve.id > #{CustomValue.table_name}.id)").
-        pluck(:id)
-
-      if ids.any?
-        custom_values.where(:id => ids).delete_all
-      end
-    end
-  end
-end
--- a/.svn/pristine/23/23f046e7217770bca11bfe9989b755a158f48868.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Token < ActiveRecord::Base
-  belongs_to :user
-  validates_uniqueness_of :value
-
-  before_create :delete_previous_tokens, :generate_new_token
-
-  @@validity_time = 1.day
-
-  def generate_new_token
-    self.value = Token.generate_token_value
-  end
-
-  # Return true if token has expired
-  def expired?
-    return Time.now > self.created_on + @@validity_time
-  end
-
-  # Delete all expired tokens
-  def self.destroy_expired
-    Token.delete_all ["action NOT IN (?) AND created_on < ?", ['feeds', 'api'], Time.now - @@validity_time]
-  end
-
-  # Returns the active user who owns the key for the given action
-  def self.find_active_user(action, key, validity_days=nil)
-    user = find_user(action, key, validity_days)
-    if user && user.active?
-      user
-    end
-  end
-
-  # Returns the user who owns the key for the given action
-  def self.find_user(action, key, validity_days=nil)
-    token = find_token(action, key, validity_days)
-    if token
-      token.user
-    end
-  end
-
-  # Returns the token for action and key with an optional
-  # validity duration (in number of days)
-  def self.find_token(action, key, validity_days=nil)
-    action = action.to_s
-    key = key.to_s
-    return nil unless action.present? && key =~ /\A[a-z0-9]+\z/i
-
-    token = Token.where(:action => action, :value => key).first
-    if token && (token.action == action) && (token.value == key) && token.user
-      if validity_days.nil? || (token.created_on > validity_days.days.ago)
-        token
-      end
-    end
-  end
-
-  def self.generate_token_value
-    Redmine::Utils.random_hex(20)
-  end
-
-  private
-
-  # Removes obsolete tokens (same user and action)
-  def delete_previous_tokens
-    if user
-      Token.delete_all(['user_id = ? AND action = ?', user.id, action])
-    end
-  end
-end
--- a/.svn/pristine/23/23ff873f0bf0f2e45a3709caf12bc84dab7be570.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module SettingsHelper
-  def administration_settings_tabs
-    tabs = [{:name => 'general', :partial => 'settings/general', :label => :label_general},
-            {:name => 'display', :partial => 'settings/display', :label => :label_display},
-            {:name => 'authentication', :partial => 'settings/authentication', :label => :label_authentication},
-            {:name => 'projects', :partial => 'settings/projects', :label => :label_project_plural},
-            {:name => 'issues', :partial => 'settings/issues', :label => :label_issue_tracking},
-            {:name => 'notifications', :partial => 'settings/notifications', :label => :field_mail_notification},
-            {:name => 'mail_handler', :partial => 'settings/mail_handler', :label => :label_incoming_emails},
-            {:name => 'repositories', :partial => 'settings/repositories', :label => :label_repository_plural}
-            ]
-  end
-
-  def setting_select(setting, choices, options={})
-    if blank_text = options.delete(:blank)
-      choices = [[blank_text.is_a?(Symbol) ? l(blank_text) : blank_text, '']] + choices
-    end
-    setting_label(setting, options).html_safe +
-      select_tag("settings[#{setting}]",
-                 options_for_select(choices, Setting.send(setting).to_s),
-                 options).html_safe
-  end
-
-  def setting_multiselect(setting, choices, options={})
-    setting_values = Setting.send(setting)
-    setting_values = [] unless setting_values.is_a?(Array)
-
-    content_tag("label", l(options[:label] || "setting_#{setting}")) +
-      hidden_field_tag("settings[#{setting}][]", '').html_safe +
-      choices.collect do |choice|
-        text, value = (choice.is_a?(Array) ? choice : [choice, choice])
-        content_tag(
-          'label',
-          check_box_tag(
-             "settings[#{setting}][]",
-             value,
-             setting_values.include?(value),
-             :id => nil
-           ) + text.to_s,
-          :class => (options[:inline] ? 'inline' : 'block')
-         )
-      end.join.html_safe
-  end
-
-  def setting_text_field(setting, options={})
-    setting_label(setting, options).html_safe +
-      text_field_tag("settings[#{setting}]", Setting.send(setting), options).html_safe
-  end
-
-  def setting_text_area(setting, options={})
-    setting_label(setting, options).html_safe +
-      text_area_tag("settings[#{setting}]", Setting.send(setting), options).html_safe
-  end
-
-  def setting_check_box(setting, options={})
-    setting_label(setting, options).html_safe +
-      hidden_field_tag("settings[#{setting}]", 0, :id => nil).html_safe +
-        check_box_tag("settings[#{setting}]", 1, Setting.send("#{setting}?"), options).html_safe
-  end
-
-  def setting_label(setting, options={})
-    label = options.delete(:label)
-    label != false ? label_tag("settings_#{setting}", l(label || "setting_#{setting}")).html_safe : ''
-  end
-
-  # Renders a notification field for a Redmine::Notifiable option
-  def notification_field(notifiable)
-    return content_tag(:label,
-                       check_box_tag('settings[notified_events][]',
-                                     notifiable.name,
-                                     Setting.notified_events.include?(notifiable.name), :id => nil).html_safe +
-                         l_or_humanize(notifiable.name, :prefix => 'label_').html_safe,
-                       :class => notifiable.parent.present? ? "parent" : '').html_safe
-  end
-
-  def cross_project_subtasks_options
-    options = [
-      [:label_disabled, ''],
-      [:label_cross_project_system, 'system'],
-      [:label_cross_project_tree, 'tree'],
-      [:label_cross_project_hierarchy, 'hierarchy'],
-      [:label_cross_project_descendants, 'descendants']
-    ]
-
-    options.map {|label, value| [l(label), value.to_s]}
-  end
-end
--- a/.svn/pristine/24/2433aef8bea3b0c55a9f7bf03a1c8b0533749f72.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WelcomeControllerTest < ActionController::TestCase
-  fixtures :projects, :news, :users, :members
-
-  def setup
-    User.current = nil
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:news)
-    assert_not_nil assigns(:projects)
-    assert !assigns(:projects).include?(Project.where(:is_public => false).first)
-  end
-
-  def test_browser_language
-    Setting.default_language = 'en'
-    @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
-    get :index
-    assert_equal :fr, @controller.current_language
-  end
-
-  def test_browser_language_alternate
-    Setting.default_language = 'en'
-    @request.env['HTTP_ACCEPT_LANGUAGE'] = 'zh-TW'
-    get :index
-    assert_equal :"zh-TW", @controller.current_language
-  end
-
-  def test_browser_language_alternate_not_valid
-    Setting.default_language = 'en'
-    @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr-CA'
-    get :index
-    assert_equal :fr, @controller.current_language
-  end
-
-  def test_robots
-    get :robots
-    assert_response :success
-    assert_equal 'text/plain', @response.content_type
-    assert @response.body.match(%r{^Disallow: /projects/ecookbook/issues\r?$})
-  end
-
-  def test_warn_on_leaving_unsaved_turn_on
-    user = User.find(2)
-    user.pref.warn_on_leaving_unsaved = '1'
-    user.pref.save!
-    @request.session[:user_id] = 2
-
-    get :index
-    assert_tag 'script',
-      :attributes => {:type => "text/javascript"},
-      :content => %r{warnLeavingUnsaved}
-  end
-
-  def test_warn_on_leaving_unsaved_turn_off
-    user = User.find(2)
-    user.pref.warn_on_leaving_unsaved = '0'
-    user.pref.save!
-    @request.session[:user_id] = 2
-
-    get :index
-    assert_no_tag 'script',
-      :attributes => {:type => "text/javascript"},
-      :content => %r{warnLeavingUnsaved}
-  end
-
-  def test_logout_link_should_post
-    @request.session[:user_id] = 2
-
-    get :index
-    assert_select 'a[href=/logout][data-method=post]', :text => 'Sign out'
-  end
-
-  def test_call_hook_mixed_in
-    assert @controller.respond_to?(:call_hook)
-  end
-
-  def test_project_jump_box_should_escape_names_once
-    Project.find(1).update_attribute :name, 'Foo & Bar'
-    @request.session[:user_id] = 2
-
-    get :index
-    assert_select "#header select" do
-      assert_select "option", :text => 'Foo &amp; Bar'
-    end
-  end
-
-  def test_api_offset_and_limit_without_params
-    assert_equal [0, 25], @controller.api_offset_and_limit({})
-  end
-
-  def test_api_offset_and_limit_with_limit
-    assert_equal [0, 30], @controller.api_offset_and_limit({:limit => 30})
-    assert_equal [0, 100], @controller.api_offset_and_limit({:limit => 120})
-    assert_equal [0, 25], @controller.api_offset_and_limit({:limit => -10})
-  end
-
-  def test_api_offset_and_limit_with_offset
-    assert_equal [10, 25], @controller.api_offset_and_limit({:offset => 10})
-    assert_equal [0, 25], @controller.api_offset_and_limit({:offset => -10})
-  end
-
-  def test_api_offset_and_limit_with_offset_and_limit
-    assert_equal [10, 50], @controller.api_offset_and_limit({:offset => 10, :limit => 50})
-  end
-
-  def test_api_offset_and_limit_with_page
-    assert_equal [0, 25], @controller.api_offset_and_limit({:page => 1})
-    assert_equal [50, 25], @controller.api_offset_and_limit({:page => 3})
-    assert_equal [0, 25], @controller.api_offset_and_limit({:page => 0})
-    assert_equal [0, 25], @controller.api_offset_and_limit({:page => -2})
-  end
-
-  def test_api_offset_and_limit_with_page_and_limit
-    assert_equal [0, 100], @controller.api_offset_and_limit({:page => 1, :limit => 100})
-    assert_equal [200, 100], @controller.api_offset_and_limit({:page => 3, :limit => 100})
-  end
-
-  def test_unhautorized_exception_with_anonymous_should_redirect_to_login
-    WelcomeController.any_instance.stubs(:index).raises(::Unauthorized)
-
-    get :index
-    assert_response 302
-    assert_redirected_to('/login?back_url='+CGI.escape('http://test.host/'))
-  end
-
-  def test_unhautorized_exception_with_anonymous_and_xmlhttprequest_should_respond_with_401_to_anonymous
-    WelcomeController.any_instance.stubs(:index).raises(::Unauthorized)
-
-    @request.env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
-    get :index
-    assert_response 401
-  end
-end
--- a/.svn/pristine/24/24abfa79128b2a39ef97f13bee5e153f6b122577.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module WorkflowsHelper
-  def field_required?(field)
-    field.is_a?(CustomField) ? field.is_required? : %w(project_id tracker_id subject priority_id is_private).include?(field)
-  end
-
-  def field_permission_tag(permissions, status, field, role)
-    name = field.is_a?(CustomField) ? field.id.to_s : field
-    options = [["", ""], [l(:label_readonly), "readonly"]]
-    options << [l(:label_required), "required"] unless field_required?(field)
-    html_options = {}
-    selected = permissions[status.id][name]
-
-    hidden = field.is_a?(CustomField) && !field.visible? && !role.custom_fields.to_a.include?(field)
-    if hidden
-      options[0][0] = l(:label_hidden)
-      selected = ''
-      html_options[:disabled] = true
-    end
-
-    select_tag("permissions[#{name}][#{status.id}]", options_for_select(options, selected), html_options)
-  end
-end
--- a/.svn/pristine/24/24b4bc532dbfbdbadb24d22bdcba74f2493b0b5a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingVersionsTest < ActionController::IntegrationTest
-  def test_roadmap
-    # /projects/foo/versions is /projects/foo/roadmap
-    assert_routing(
-        { :method => 'get', :path => "/projects/33/roadmap" },
-        { :controller => 'versions', :action => 'index', :project_id => '33' }
-      )
-  end
-
-  def test_versions_scoped_under_project
-    assert_routing(
-        { :method => 'put', :path => "/projects/foo/versions/close_completed" },
-        { :controller => 'versions', :action => 'close_completed',
-          :project_id => 'foo' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/foo/versions.xml" },
-        { :controller => 'versions', :action => 'index',
-          :project_id => 'foo', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/foo/versions.json" },
-        { :controller => 'versions', :action => 'index',
-          :project_id => 'foo', :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/foo/versions/new" },
-        { :controller => 'versions', :action => 'new',
-          :project_id => 'foo' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/foo/versions" },
-        { :controller => 'versions', :action => 'create',
-          :project_id => 'foo' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/foo/versions.xml" },
-        { :controller => 'versions', :action => 'create',
-          :project_id => 'foo', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/foo/versions.json" },
-        { :controller => 'versions', :action => 'create',
-          :project_id => 'foo', :format => 'json' }
-      )
-  end
-
-  def test_versions
-    assert_routing(
-        { :method => 'get', :path => "/versions/1" },
-        { :controller => 'versions', :action => 'show', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/versions/1.xml" },
-        { :controller => 'versions', :action => 'show', :id => '1',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/versions/1.json" },
-        { :controller => 'versions', :action => 'show', :id => '1',
-          :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/versions/1/edit" },
-        { :controller => 'versions', :action => 'edit', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/versions/1" },
-        { :controller => 'versions', :action => 'update', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/versions/1.xml" },
-        { :controller => 'versions', :action => 'update', :id => '1',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/versions/1.json" },
-        { :controller => 'versions', :action => 'update', :id => '1',
-          :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/versions/1" },
-        { :controller => 'versions', :action => 'destroy', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/versions/1.xml" },
-        { :controller => 'versions', :action => 'destroy', :id => '1',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/versions/1.json" },
-        { :controller => 'versions', :action => 'destroy', :id => '1',
-          :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/versions/1/status_by" },
-        { :controller => 'versions', :action => 'status_by', :id => '1' }
-      )
-  end
-end
--- a/.svn/pristine/24/24ebd90070f1307a8f6d2f2f35671e06e60bb2b7.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class MessageTest < ActiveSupport::TestCase
-  fixtures :projects, :roles, :members, :member_roles, :boards, :messages,
-           :users, :watchers, :enabled_modules
-
-  def setup
-    @board = Board.find(1)
-    @user = User.find(1)
-  end
-
-  def test_create
-    topics_count = @board.topics_count
-    messages_count = @board.messages_count
-
-    message = Message.new(:board => @board, :subject => 'Test message',
-                          :content => 'Test message content',
-                          :author => @user)
-    assert message.save
-    @board.reload
-    # topics count incremented
-    assert_equal topics_count + 1, @board[:topics_count]
-    # messages count incremented
-    assert_equal messages_count + 1, @board[:messages_count]
-    assert_equal message, @board.last_message
-    # author should be watching the message
-    assert message.watched_by?(@user)
-  end
-
-  def test_reply
-    topics_count = @board.topics_count
-    messages_count = @board.messages_count
-    message = Message.find(1)
-    replies_count = message.replies_count
-
-    reply_author = User.find(2)
-    reply = Message.new(:board => @board, :subject => 'Test reply',
-                        :content => 'Test reply content',
-                        :parent => message, :author => reply_author)
-    assert reply.save
-    @board.reload
-    # same topics count
-    assert_equal topics_count, @board[:topics_count]
-    # messages count incremented
-    assert_equal messages_count+1, @board[:messages_count]
-    assert_equal reply, @board.last_message
-    message.reload
-    # replies count incremented
-    assert_equal replies_count+1, message[:replies_count]
-    assert_equal reply, message.last_reply
-    # author should be watching the message
-    assert message.watched_by?(reply_author)
-  end
-
-  def test_cannot_reply_to_locked_topic
-    topics_count = @board.topics_count
-    messages_count = @board.messages_count
-    message = Message.find(1)
-    replies_count = message.replies_count
-    assert_equal false, message.locked
-    message.locked = true
-    assert message.save
-    assert_equal true, message.locked
-
-    reply_author = User.find(2)
-    reply = Message.new(:board => @board, :subject => 'Test reply',
-                        :content => 'Test reply content',
-                        :parent => message, :author => reply_author)
-    reply.save
-    assert_equal 1, reply.errors.count
-  end
-
-  def test_moving_message_should_update_counters
-    message = Message.find(1)
-    assert_no_difference 'Message.count' do
-      # Previous board
-      assert_difference 'Board.find(1).topics_count', -1 do
-        assert_difference 'Board.find(1).messages_count', -(1 + message.replies_count) do
-          # New board
-          assert_difference 'Board.find(2).topics_count' do
-            assert_difference 'Board.find(2).messages_count', (1 + message.replies_count) do
-              message.update_attributes(:board_id => 2)
-            end
-          end
-        end
-      end
-    end
-  end
-
-  def test_destroy_topic
-    message = Message.find(1)
-    board = message.board
-    topics_count, messages_count = board.topics_count, board.messages_count
-
-    assert_difference('Watcher.count', -1) do
-      assert message.destroy
-    end
-    board.reload
-
-    # Replies deleted
-    assert Message.find_all_by_parent_id(1).empty?
-    # Checks counters
-    assert_equal topics_count - 1, board.topics_count
-    assert_equal messages_count - 3, board.messages_count
-    # Watchers removed
-  end
-
-  def test_destroy_reply
-    message = Message.find(5)
-    board = message.board
-    topics_count, messages_count = board.topics_count, board.messages_count
-    assert message.destroy
-    board.reload
-
-    # Checks counters
-    assert_equal topics_count, board.topics_count
-    assert_equal messages_count - 1, board.messages_count
-  end
-
-  def test_destroying_last_reply_should_update_topic_last_reply_id
-    topic = Message.find(4)
-    assert_equal 6, topic.last_reply_id
-
-    assert_difference 'Message.count', -1 do
-      Message.find(6).destroy
-    end
-    assert_equal 5, topic.reload.last_reply_id
-
-    assert_difference 'Message.count', -1 do
-      Message.find(5).destroy
-    end
-    assert_nil topic.reload.last_reply_id
-  end
-
-  def test_editable_by
-    message = Message.find(6)
-    author = message.author
-    assert message.editable_by?(author)
-
-    author.roles_for_project(message.project).first.remove_permission!(:edit_own_messages)
-    assert !message.reload.editable_by?(author.reload)
-  end
-
-  def test_destroyable_by
-    message = Message.find(6)
-    author = message.author
-    assert message.destroyable_by?(author)
-
-    author.roles_for_project(message.project).first.remove_permission!(:delete_own_messages)
-    assert !message.reload.destroyable_by?(author.reload)
-  end
-
-  def test_set_sticky
-    message = Message.new
-    assert_equal 0, message.sticky
-    message.sticky = nil
-    assert_equal 0, message.sticky
-    message.sticky = false
-    assert_equal 0, message.sticky
-    message.sticky = true
-    assert_equal 1, message.sticky
-    message.sticky = '0'
-    assert_equal 0, message.sticky
-    message.sticky = '1'
-    assert_equal 1, message.sticky
-  end
-end
--- a/.svn/pristine/25/25f1da6f66db9d07326385e2039be298e7f220f8.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::ConfigurationTest < ActiveSupport::TestCase
-  def setup
-    @conf = Redmine::Configuration
-  end
-
-  def test_empty
-    assert_kind_of Hash, load_conf('empty.yml', 'test')
-  end
-
-  def test_default
-    assert_kind_of Hash, load_conf('default.yml', 'test')
-    assert_equal 'foo', @conf['somesetting']
-  end
-
-  def test_no_default
-    assert_kind_of Hash, load_conf('no_default.yml', 'test')
-    assert_equal 'foo', @conf['somesetting']
-  end
-
-  def test_overrides
-    assert_kind_of Hash, load_conf('overrides.yml', 'test')
-    assert_equal 'bar', @conf['somesetting']
-  end
-
-  def test_with
-    load_conf('default.yml', 'test')
-    assert_equal 'foo', @conf['somesetting']
-    @conf.with 'somesetting' => 'bar' do
-      assert_equal 'bar', @conf['somesetting']
-    end
-    assert_equal 'foo', @conf['somesetting']
-  end
-
-  private
-
-  def load_conf(file, env)
-    @conf.load(
-      :file => File.join(Rails.root, 'test', 'fixtures', 'configuration', file),
-      :env => env
-    )
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/26/266dfa6887b7544baedd932a1d45fffff0382a86.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,388 @@
+# Redmine - project management software
+# Copyright (C) 2006-2014  Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+class CustomField < ActiveRecord::Base
+  include Redmine::SubclassFactory
+
+  has_many :custom_values, :dependent => :delete_all
+  has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}custom_fields_roles#{table_name_suffix}", :foreign_key => "custom_field_id"
+  acts_as_list :scope => 'type = \'#{self.class}\''
+  serialize :possible_values
+
+  validates_presence_of :name, :field_format
+  validates_uniqueness_of :name, :scope => :type
+  validates_length_of :name, :maximum => 30
+  validates_inclusion_of :field_format, :in => Proc.new { Redmine::CustomFieldFormat.available_formats }
+  validate :validate_custom_field
+
+  before_validation :set_searchable
+  after_save :handle_multiplicity_change
+  after_save do |field|
+    if field.visible_changed? && field.visible
+      field.roles.clear
+    end
+  end
+
+  scope :sorted, lambda { order("#{table_name}.position ASC") }
+  scope :visible, lambda {|*args|
+    user = args.shift || User.current
+    if user.admin?
+      # nop
+    elsif user.memberships.any?
+      where("#{table_name}.visible = ? OR #{table_name}.id IN (SELECT DISTINCT cfr.custom_field_id FROM #{Member.table_name} m" +
+        " INNER JOIN #{MemberRole.table_name} mr ON mr.member_id = m.id" +
+        " INNER JOIN #{table_name_prefix}custom_fields_roles#{table_name_suffix} cfr ON cfr.role_id = mr.role_id" +
+        " WHERE m.user_id = ?)",
+        true, user.id)
+    else
+      where(:visible => true)
+    end
+  }
+
+  def visible_by?(project, user=User.current)
+    visible? || user.admin?
+  end
+
+  def field_format=(arg)
+    # cannot change format of a saved custom field
+    super if new_record?
+  end
+
+  def set_searchable
+    # make sure these fields are not searchable
+    self.searchable = false if %w(int float date bool).include?(field_format)
+    # make sure only these fields can have multiple values
+    self.multiple = false unless %w(list user version).include?(field_format)
+    true
+  end
+
+  def validate_custom_field
+    if self.field_format == "list"
+      errors.add(:possible_values, :blank) if self.possible_values.nil? || self.possible_values.empty?
+      errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array
+    end
+
+    if regexp.present?
+      begin
+        Regexp.new(regexp)
+      rescue
+        errors.add(:regexp, :invalid)
+      end
+    end
+
+    if default_value.present? && !valid_field_value?(default_value)
+      errors.add(:default_value, :invalid)
+    end
+  end
+
+  def possible_values_options(obj=nil)
+    case field_format
+    when 'user', 'version'
+      if obj.respond_to?(:project) && obj.project
+        case field_format
+        when 'user'
+          obj.project.users.sort.collect {|u| [u.to_s, u.id.to_s]}
+        when 'version'
+          obj.project.shared_versions.sort.collect {|u| [u.to_s, u.id.to_s]}
+        end
+      elsif obj.is_a?(Array)
+        obj.collect {|o| possible_values_options(o)}.reduce(:&)
+      else
+        []
+      end
+    when 'bool'
+      [[l(:general_text_Yes), '1'], [l(:general_text_No), '0']]
+    else
+      possible_values || []
+    end
+  end
+
+  def possible_values(obj=nil)
+    case field_format
+    when 'user', 'version'
+      possible_values_options(obj).collect(&:last)
+    when 'bool'
+      ['1', '0']
+    else
+      values = super()
+      if values.is_a?(Array)
+        values.each do |value|
+          value.force_encoding('UTF-8') if value.respond_to?(:force_encoding)
+        end
+        values
+      else
+        []
+      end
+    end
+  end
+
+  # Makes possible_values accept a multiline string
+  def possible_values=(arg)
+    if arg.is_a?(Array)
+      super(arg.compact.collect(&:strip).select {|v| !v.blank?})
+    else
+      self.possible_values = arg.to_s.split(/[\n\r]+/)
+    end
+  end
+
+  def cast_value(value)
+    casted = nil
+    unless value.blank?
+      case field_format
+      when 'string', 'text', 'list'
+        casted = value
+      when 'date'
+        casted = begin; value.to_date; rescue; nil end
+      when 'bool'
+        casted = (value == '1' ? true : false)
+      when 'int'
+        casted = value.to_i
+      when 'float'
+        casted = value.to_f
+      when 'user', 'version'
+        casted = (value.blank? ? nil : field_format.classify.constantize.find_by_id(value.to_i))
+      end
+    end
+    casted
+  end
+
+  def value_from_keyword(keyword, customized)
+    possible_values_options = possible_values_options(customized)
+    if possible_values_options.present?
+      keyword = keyword.to_s.downcase
+      if v = possible_values_options.detect {|text, id| text.downcase == keyword}
+        if v.is_a?(Array)
+          v.last
+        else
+          v
+        end
+      end
+    else
+      keyword
+    end
+  end
+
+  # Returns a ORDER BY clause that can used to sort customized
+  # objects by their value of the custom field.
+  # Returns nil if the custom field can not be used for sorting.
+  def order_statement
+    return nil if multiple?
+    case field_format
+      when 'string', 'text', 'list', 'date', 'bool'
+        # COALESCE is here to make sure that blank and NULL values are sorted equally
+        "COALESCE(#{join_alias}.value, '')"
+      when 'int', 'float'
+        # Make the database cast values into numeric
+        # Postgresql will raise an error if a value can not be casted!
+        # CustomValue validations should ensure that it doesn't occur
+        "CAST(CASE #{join_alias}.value WHEN '' THEN '0' ELSE #{join_alias}.value END AS decimal(30,3))"
+      when 'user', 'version'
+        value_class.fields_for_order_statement(value_join_alias)
+      else
+        nil
+    end
+  end
+
+  # Returns a GROUP BY clause that can used to group by custom value
+  # Returns nil if the custom field can not be used for grouping.
+  def group_statement
+    return nil if multiple?
+    case field_format
+      when 'list', 'date', 'bool', 'int'
+        order_statement
+      when 'user', 'version'
+        "COALESCE(#{join_alias}.value, '')"
+      else
+        nil
+    end
+  end
+
+  def join_for_order_statement
+    case field_format
+      when 'user', 'version'
+        "LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
+          " ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
+          " AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
+          " AND #{join_alias}.custom_field_id = #{id}" +
+          " AND (#{visibility_by_project_condition})" +
+          " AND #{join_alias}.value <> ''" +
+          " AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
+            " WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
+            " AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
+            " AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)" +
+          " LEFT OUTER JOIN #{value_class.table_name} #{value_join_alias}" +
+          " ON CAST(CASE #{join_alias}.value WHEN '' THEN '0' ELSE #{join_alias}.value END AS decimal(30,0)) = #{value_join_alias}.id"
+      when 'int', 'float'
+        "LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
+          " ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
+          " AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
+          " AND #{join_alias}.custom_field_id = #{id}" +
+          " AND (#{visibility_by_project_condition})" +
+          " AND #{join_alias}.value <> ''" +
+          " AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
+            " WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
+            " AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
+            " AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)"
+      when 'string', 'text', 'list', 'date', 'bool'
+        "LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
+          " ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
+          " AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
+          " AND #{join_alias}.custom_field_id = #{id}" +
+          " AND (#{visibility_by_project_condition})" +
+          " AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
+            " WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
+            " AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
+            " AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)"
+      else
+        nil
+    end
+  end
+
+  def join_alias
+    "cf_#{id}"
+  end
+
+  def value_join_alias
+    join_alias + "_" + field_format
+  end
+
+  def visibility_by_project_condition(project_key=nil, user=User.current)
+    if visible? || user.admin?
+      "1=1"
+    elsif user.anonymous?
+      "1=0"
+    else
+      project_key ||= "#{self.class.customized_class.table_name}.project_id"
+      "#{project_key} IN (SELECT DISTINCT m.project_id FROM #{Member.table_name} m" +
+        " INNER JOIN #{MemberRole.table_name} mr ON mr.member_id = m.id" +
+        " INNER JOIN #{table_name_prefix}custom_fields_roles#{table_name_suffix} cfr ON cfr.role_id = mr.role_id" +
+        " WHERE m.user_id = #{user.id} AND cfr.custom_field_id = #{id})"
+    end
+  end
+
+  def self.visibility_condition
+    if user.admin?
+      "1=1"
+    elsif user.anonymous?
+      "#{table_name}.visible"
+    else
+      "#{project_key} IN (SELECT DISTINCT m.project_id FROM #{Member.table_name} m" +
+        " INNER JOIN #{MemberRole.table_name} mr ON mr.member_id = m.id" +
+        " INNER JOIN #{table_name_prefix}custom_fields_roles#{table_name_suffix} cfr ON cfr.role_id = mr.role_id" +
+        " WHERE m.user_id = #{user.id} AND cfr.custom_field_id = #{id})"
+    end
+  end
+
+  def <=>(field)
+    position <=> field.position
+  end
+
+  # Returns the class that values represent
+  def value_class
+    case field_format
+      when 'user', 'version'
+        field_format.classify.constantize
+      else
+        nil
+    end
+  end
+
+  def self.customized_class
+    self.name =~ /^(.+)CustomField$/
+    $1.constantize rescue nil
+  end
+
+  # to move in project_custom_field
+  def self.for_all
+    where(:is_for_all => true).order('position').all
+  end
+
+  def type_name
+    nil
+  end
+
+  # Returns the error messages for the given value
+  # or an empty array if value is a valid value for the custom field
+  def validate_field_value(value)
+    errs = []
+    if value.is_a?(Array)
+      if !multiple?
+        errs << ::I18n.t('activerecord.errors.messages.invalid')
+      end
+      if is_required? && value.detect(&:present?).nil?
+        errs << ::I18n.t('activerecord.errors.messages.blank')
+      end
+      value.each {|v| errs += validate_field_value_format(v)}
+    else
+      if is_required? && value.blank?
+        errs << ::I18n.t('activerecord.errors.messages.blank')
+      end
+      errs += validate_field_value_format(value)
+    end
+    errs
+  end
+
+  # Returns true if value is a valid value for the custom field
+  def valid_field_value?(value)
+    validate_field_value(value).empty?
+  end
+
+  def format_in?(*args)
+    args.include?(field_format)
+  end
+
+  protected
+
+  # Returns the error message for the given value regarding its format
+  def validate_field_value_format(value)
+    errs = []
+    unless value.to_s == ''
+      errs << ::I18n.t('activerecord.errors.messages.invalid') unless regexp.blank? or value =~ Regexp.new(regexp)
+      errs << ::I18n.t('activerecord.errors.messages.too_short', :count => min_length) if min_length && min_length > 0 && value.length < min_length
+      errs << ::I18n.t('activerecord.errors.messages.too_long', :count => max_length) if max_length && max_length > 0 && value.length > max_length
+
+      # Format specific validations
+      case field_format
+      when 'int'
+        errs << ::I18n.t('activerecord.errors.messages.not_a_number') unless value =~ /^[+-]?\d+$/
+      when 'float'
+        begin; Kernel.Float(value); rescue; errs << ::I18n.t('activerecord.errors.messages.invalid') end
+      when 'date'
+        errs << ::I18n.t('activerecord.errors.messages.not_a_date') unless value =~ /^\d{4}-\d{2}-\d{2}$/ && begin; value.to_date; rescue; false end
+      when 'list'
+        errs << ::I18n.t('activerecord.errors.messages.inclusion') unless possible_values.include?(value)
+      end
+    end
+    errs
+  end
+
+  # Removes multiple values for the custom field after setting the multiple attribute to false
+  # We kepp the value with the highest id for each customized object
+  def handle_multiplicity_change
+    if !new_record? && multiple_was && !multiple
+      ids = custom_values.
+        where("EXISTS(SELECT 1 FROM #{CustomValue.table_name} cve WHERE cve.custom_field_id = #{CustomValue.table_name}.custom_field_id" +
+          " AND cve.customized_type = #{CustomValue.table_name}.customized_type AND cve.customized_id = #{CustomValue.table_name}.customized_id" +
+          " AND cve.id > #{CustomValue.table_name}.id)").
+        pluck(:id)
+
+      if ids.any?
+        custom_values.where(:id => ids).delete_all
+      end
+    end
+  end
+end
--- a/.svn/pristine/26/268f3cd3f61de314baeae7c147ac3b2585846bcc.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class SysController < ActionController::Base
-  before_filter :check_enabled
-
-  def projects
-    p = Project.active.has_module(:repository).order("#{Project.table_name}.identifier").preload(:repository).all
-    # extra_info attribute from repository breaks activeresource client
-    render :xml => p.to_xml(
-                       :only => [:id, :identifier, :name, :is_public, :status],
-                       :include => {:repository => {:only => [:id, :url]}}
-                     )
-  end
-
-  def create_project_repository
-    project = Project.find(params[:id])
-    if project.repository
-      render :nothing => true, :status => 409
-    else
-      logger.info "Repository for #{project.name} was reported to be created by #{request.remote_ip}."
-      repository = Repository.factory(params[:vendor], params[:repository])
-      repository.project = project
-      if repository.save
-        render :xml => {repository.class.name.underscore.gsub('/', '-') => {:id => repository.id, :url => repository.url}}, :status => 201
-      else
-        render :nothing => true, :status => 422
-      end
-    end
-  end
-
-  def fetch_changesets
-    projects = []
-    scope = Project.active.has_module(:repository)
-    if params[:id]
-      project = nil
-      if params[:id].to_s =~ /^\d*$/
-        project = scope.find(params[:id])
-      else
-        project = scope.find_by_identifier(params[:id])
-      end
-      raise ActiveRecord::RecordNotFound unless project
-      projects << project
-    else
-      projects = scope.all
-    end
-    projects.each do |project|
-      project.repositories.each do |repository|
-        repository.fetch_changesets
-      end
-    end
-    render :nothing => true, :status => 200
-  rescue ActiveRecord::RecordNotFound
-    render :nothing => true, :status => 404
-  end
-
-  protected
-
-  def check_enabled
-    User.current = nil
-    unless Setting.sys_api_enabled? && params[:key].to_s == Setting.sys_api_key
-      render :text => 'Access denied. Repository management WS is disabled or key is invalid.', :status => 403
-      return false
-    end
-  end
-end
--- a/.svn/pristine/26/26cd514059c01b6bbe50d8e07c103ad7d4e81104.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,483 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssueQuery < Query
-
-  self.queried_class = Issue
-
-  self.available_columns = [
-    QueryColumn.new(:id, :sortable => "#{Issue.table_name}.id", :default_order => 'desc', :caption => '#', :frozen => true),
-    QueryColumn.new(:project, :sortable => "#{Project.table_name}.name", :groupable => true),
-    QueryColumn.new(:tracker, :sortable => "#{Tracker.table_name}.position", :groupable => true),
-    QueryColumn.new(:parent, :sortable => ["#{Issue.table_name}.root_id", "#{Issue.table_name}.lft ASC"], :default_order => 'desc', :caption => :field_parent_issue),
-    QueryColumn.new(:status, :sortable => "#{IssueStatus.table_name}.position", :groupable => true),
-    QueryColumn.new(:priority, :sortable => "#{IssuePriority.table_name}.position", :default_order => 'desc', :groupable => true),
-    QueryColumn.new(:subject, :sortable => "#{Issue.table_name}.subject"),
-    QueryColumn.new(:author, :sortable => lambda {User.fields_for_order_statement("authors")}, :groupable => true),
-    QueryColumn.new(:assigned_to, :sortable => lambda {User.fields_for_order_statement}, :groupable => true),
-    QueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on", :default_order => 'desc'),
-    QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name", :groupable => true),
-    QueryColumn.new(:fixed_version, :sortable => lambda {Version.fields_for_order_statement}, :groupable => true),
-    QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date"),
-    QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"),
-    QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours"),
-    QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio", :groupable => true),
-    QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'),
-    QueryColumn.new(:closed_on, :sortable => "#{Issue.table_name}.closed_on", :default_order => 'desc'),
-    QueryColumn.new(:relations, :caption => :label_related_issues),
-    QueryColumn.new(:description, :inline => false)
-  ]
-
-  scope :visible, lambda {|*args|
-    user = args.shift || User.current
-    base = Project.allowed_to_condition(user, :view_issues, *args)
-    scope = includes(:project).where("#{table_name}.project_id IS NULL OR (#{base})")
-
-    if user.admin?
-      scope.where("#{table_name}.visibility <> ? OR #{table_name}.user_id = ?", VISIBILITY_PRIVATE, user.id)
-    elsif user.memberships.any?
-      scope.where("#{table_name}.visibility = ?" +
-        " OR (#{table_name}.visibility = ? AND #{table_name}.id IN (" +
-          "SELECT DISTINCT q.id FROM #{table_name} q" +
-          " INNER JOIN #{table_name_prefix}queries_roles#{table_name_suffix} qr on qr.query_id = q.id" +
-          " INNER JOIN #{MemberRole.table_name} mr ON mr.role_id = qr.role_id" +
-          " INNER JOIN #{Member.table_name} m ON m.id = mr.member_id AND m.user_id = ?" +
-          " WHERE q.project_id IS NULL OR q.project_id = m.project_id))" +
-        " OR #{table_name}.user_id = ?",
-        VISIBILITY_PUBLIC, VISIBILITY_ROLES, user.id, user.id)
-    elsif user.logged?
-      scope.where("#{table_name}.visibility = ? OR #{table_name}.user_id = ?", VISIBILITY_PUBLIC, user.id)
-    else
-      scope.where("#{table_name}.visibility = ?", VISIBILITY_PUBLIC)
-    end
-  }
-
-  def initialize(attributes=nil, *args)
-    super attributes
-    self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
-  end
-
-  # Returns true if the query is visible to +user+ or the current user.
-  def visible?(user=User.current)
-    return true if user.admin?
-    return false unless project.nil? || user.allowed_to?(:view_issues, project)
-    case visibility
-    when VISIBILITY_PUBLIC
-      true
-    when VISIBILITY_ROLES
-      if project
-        (user.roles_for_project(project) & roles).any?
-      else
-        Member.where(:user_id => user.id).joins(:roles).where(:member_roles => {:role_id => roles.map(&:id)}).any?
-      end
-    else
-      user == self.user
-    end
-  end
-
-  def is_private?
-    visibility == VISIBILITY_PRIVATE
-  end
-
-  def is_public?
-    !is_private?
-  end
-
-  def draw_relations
-    r = options[:draw_relations]
-    r.nil? || r == '1'
-  end
-
-  def draw_relations=(arg)
-    options[:draw_relations] = (arg == '0' ? '0' : nil)
-  end
-
-  def draw_progress_line
-    r = options[:draw_progress_line]
-    r == '1'
-  end
-
-  def draw_progress_line=(arg)
-    options[:draw_progress_line] = (arg == '1' ? '1' : nil)
-  end
-
-  def build_from_params(params)
-    super
-    self.draw_relations = params[:draw_relations] || (params[:query] && params[:query][:draw_relations])
-    self.draw_progress_line = params[:draw_progress_line] || (params[:query] && params[:query][:draw_progress_line])
-    self
-  end
-
-  def initialize_available_filters
-    principals = []
-    subprojects = []
-    versions = []
-    categories = []
-    issue_custom_fields = []
-
-    if project
-      principals += project.principals.sort
-      unless project.leaf?
-        subprojects = project.descendants.visible.all
-        principals += Principal.member_of(subprojects)
-      end
-      versions = project.shared_versions.all
-      categories = project.issue_categories.all
-      issue_custom_fields = project.all_issue_custom_fields
-    else
-      if all_projects.any?
-        principals += Principal.member_of(all_projects)
-      end
-      versions = Version.visible.find_all_by_sharing('system')
-      issue_custom_fields = IssueCustomField.where(:is_for_all => true)
-    end
-    principals.uniq!
-    principals.sort!
-    users = principals.select {|p| p.is_a?(User)}
-
-    add_available_filter "status_id",
-      :type => :list_status, :values => IssueStatus.sorted.all.collect{|s| [s.name, s.id.to_s] }
-
-    if project.nil?
-      project_values = []
-      if User.current.logged? && User.current.memberships.any?
-        project_values << ["<< #{l(:label_my_projects).downcase} >>", "mine"]
-      end
-      project_values += all_projects_values
-      add_available_filter("project_id",
-        :type => :list, :values => project_values
-      ) unless project_values.empty?
-    end
-
-    add_available_filter "tracker_id",
-      :type => :list, :values => trackers.collect{|s| [s.name, s.id.to_s] }
-    add_available_filter "priority_id",
-      :type => :list, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] }
-
-    author_values = []
-    author_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
-    author_values += users.collect{|s| [s.name, s.id.to_s] }
-    add_available_filter("author_id",
-      :type => :list, :values => author_values
-    ) unless author_values.empty?
-
-    assigned_to_values = []
-    assigned_to_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
-    assigned_to_values += (Setting.issue_group_assignment? ?
-                              principals : users).collect{|s| [s.name, s.id.to_s] }
-    add_available_filter("assigned_to_id",
-      :type => :list_optional, :values => assigned_to_values
-    ) unless assigned_to_values.empty?
-
-    group_values = Group.all.collect {|g| [g.name, g.id.to_s] }
-    add_available_filter("member_of_group",
-      :type => :list_optional, :values => group_values
-    ) unless group_values.empty?
-
-    role_values = Role.givable.collect {|r| [r.name, r.id.to_s] }
-    add_available_filter("assigned_to_role",
-      :type => :list_optional, :values => role_values
-    ) unless role_values.empty?
-
-    if versions.any?
-      add_available_filter "fixed_version_id",
-        :type => :list_optional,
-        :values => versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] }
-    end
-
-    if categories.any?
-      add_available_filter "category_id",
-        :type => :list_optional,
-        :values => categories.collect{|s| [s.name, s.id.to_s] }
-    end
-
-    add_available_filter "subject", :type => :text
-    add_available_filter "created_on", :type => :date_past
-    add_available_filter "updated_on", :type => :date_past
-    add_available_filter "closed_on", :type => :date_past
-    add_available_filter "start_date", :type => :date
-    add_available_filter "due_date", :type => :date
-    add_available_filter "estimated_hours", :type => :float
-    add_available_filter "done_ratio", :type => :integer
-
-    if User.current.allowed_to?(:set_issues_private, nil, :global => true) ||
-      User.current.allowed_to?(:set_own_issues_private, nil, :global => true)
-      add_available_filter "is_private",
-        :type => :list,
-        :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]]
-    end
-
-    if User.current.logged?
-      add_available_filter "watcher_id",
-        :type => :list, :values => [["<< #{l(:label_me)} >>", "me"]]
-    end
-
-    if subprojects.any?
-      add_available_filter "subproject_id",
-        :type => :list_subprojects,
-        :values => subprojects.collect{|s| [s.name, s.id.to_s] }
-    end
-
-    add_custom_fields_filters(issue_custom_fields)
-
-    add_associations_custom_fields_filters :project, :author, :assigned_to, :fixed_version
-
-    IssueRelation::TYPES.each do |relation_type, options|
-      add_available_filter relation_type, :type => :relation, :label => options[:name]
-    end
-
-    Tracker.disabled_core_fields(trackers).each {|field|
-      delete_available_filter field
-    }
-  end
-
-  def available_columns
-    return @available_columns if @available_columns
-    @available_columns = self.class.available_columns.dup
-    @available_columns += (project ?
-                            project.all_issue_custom_fields :
-                            IssueCustomField
-                           ).visible.collect {|cf| QueryCustomFieldColumn.new(cf) }
-
-    if User.current.allowed_to?(:view_time_entries, project, :global => true)
-      index = nil
-      @available_columns.each_with_index {|column, i| index = i if column.name == :estimated_hours}
-      index = (index ? index + 1 : -1)
-      # insert the column after estimated_hours or at the end
-      @available_columns.insert index, QueryColumn.new(:spent_hours,
-        :sortable => "COALESCE((SELECT SUM(hours) FROM #{TimeEntry.table_name} WHERE #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id), 0)",
-        :default_order => 'desc',
-        :caption => :label_spent_time
-      )
-    end
-
-    if User.current.allowed_to?(:set_issues_private, nil, :global => true) ||
-      User.current.allowed_to?(:set_own_issues_private, nil, :global => true)
-      @available_columns << QueryColumn.new(:is_private, :sortable => "#{Issue.table_name}.is_private")
-    end
-
-    disabled_fields = Tracker.disabled_core_fields(trackers).map {|field| field.sub(/_id$/, '')}
-    @available_columns.reject! {|column|
-      disabled_fields.include?(column.name.to_s)
-    }
-
-    @available_columns
-  end
-
-  def default_columns_names
-    @default_columns_names ||= begin
-      default_columns = Setting.issue_list_default_columns.map(&:to_sym)
-
-      project.present? ? default_columns : [:project] | default_columns
-    end
-  end
-
-  # Returns the issue count
-  def issue_count
-    Issue.visible.joins(:status, :project).where(statement).count
-  rescue ::ActiveRecord::StatementInvalid => e
-    raise StatementInvalid.new(e.message)
-  end
-
-  # Returns the issue count by group or nil if query is not grouped
-  def issue_count_by_group
-    r = nil
-    if grouped?
-      begin
-        # Rails3 will raise an (unexpected) RecordNotFound if there's only a nil group value
-        r = Issue.visible.
-          joins(:status, :project).
-          where(statement).
-          joins(joins_for_order_statement(group_by_statement)).
-          group(group_by_statement).
-          count
-      rescue ActiveRecord::RecordNotFound
-        r = {nil => issue_count}
-      end
-      c = group_by_column
-      if c.is_a?(QueryCustomFieldColumn)
-        r = r.keys.inject({}) {|h, k| h[c.custom_field.cast_value(k)] = r[k]; h}
-      end
-    end
-    r
-  rescue ::ActiveRecord::StatementInvalid => e
-    raise StatementInvalid.new(e.message)
-  end
-
-  # Returns the issues
-  # Valid options are :order, :offset, :limit, :include, :conditions
-  def issues(options={})
-    order_option = [group_by_sort_order, options[:order]].flatten.reject(&:blank?)
-
-    scope = Issue.visible.
-      joins(:status, :project).
-      where(statement).
-      includes(([:status, :project] + (options[:include] || [])).uniq).
-      where(options[:conditions]).
-      order(order_option).
-      joins(joins_for_order_statement(order_option.join(','))).
-      limit(options[:limit]).
-      offset(options[:offset])
-
-    if has_custom_field_column?
-      scope = scope.preload(:custom_values)
-    end
-
-    issues = scope.all
-
-    if has_column?(:spent_hours)
-      Issue.load_visible_spent_hours(issues)
-    end
-    if has_column?(:relations)
-      Issue.load_visible_relations(issues)
-    end
-    issues
-  rescue ::ActiveRecord::StatementInvalid => e
-    raise StatementInvalid.new(e.message)
-  end
-
-  # Returns the issues ids
-  def issue_ids(options={})
-    order_option = [group_by_sort_order, options[:order]].flatten.reject(&:blank?)
-
-    Issue.visible.
-      joins(:status, :project).
-      where(statement).
-      includes(([:status, :project] + (options[:include] || [])).uniq).
-      where(options[:conditions]).
-      order(order_option).
-      joins(joins_for_order_statement(order_option.join(','))).
-      limit(options[:limit]).
-      offset(options[:offset]).
-      find_ids
-  rescue ::ActiveRecord::StatementInvalid => e
-    raise StatementInvalid.new(e.message)
-  end
-
-  # Returns the journals
-  # Valid options are :order, :offset, :limit
-  def journals(options={})
-    Journal.visible.
-      joins(:issue => [:project, :status]).
-      where(statement).
-      order(options[:order]).
-      limit(options[:limit]).
-      offset(options[:offset]).
-      preload(:details, :user, {:issue => [:project, :author, :tracker, :status]}).
-      all
-  rescue ::ActiveRecord::StatementInvalid => e
-    raise StatementInvalid.new(e.message)
-  end
-
-  # Returns the versions
-  # Valid options are :conditions
-  def versions(options={})
-    Version.visible.
-      where(project_statement).
-      where(options[:conditions]).
-      includes(:project).
-      all
-  rescue ::ActiveRecord::StatementInvalid => e
-    raise StatementInvalid.new(e.message)
-  end
-
-  def sql_for_watcher_id_field(field, operator, value)
-    db_table = Watcher.table_name
-    "#{Issue.table_name}.id #{ operator == '=' ? 'IN' : 'NOT IN' } (SELECT #{db_table}.watchable_id FROM #{db_table} WHERE #{db_table}.watchable_type='Issue' AND " +
-      sql_for_field(field, '=', value, db_table, 'user_id') + ')'
-  end
-
-  def sql_for_member_of_group_field(field, operator, value)
-    if operator == '*' # Any group
-      groups = Group.all
-      operator = '=' # Override the operator since we want to find by assigned_to
-    elsif operator == "!*"
-      groups = Group.all
-      operator = '!' # Override the operator since we want to find by assigned_to
-    else
-      groups = Group.find_all_by_id(value)
-    end
-    groups ||= []
-
-    members_of_groups = groups.inject([]) {|user_ids, group|
-      user_ids + group.user_ids + [group.id]
-    }.uniq.compact.sort.collect(&:to_s)
-
-    '(' + sql_for_field("assigned_to_id", operator, members_of_groups, Issue.table_name, "assigned_to_id", false) + ')'
-  end
-
-  def sql_for_assigned_to_role_field(field, operator, value)
-    case operator
-    when "*", "!*" # Member / Not member
-      sw = operator == "!*" ? 'NOT' : ''
-      nl = operator == "!*" ? "#{Issue.table_name}.assigned_to_id IS NULL OR" : ''
-      "(#{nl} #{Issue.table_name}.assigned_to_id #{sw} IN (SELECT DISTINCT #{Member.table_name}.user_id FROM #{Member.table_name}" +
-        " WHERE #{Member.table_name}.project_id = #{Issue.table_name}.project_id))"
-    when "=", "!"
-      role_cond = value.any? ?
-        "#{MemberRole.table_name}.role_id IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")" :
-        "1=0"
-
-      sw = operator == "!" ? 'NOT' : ''
-      nl = operator == "!" ? "#{Issue.table_name}.assigned_to_id IS NULL OR" : ''
-      "(#{nl} #{Issue.table_name}.assigned_to_id #{sw} IN (SELECT DISTINCT #{Member.table_name}.user_id FROM #{Member.table_name}, #{MemberRole.table_name}" +
-        " WHERE #{Member.table_name}.project_id = #{Issue.table_name}.project_id AND #{Member.table_name}.id = #{MemberRole.table_name}.member_id AND #{role_cond}))"
-    end
-  end
-
-  def sql_for_is_private_field(field, operator, value)
-    op = (operator == "=" ? 'IN' : 'NOT IN')
-    va = value.map {|v| v == '0' ? connection.quoted_false : connection.quoted_true}.uniq.join(',')
-
-    "#{Issue.table_name}.is_private #{op} (#{va})"
-  end
-
-  def sql_for_relations(field, operator, value, options={})
-    relation_options = IssueRelation::TYPES[field]
-    return relation_options unless relation_options
-
-    relation_type = field
-    join_column, target_join_column = "issue_from_id", "issue_to_id"
-    if relation_options[:reverse] || options[:reverse]
-      relation_type = relation_options[:reverse] || relation_type
-      join_column, target_join_column = target_join_column, join_column
-    end
-
-    sql = case operator
-      when "*", "!*"
-        op = (operator == "*" ? 'IN' : 'NOT IN')
-        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}')"
-      when "=", "!"
-        op = (operator == "=" ? 'IN' : 'NOT IN')
-        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = #{value.first.to_i})"
-      when "=p", "=!p", "!p"
-        op = (operator == "!p" ? 'NOT IN' : 'IN')
-        comp = (operator == "=!p" ? '<>' : '=')
-        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{comp} #{value.first.to_i})"
-      end
-
-    if relation_options[:sym] == field && !options[:reverse]
-      sqls = [sql, sql_for_relations(field, operator, value, :reverse => true)]
-      sql = sqls.join(["!", "!*", "!p"].include?(operator) ? " AND " : " OR ")
-    end
-    "(#{sql})"
-  end
-
-  IssueRelation::TYPES.keys.each do |relation_type|
-    alias_method "sql_for_#{relation_type}_field".to_sym, :sql_for_relations
-  end
-end
--- a/.svn/pristine/26/26d9747ae706cea5f68ea0007e9fb7e1bf0c8d18.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class CustomFieldVersionFormatTest < ActiveSupport::TestCase
-  fixtures :custom_fields, :projects, :members, :users, :member_roles, :trackers, :issues, :versions
-
-  def setup
-    @field = IssueCustomField.create!(:name => 'Tester', :field_format => 'version')
-  end
-
-  def test_possible_values_with_no_arguments
-    assert_equal [], @field.possible_values
-    assert_equal [], @field.possible_values(nil)
-  end
-
-  def test_possible_values_with_project_resource
-    project = Project.find(1)
-    possible_values = @field.possible_values(project.issues.first)
-    assert possible_values.any?
-    assert_equal project.shared_versions.sort.collect(&:id).map(&:to_s), possible_values
-  end
-
-  def test_possible_values_with_nil_project_resource
-    assert_equal [], @field.possible_values(Issue.new)
-  end
-
-  def test_possible_values_options_with_no_arguments
-    assert_equal [], @field.possible_values_options
-    assert_equal [], @field.possible_values_options(nil)
-  end
-
-  def test_possible_values_options_with_project_resource
-    project = Project.find(1)
-    possible_values_options = @field.possible_values_options(project.issues.first)
-    assert possible_values_options.any?
-    assert_equal project.shared_versions.sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
-  end
-
-  def test_possible_values_options_with_array
-    projects = Project.find([1, 2])
-    possible_values_options = @field.possible_values_options(projects)
-    assert possible_values_options.any?
-    assert_equal (projects.first.shared_versions & projects.last.shared_versions).sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
-  end
-
-  def test_cast_blank_value
-    assert_equal nil, @field.cast_value(nil)
-    assert_equal nil, @field.cast_value("")
-  end
-
-  def test_cast_valid_value
-    version = @field.cast_value("2")
-    assert_kind_of Version, version
-    assert_equal Version.find(2), version
-  end
-
-  def test_cast_invalid_value
-    assert_equal nil, @field.cast_value("187")
-  end
-end
--- a/.svn/pristine/27/2745a50d7301c30263d5450e181481b6eeb6b406.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::CipheringTest < ActiveSupport::TestCase
-
-  def test_password_should_be_encrypted
-    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
-      r = Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'svn')
-      assert_equal 'foo', r.password
-      assert r.read_attribute(:password).match(/\Aaes-256-cbc:.+\Z/)
-    end
-  end
-
-  def test_password_should_be_clear_with_blank_key
-    Redmine::Configuration.with 'database_cipher_key' => '' do
-      r = Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'svn')
-      assert_equal 'foo', r.password
-      assert_equal 'foo', r.read_attribute(:password)
-    end
-  end
-
-  def test_password_should_be_clear_with_nil_key
-    Redmine::Configuration.with 'database_cipher_key' => nil do
-      r = Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'svn')
-      assert_equal 'foo', r.password
-      assert_equal 'foo', r.read_attribute(:password)
-    end
-  end
-
-  def test_blank_password_should_be_clear
-    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
-      r = Repository::Subversion.create!(:password => '', :url => 'file:///tmp', :identifier => 'svn')
-      assert_equal '', r.password
-      assert_equal '', r.read_attribute(:password)
-    end
-  end
-
-  def test_unciphered_password_should_be_readable
-    Redmine::Configuration.with 'database_cipher_key' => nil do
-      r = Repository::Subversion.create!(:password => 'clear', :url => 'file:///tmp', :identifier => 'svn')
-    end
-
-    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
-      r = Repository.first(:order => 'id DESC')
-      assert_equal 'clear', r.password
-    end
-  end
-  
-  def test_ciphered_password_with_no_cipher_key_configured_should_be_returned_ciphered
-    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
-      r = Repository::Subversion.create!(:password => 'clear', :url => 'file:///tmp', :identifier => 'svn')
-    end
-
-    Redmine::Configuration.with 'database_cipher_key' => '' do
-      r = Repository.first(:order => 'id DESC')
-      # password can not be deciphered
-      assert_nothing_raised do
-        assert r.password.match(/\Aaes-256-cbc:.+\Z/)
-      end
-    end
-  end
-
-  def test_encrypt_all
-    Repository.delete_all
-    Redmine::Configuration.with 'database_cipher_key' => nil do
-      Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'foo')
-      Repository::Subversion.create!(:password => 'bar', :url => 'file:///tmp', :identifier => 'bar')
-    end
-
-    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
-      assert Repository.encrypt_all(:password)
-      r = Repository.first(:order => 'id DESC')
-      assert_equal 'bar', r.password
-      assert r.read_attribute(:password).match(/\Aaes-256-cbc:.+\Z/)
-    end
-  end
-
-  def test_decrypt_all
-    Repository.delete_all
-    Redmine::Configuration.with 'database_cipher_key' => 'secret' do
-      Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'foo')
-      Repository::Subversion.create!(:password => 'bar', :url => 'file:///tmp', :identifier => 'bar')
-
-      assert Repository.decrypt_all(:password)
-      r = Repository.first(:order => 'id DESC')
-      assert_equal 'bar', r.password
-      assert_equal 'bar', r.read_attribute(:password)
-    end
-  end
-end
--- a/.svn/pristine/27/27aa9063bcb916743c8adfa7af143c30c526db50.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,522 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-desc 'Mantis migration script'
-
-require 'active_record'
-require 'iconv' if RUBY_VERSION < '1.9'
-require 'pp'
-
-namespace :redmine do
-task :migrate_from_mantis => :environment do
-
-  module MantisMigrate
-
-      DEFAULT_STATUS = IssueStatus.default
-      assigned_status = IssueStatus.find_by_position(2)
-      resolved_status = IssueStatus.find_by_position(3)
-      feedback_status = IssueStatus.find_by_position(4)
-      closed_status = IssueStatus.where(:is_closed => true).first
-      STATUS_MAPPING = {10 => DEFAULT_STATUS,  # new
-                        20 => feedback_status, # feedback
-                        30 => DEFAULT_STATUS,  # acknowledged
-                        40 => DEFAULT_STATUS,  # confirmed
-                        50 => assigned_status, # assigned
-                        80 => resolved_status, # resolved
-                        90 => closed_status    # closed
-                        }
-
-      priorities = IssuePriority.all
-      DEFAULT_PRIORITY = priorities[2]
-      PRIORITY_MAPPING = {10 => priorities[1], # none
-                          20 => priorities[1], # low
-                          30 => priorities[2], # normal
-                          40 => priorities[3], # high
-                          50 => priorities[4], # urgent
-                          60 => priorities[5]  # immediate
-                          }
-
-      TRACKER_BUG = Tracker.find_by_position(1)
-      TRACKER_FEATURE = Tracker.find_by_position(2)
-
-      roles = Role.where(:builtin => 0).order('position ASC').all
-      manager_role = roles[0]
-      developer_role = roles[1]
-      DEFAULT_ROLE = roles.last
-      ROLE_MAPPING = {10 => DEFAULT_ROLE,   # viewer
-                      25 => DEFAULT_ROLE,   # reporter
-                      40 => DEFAULT_ROLE,   # updater
-                      55 => developer_role, # developer
-                      70 => manager_role,   # manager
-                      90 => manager_role    # administrator
-                      }
-
-      CUSTOM_FIELD_TYPE_MAPPING = {0 => 'string', # String
-                                   1 => 'int',    # Numeric
-                                   2 => 'int',    # Float
-                                   3 => 'list',   # Enumeration
-                                   4 => 'string', # Email
-                                   5 => 'bool',   # Checkbox
-                                   6 => 'list',   # List
-                                   7 => 'list',   # Multiselection list
-                                   8 => 'date',   # Date
-                                   }
-
-      RELATION_TYPE_MAPPING = {1 => IssueRelation::TYPE_RELATES,    # related to
-                               2 => IssueRelation::TYPE_RELATES,    # parent of
-                               3 => IssueRelation::TYPE_RELATES,    # child of
-                               0 => IssueRelation::TYPE_DUPLICATES, # duplicate of
-                               4 => IssueRelation::TYPE_DUPLICATES  # has duplicate
-                               }
-
-    class MantisUser < ActiveRecord::Base
-      self.table_name = :mantis_user_table
-
-      def firstname
-        @firstname = realname.blank? ? username : realname.split.first[0..29]
-        @firstname
-      end
-
-      def lastname
-        @lastname = realname.blank? ? '-' : realname.split[1..-1].join(' ')[0..29]
-        @lastname = '-' if @lastname.blank?
-        @lastname
-      end
-
-      def email
-        if read_attribute(:email).match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) &&
-             !User.find_by_mail(read_attribute(:email))
-          @email = read_attribute(:email)
-        else
-          @email = "#{username}@foo.bar"
-        end
-      end
-
-      def username
-        read_attribute(:username)[0..29].gsub(/[^a-zA-Z0-9_\-@\.]/, '-')
-      end
-    end
-
-    class MantisProject < ActiveRecord::Base
-      self.table_name = :mantis_project_table
-      has_many :versions, :class_name => "MantisVersion", :foreign_key => :project_id
-      has_many :categories, :class_name => "MantisCategory", :foreign_key => :project_id
-      has_many :news, :class_name => "MantisNews", :foreign_key => :project_id
-      has_many :members, :class_name => "MantisProjectUser", :foreign_key => :project_id
-
-      def identifier
-        read_attribute(:name).downcase.gsub(/[^a-z0-9\-]+/, '-').slice(0, Project::IDENTIFIER_MAX_LENGTH)
-      end
-    end
-
-    class MantisVersion < ActiveRecord::Base
-      self.table_name = :mantis_project_version_table
-
-      def version
-        read_attribute(:version)[0..29]
-      end
-
-      def description
-        read_attribute(:description)[0..254]
-      end
-    end
-
-    class MantisCategory < ActiveRecord::Base
-      self.table_name = :mantis_project_category_table
-    end
-
-    class MantisProjectUser < ActiveRecord::Base
-      self.table_name = :mantis_project_user_list_table
-    end
-
-    class MantisBug < ActiveRecord::Base
-      self.table_name = :mantis_bug_table
-      belongs_to :bug_text, :class_name => "MantisBugText", :foreign_key => :bug_text_id
-      has_many :bug_notes, :class_name => "MantisBugNote", :foreign_key => :bug_id
-      has_many :bug_files, :class_name => "MantisBugFile", :foreign_key => :bug_id
-      has_many :bug_monitors, :class_name => "MantisBugMonitor", :foreign_key => :bug_id
-    end
-
-    class MantisBugText < ActiveRecord::Base
-      self.table_name = :mantis_bug_text_table
-
-      # Adds Mantis steps_to_reproduce and additional_information fields
-      # to description if any
-      def full_description
-        full_description = description
-        full_description += "\n\n*Steps to reproduce:*\n\n#{steps_to_reproduce}" unless steps_to_reproduce.blank?
-        full_description += "\n\n*Additional information:*\n\n#{additional_information}" unless additional_information.blank?
-        full_description
-      end
-    end
-
-    class MantisBugNote < ActiveRecord::Base
-      self.table_name = :mantis_bugnote_table
-      belongs_to :bug, :class_name => "MantisBug", :foreign_key => :bug_id
-      belongs_to :bug_note_text, :class_name => "MantisBugNoteText", :foreign_key => :bugnote_text_id
-    end
-
-    class MantisBugNoteText < ActiveRecord::Base
-      self.table_name = :mantis_bugnote_text_table
-    end
-
-    class MantisBugFile < ActiveRecord::Base
-      self.table_name = :mantis_bug_file_table
-
-      def size
-        filesize
-      end
-
-      def original_filename
-        MantisMigrate.encode(filename)
-      end
-
-      def content_type
-        file_type
-      end
-
-      def read(*args)
-          if @read_finished
-              nil
-          else
-              @read_finished = true
-              content
-          end
-      end
-    end
-
-    class MantisBugRelationship < ActiveRecord::Base
-      self.table_name = :mantis_bug_relationship_table
-    end
-
-    class MantisBugMonitor < ActiveRecord::Base
-      self.table_name = :mantis_bug_monitor_table
-    end
-
-    class MantisNews < ActiveRecord::Base
-      self.table_name = :mantis_news_table
-    end
-
-    class MantisCustomField < ActiveRecord::Base
-      self.table_name = :mantis_custom_field_table
-      set_inheritance_column :none
-      has_many :values, :class_name => "MantisCustomFieldString", :foreign_key => :field_id
-      has_many :projects, :class_name => "MantisCustomFieldProject", :foreign_key => :field_id
-
-      def format
-        read_attribute :type
-      end
-
-      def name
-        read_attribute(:name)[0..29]
-      end
-    end
-
-    class MantisCustomFieldProject < ActiveRecord::Base
-      self.table_name = :mantis_custom_field_project_table
-    end
-
-    class MantisCustomFieldString < ActiveRecord::Base
-      self.table_name = :mantis_custom_field_string_table
-    end
-
-    def self.migrate
-
-      # Users
-      print "Migrating users"
-      User.delete_all "login <> 'admin'"
-      users_map = {}
-      users_migrated = 0
-      MantisUser.all.each do |user|
-        u = User.new :firstname => encode(user.firstname),
-                     :lastname => encode(user.lastname),
-                     :mail => user.email,
-                     :last_login_on => user.last_visit
-        u.login = user.username
-        u.password = 'mantis'
-        u.status = User::STATUS_LOCKED if user.enabled != 1
-        u.admin = true if user.access_level == 90
-        next unless u.save!
-        users_migrated += 1
-        users_map[user.id] = u.id
-        print '.'
-      end
-      puts
-
-      # Projects
-      print "Migrating projects"
-      Project.destroy_all
-      projects_map = {}
-      versions_map = {}
-      categories_map = {}
-      MantisProject.all.each do |project|
-        p = Project.new :name => encode(project.name),
-                        :description => encode(project.description)
-        p.identifier = project.identifier
-        next unless p.save
-        projects_map[project.id] = p.id
-        p.enabled_module_names = ['issue_tracking', 'news', 'wiki']
-        p.trackers << TRACKER_BUG unless p.trackers.include?(TRACKER_BUG)
-        p.trackers << TRACKER_FEATURE unless p.trackers.include?(TRACKER_FEATURE)
-        print '.'
-
-        # Project members
-        project.members.each do |member|
-          m = Member.new :user => User.find_by_id(users_map[member.user_id]),
-                           :roles => [ROLE_MAPPING[member.access_level] || DEFAULT_ROLE]
-          m.project = p
-          m.save
-        end
-
-        # Project versions
-        project.versions.each do |version|
-          v = Version.new :name => encode(version.version),
-                          :description => encode(version.description),
-                          :effective_date => (version.date_order ? version.date_order.to_date : nil)
-          v.project = p
-          v.save
-          versions_map[version.id] = v.id
-        end
-
-        # Project categories
-        project.categories.each do |category|
-          g = IssueCategory.new :name => category.category[0,30]
-          g.project = p
-          g.save
-          categories_map[category.category] = g.id
-        end
-      end
-      puts
-
-      # Bugs
-      print "Migrating bugs"
-      Issue.destroy_all
-      issues_map = {}
-      keep_bug_ids = (Issue.count == 0)
-      MantisBug.find_each(:batch_size => 200) do |bug|
-        next unless projects_map[bug.project_id] && users_map[bug.reporter_id]
-        i = Issue.new :project_id => projects_map[bug.project_id],
-                      :subject => encode(bug.summary),
-                      :description => encode(bug.bug_text.full_description),
-                      :priority => PRIORITY_MAPPING[bug.priority] || DEFAULT_PRIORITY,
-                      :created_on => bug.date_submitted,
-                      :updated_on => bug.last_updated
-        i.author = User.find_by_id(users_map[bug.reporter_id])
-        i.category = IssueCategory.find_by_project_id_and_name(i.project_id, bug.category[0,30]) unless bug.category.blank?
-        i.fixed_version = Version.find_by_project_id_and_name(i.project_id, bug.fixed_in_version) unless bug.fixed_in_version.blank?
-        i.status = STATUS_MAPPING[bug.status] || DEFAULT_STATUS
-        i.tracker = (bug.severity == 10 ? TRACKER_FEATURE : TRACKER_BUG)
-        i.id = bug.id if keep_bug_ids
-        next unless i.save
-        issues_map[bug.id] = i.id
-        print '.'
-        STDOUT.flush
-
-        # Assignee
-        # Redmine checks that the assignee is a project member
-        if (bug.handler_id && users_map[bug.handler_id])
-          i.assigned_to = User.find_by_id(users_map[bug.handler_id])
-          i.save(:validate => false)
-        end
-
-        # Bug notes
-        bug.bug_notes.each do |note|
-          next unless users_map[note.reporter_id]
-          n = Journal.new :notes => encode(note.bug_note_text.note),
-                          :created_on => note.date_submitted
-          n.user = User.find_by_id(users_map[note.reporter_id])
-          n.journalized = i
-          n.save
-        end
-
-        # Bug files
-        bug.bug_files.each do |file|
-          a = Attachment.new :created_on => file.date_added
-          a.file = file
-          a.author = User.first
-          a.container = i
-          a.save
-        end
-
-        # Bug monitors
-        bug.bug_monitors.each do |monitor|
-          next unless users_map[monitor.user_id]
-          i.add_watcher(User.find_by_id(users_map[monitor.user_id]))
-        end
-      end
-
-      # update issue id sequence if needed (postgresql)
-      Issue.connection.reset_pk_sequence!(Issue.table_name) if Issue.connection.respond_to?('reset_pk_sequence!')
-      puts
-
-      # Bug relationships
-      print "Migrating bug relations"
-      MantisBugRelationship.all.each do |relation|
-        next unless issues_map[relation.source_bug_id] && issues_map[relation.destination_bug_id]
-        r = IssueRelation.new :relation_type => RELATION_TYPE_MAPPING[relation.relationship_type]
-        r.issue_from = Issue.find_by_id(issues_map[relation.source_bug_id])
-        r.issue_to = Issue.find_by_id(issues_map[relation.destination_bug_id])
-        pp r unless r.save
-        print '.'
-        STDOUT.flush
-      end
-      puts
-
-      # News
-      print "Migrating news"
-      News.destroy_all
-      MantisNews.where('project_id > 0').all.each do |news|
-        next unless projects_map[news.project_id]
-        n = News.new :project_id => projects_map[news.project_id],
-                     :title => encode(news.headline[0..59]),
-                     :description => encode(news.body),
-                     :created_on => news.date_posted
-        n.author = User.find_by_id(users_map[news.poster_id])
-        n.save
-        print '.'
-        STDOUT.flush
-      end
-      puts
-
-      # Custom fields
-      print "Migrating custom fields"
-      IssueCustomField.destroy_all
-      MantisCustomField.all.each do |field|
-        f = IssueCustomField.new :name => field.name[0..29],
-                                 :field_format => CUSTOM_FIELD_TYPE_MAPPING[field.format],
-                                 :min_length => field.length_min,
-                                 :max_length => field.length_max,
-                                 :regexp => field.valid_regexp,
-                                 :possible_values => field.possible_values.split('|'),
-                                 :is_required => field.require_report?
-        next unless f.save
-        print '.'
-        STDOUT.flush
-        # Trackers association
-        f.trackers = Tracker.all
-
-        # Projects association
-        field.projects.each do |project|
-          f.projects << Project.find_by_id(projects_map[project.project_id]) if projects_map[project.project_id]
-        end
-
-        # Values
-        field.values.each do |value|
-          v = CustomValue.new :custom_field_id => f.id,
-                              :value => value.value
-          v.customized = Issue.find_by_id(issues_map[value.bug_id]) if issues_map[value.bug_id]
-          v.save
-        end unless f.new_record?
-      end
-      puts
-
-      puts
-      puts "Users:           #{users_migrated}/#{MantisUser.count}"
-      puts "Projects:        #{Project.count}/#{MantisProject.count}"
-      puts "Memberships:     #{Member.count}/#{MantisProjectUser.count}"
-      puts "Versions:        #{Version.count}/#{MantisVersion.count}"
-      puts "Categories:      #{IssueCategory.count}/#{MantisCategory.count}"
-      puts "Bugs:            #{Issue.count}/#{MantisBug.count}"
-      puts "Bug notes:       #{Journal.count}/#{MantisBugNote.count}"
-      puts "Bug files:       #{Attachment.count}/#{MantisBugFile.count}"
-      puts "Bug relations:   #{IssueRelation.count}/#{MantisBugRelationship.count}"
-      puts "Bug monitors:    #{Watcher.count}/#{MantisBugMonitor.count}"
-      puts "News:            #{News.count}/#{MantisNews.count}"
-      puts "Custom fields:   #{IssueCustomField.count}/#{MantisCustomField.count}"
-    end
-
-    def self.encoding(charset)
-      @charset = charset
-    end
-
-    def self.establish_connection(params)
-      constants.each do |const|
-        klass = const_get(const)
-        next unless klass.respond_to? 'establish_connection'
-        klass.establish_connection params
-      end
-    end
-
-    def self.encode(text)
-      if RUBY_VERSION < '1.9'
-        @ic ||= Iconv.new('UTF-8', @charset)
-        @ic.iconv text
-      else
-        text.to_s.force_encoding(@charset).encode('UTF-8')
-      end
-    end
-  end
-
-  puts
-  if Redmine::DefaultData::Loader.no_data?
-    puts "Redmine configuration need to be loaded before importing data."
-    puts "Please, run this first:"
-    puts
-    puts "  rake redmine:load_default_data RAILS_ENV=\"#{ENV['RAILS_ENV']}\""
-    exit
-  end
-
-  puts "WARNING: Your Redmine data will be deleted during this process."
-  print "Are you sure you want to continue ? [y/N] "
-  STDOUT.flush
-  break unless STDIN.gets.match(/^y$/i)
-
-  # Default Mantis database settings
-  db_params = {:adapter => 'mysql2',
-               :database => 'bugtracker',
-               :host => 'localhost',
-               :username => 'root',
-               :password => '' }
-
-  puts
-  puts "Please enter settings for your Mantis database"
-  [:adapter, :host, :database, :username, :password].each do |param|
-    print "#{param} [#{db_params[param]}]: "
-    value = STDIN.gets.chomp!
-    db_params[param] = value unless value.blank?
-  end
-
-  while true
-    print "encoding [UTF-8]: "
-    STDOUT.flush
-    encoding = STDIN.gets.chomp!
-    encoding = 'UTF-8' if encoding.blank?
-    break if MantisMigrate.encoding encoding
-    puts "Invalid encoding!"
-  end
-  puts
-
-  # Make sure bugs can refer bugs in other projects
-  Setting.cross_project_issue_relations = 1 if Setting.respond_to? 'cross_project_issue_relations'
-
-  old_notified_events = Setting.notified_events
-  old_password_min_length = Setting.password_min_length
-  begin
-    # Turn off email notifications temporarily
-    Setting.notified_events = []
-    Setting.password_min_length = 4
-    # Run the migration
-    MantisMigrate.establish_connection db_params
-    MantisMigrate.migrate
-  ensure
-    # Restore previous settings
-    Setting.notified_events = old_notified_events
-    Setting.password_min_length = old_password_min_length
-  end
-
-end
-end
--- a/.svn/pristine/27/27ff0c8aa6059bb3d3244c9053898a1f8e9c2b1e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Views
-    module MyPage
-      module Block
-        def self.additional_blocks
-          @@additional_blocks ||= Dir.glob("#{Redmine::Plugin.directory}/*/app/views/my/blocks/_*.{rhtml,erb}").inject({}) do |h,file|
-            name = File.basename(file).split('.').first.gsub(/^_/, '')
-            h[name] = name.to_sym
-            h
-          end
-        end
-      end
-    end
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/28/28a718992fc9b78318367f1ea258610932c7f8f4.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,392 @@
+# Redmine - project management software
+# Copyright (C) 2006-2014  Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require File.expand_path('../../test_helper', __FILE__)
+
+class AccountControllerTest < ActionController::TestCase
+  fixtures :users, :roles
+
+  def setup
+    User.current = nil
+  end
+
+  def test_get_login
+    get :login
+    assert_response :success
+    assert_template 'login'
+
+    assert_select 'input[name=username]'
+    assert_select 'input[name=password]'
+  end
+
+  def test_get_login_while_logged_in_should_redirect_to_home
+    @request.session[:user_id] = 2
+
+    get :login
+    assert_redirected_to '/'
+    assert_equal 2, @request.session[:user_id]
+  end
+
+  def test_login_should_redirect_to_back_url_param
+    # request.uri is "test.host" in test environment
+    back_urls = [
+      'http://test.host/issues/show/1',
+      '/'
+    ]
+    back_urls.each do |back_url|
+      post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
+      assert_redirected_to back_url
+    end
+  end
+
+  def test_login_with_suburi_should_redirect_to_back_url_param
+    @relative_url_root = ApplicationController.relative_url_root
+    ApplicationController.relative_url_root = '/redmine'
+
+    back_urls = [
+      'http://test.host/redmine/issues/show/1',
+      '/redmine'
+    ]
+    back_urls.each do |back_url|
+      post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
+      assert_redirected_to back_url
+    end
+  ensure
+    ApplicationController.relative_url_root = @relative_url_root
+  end
+
+  def test_login_should_not_redirect_to_another_host
+    back_urls = [
+      'http://test.foo/fake',
+      '//test.foo/fake'
+    ]
+    back_urls.each do |back_url|
+      post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
+      assert_redirected_to '/my/page'
+    end
+  end
+
+  def test_login_with_suburi_should_not_redirect_to_another_suburi
+    @relative_url_root = ApplicationController.relative_url_root
+    ApplicationController.relative_url_root = '/redmine'
+
+    back_urls = [
+      'http://test.host/',
+      'http://test.host/fake',
+      'http://test.host/fake/issues',
+      'http://test.host/redmine/../fake',
+      'http://test.host/redmine/../fake/issues',
+      'http://test.host/redmine/%2e%2e/fake'
+    ]
+    back_urls.each do |back_url|
+      post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
+      assert_redirected_to '/my/page'
+    end
+  ensure
+    ApplicationController.relative_url_root = @relative_url_root
+  end
+
+  def test_login_with_wrong_password
+    post :login, :username => 'admin', :password => 'bad'
+    assert_response :success
+    assert_template 'login'
+
+    assert_select 'div.flash.error', :text => /Invalid user or password/
+    assert_select 'input[name=username][value=admin]'
+    assert_select 'input[name=password]'
+    assert_select 'input[name=password][value]', 0
+  end
+
+  def test_login_with_locked_account_should_fail
+    User.find(2).update_attribute :status, User::STATUS_LOCKED
+
+    post :login, :username => 'jsmith', :password => 'jsmith'
+    assert_redirected_to '/login'
+    assert_include 'locked', flash[:error]
+    assert_nil @request.session[:user_id]
+  end
+
+  def test_login_as_registered_user_with_manual_activation_should_inform_user
+    User.find(2).update_attribute :status, User::STATUS_REGISTERED
+
+    with_settings :self_registration => '2', :default_language => 'en' do
+      post :login, :username => 'jsmith', :password => 'jsmith'
+      assert_redirected_to '/login'
+      assert_include 'pending administrator approval', flash[:error]
+    end
+  end
+
+  def test_login_as_registered_user_with_email_activation_should_propose_new_activation_email
+    User.find(2).update_attribute :status, User::STATUS_REGISTERED
+
+    with_settings :self_registration => '1', :default_language => 'en' do
+      post :login, :username => 'jsmith', :password => 'jsmith'
+      assert_redirected_to '/login'
+      assert_equal 2, @request.session[:registered_user_id]
+      assert_include 'new activation email', flash[:error]
+    end
+  end
+
+  def test_login_should_rescue_auth_source_exception
+    source = AuthSource.create!(:name => 'Test')
+    User.find(2).update_attribute :auth_source_id, source.id
+    AuthSource.any_instance.stubs(:authenticate).raises(AuthSourceException.new("Something wrong"))
+
+    post :login, :username => 'jsmith', :password => 'jsmith'
+    assert_response 500
+    assert_error_tag :content => /Something wrong/
+  end
+
+  def test_login_should_reset_session
+    @controller.expects(:reset_session).once
+
+    post :login, :username => 'jsmith', :password => 'jsmith'
+    assert_response 302
+  end
+
+  def test_get_logout_should_not_logout
+    @request.session[:user_id] = 2
+    get :logout
+    assert_response :success
+    assert_template 'logout'
+
+    assert_equal 2, @request.session[:user_id]
+  end
+
+  def test_get_logout_with_anonymous_should_redirect
+    get :logout
+    assert_redirected_to '/'
+  end
+
+  def test_logout
+    @request.session[:user_id] = 2
+    post :logout
+    assert_redirected_to '/'
+    assert_nil @request.session[:user_id]
+  end
+
+  def test_logout_should_reset_session
+    @controller.expects(:reset_session).once
+
+    @request.session[:user_id] = 2
+    post :logout
+    assert_response 302
+  end
+
+  def test_get_register_with_registration_on
+    with_settings :self_registration => '3' do
+      get :register
+      assert_response :success
+      assert_template 'register'
+      assert_not_nil assigns(:user)
+
+      assert_select 'input[name=?]', 'user[password]'
+      assert_select 'input[name=?]', 'user[password_confirmation]'
+    end
+  end
+
+  def test_get_register_should_detect_user_language
+    with_settings :self_registration => '3' do
+      @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
+      get :register
+      assert_response :success
+      assert_not_nil assigns(:user)
+      assert_equal 'fr', assigns(:user).language
+      assert_select 'select[name=?]', 'user[language]' do
+        assert_select 'option[value=fr][selected=selected]'
+      end
+    end
+  end
+
+  def test_get_register_with_registration_off_should_redirect
+    with_settings :self_registration => '0' do
+      get :register
+      assert_redirected_to '/'
+    end
+  end
+
+  # See integration/account_test.rb for the full test
+  def test_post_register_with_registration_on
+    with_settings :self_registration => '3' do
+      assert_difference 'User.count' do
+        post :register, :user => {
+          :login => 'register',
+          :password => 'secret123',
+          :password_confirmation => 'secret123',
+          :firstname => 'John',
+          :lastname => 'Doe',
+          :mail => 'register@example.com'
+        }
+        assert_redirected_to '/my/account'
+      end
+      user = User.first(:order => 'id DESC')
+      assert_equal 'register', user.login
+      assert_equal 'John', user.firstname
+      assert_equal 'Doe', user.lastname
+      assert_equal 'register@example.com', user.mail
+      assert user.check_password?('secret123')
+      assert user.active?
+    end
+  end
+  
+  def test_post_register_with_registration_off_should_redirect
+    with_settings :self_registration => '0' do
+      assert_no_difference 'User.count' do
+        post :register, :user => {
+          :login => 'register',
+          :password => 'test',
+          :password_confirmation => 'test',
+          :firstname => 'John',
+          :lastname => 'Doe',
+          :mail => 'register@example.com'
+        }
+        assert_redirected_to '/'
+      end
+    end
+  end
+
+  def test_get_lost_password_should_display_lost_password_form
+    get :lost_password
+    assert_response :success
+    assert_select 'input[name=mail]'
+  end
+
+  def test_lost_password_for_active_user_should_create_a_token
+    Token.delete_all
+    ActionMailer::Base.deliveries.clear
+    assert_difference 'ActionMailer::Base.deliveries.size' do
+      assert_difference 'Token.count' do
+        with_settings :host_name => 'mydomain.foo', :protocol => 'http' do
+          post :lost_password, :mail => 'JSmith@somenet.foo'
+          assert_redirected_to '/login'
+        end
+      end
+    end
+
+    token = Token.order('id DESC').first
+    assert_equal User.find(2), token.user
+    assert_equal 'recovery', token.action
+
+    assert_select_email do
+      assert_select "a[href=?]", "http://mydomain.foo/account/lost_password?token=#{token.value}"
+    end
+  end
+
+  def test_lost_password_for_unknown_user_should_fail
+    Token.delete_all
+    assert_no_difference 'Token.count' do
+      post :lost_password, :mail => 'invalid@somenet.foo'
+      assert_response :success
+    end
+  end
+
+  def test_lost_password_for_non_active_user_should_fail
+    Token.delete_all
+    assert User.find(2).lock!
+
+    assert_no_difference 'Token.count' do
+      post :lost_password, :mail => 'JSmith@somenet.foo'
+      assert_redirected_to '/account/lost_password'
+    end
+  end
+
+  def test_lost_password_for_user_who_cannot_change_password_should_fail
+    User.any_instance.stubs(:change_password_allowed?).returns(false)
+
+    assert_no_difference 'Token.count' do
+      post :lost_password, :mail => 'JSmith@somenet.foo'
+      assert_response :success
+    end
+  end
+
+  def test_get_lost_password_with_token_should_display_the_password_recovery_form
+    user = User.find(2)
+    token = Token.create!(:action => 'recovery', :user => user)
+
+    get :lost_password, :token => token.value
+    assert_response :success
+    assert_template 'password_recovery'
+
+    assert_select 'input[type=hidden][name=token][value=?]', token.value
+  end
+
+  def test_get_lost_password_with_invalid_token_should_redirect
+    get :lost_password, :token => "abcdef"
+    assert_redirected_to '/'
+  end
+
+  def test_post_lost_password_with_token_should_change_the_user_password
+    user = User.find(2)
+    token = Token.create!(:action => 'recovery', :user => user)
+
+    post :lost_password, :token => token.value, :new_password => 'newpass123', :new_password_confirmation => 'newpass123'
+    assert_redirected_to '/login'
+    user.reload
+    assert user.check_password?('newpass123')
+    assert_nil Token.find_by_id(token.id), "Token was not deleted"
+  end
+
+  def test_post_lost_password_with_token_for_non_active_user_should_fail
+    user = User.find(2)
+    token = Token.create!(:action => 'recovery', :user => user)
+    user.lock!
+
+    post :lost_password, :token => token.value, :new_password => 'newpass123', :new_password_confirmation => 'newpass123'
+    assert_redirected_to '/'
+    assert ! user.check_password?('newpass123')
+  end
+
+  def test_post_lost_password_with_token_and_password_confirmation_failure_should_redisplay_the_form
+    user = User.find(2)
+    token = Token.create!(:action => 'recovery', :user => user)
+
+    post :lost_password, :token => token.value, :new_password => 'newpass', :new_password_confirmation => 'wrongpass'
+    assert_response :success
+    assert_template 'password_recovery'
+    assert_not_nil Token.find_by_id(token.id), "Token was deleted"
+
+    assert_select 'input[type=hidden][name=token][value=?]', token.value
+  end
+
+  def test_post_lost_password_with_invalid_token_should_redirect
+    post :lost_password, :token => "abcdef", :new_password => 'newpass', :new_password_confirmation => 'newpass'
+    assert_redirected_to '/'
+  end
+
+  def test_activation_email_should_send_an_activation_email
+    User.find(2).update_attribute :status, User::STATUS_REGISTERED
+    @request.session[:registered_user_id] = 2
+
+    with_settings :self_registration => '1' do
+      assert_difference 'ActionMailer::Base.deliveries.size' do
+        get :activation_email
+        assert_redirected_to '/login'
+      end
+    end
+  end
+
+  def test_activation_email_without_session_data_should_fail
+    User.find(2).update_attribute :status, User::STATUS_REGISTERED
+
+    with_settings :self_registration => '1' do
+      assert_no_difference 'ActionMailer::Base.deliveries.size' do
+        get :activation_email
+        assert_redirected_to '/'
+      end
+    end
+  end
+end
--- a/.svn/pristine/28/28ed7202edbfd59150a254a3d4ac24d16c42373f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class CustomFieldsHelperTest < ActionView::TestCase
-  include CustomFieldsHelper
-  include Redmine::I18n
-  include ERB::Util
-
-  def test_format_boolean_value
-    I18n.locale = 'en'
-    assert_equal 'Yes', format_value('1', 'bool')
-    assert_equal 'No', format_value('0', 'bool')
-  end
-
-  def test_unknow_field_format_should_be_edited_as_string
-    field = CustomField.new(:field_format => 'foo')
-    value = CustomValue.new(:value => 'bar', :custom_field => field)
-    field.id = 52
-
-    assert_equal '<input class="foo_cf" id="object_custom_field_values_52" name="object[custom_field_values][52]" type="text" value="bar" />',
-      custom_field_tag('object', value)
-  end
-
-  def test_unknow_field_format_should_be_bulk_edited_as_string
-    field = CustomField.new(:field_format => 'foo')
-    field.id = 52
-
-    assert_include '<input class="foo_cf" id="object_custom_field_values_52" name="object[custom_field_values][52]" type="text" value="" />',
-      custom_field_tag_for_bulk_edit('object', field)
-  end
-end
--- a/.svn/pristine/29/29f1e7420f4ca87ea1757481bcca4dae405f53b6.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class UserPreferenceTest < ActiveSupport::TestCase
-  fixtures :users, :user_preferences
-
-  def test_create
-    user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
-    user.login = "newuser"
-    user.password, user.password_confirmation = "password", "password"
-    assert user.save
-
-    assert_kind_of UserPreference, user.pref
-    assert_kind_of Hash, user.pref.others
-    assert user.pref.save
-  end
-
-  def test_update
-    user = User.find(1)
-    assert_equal true, user.pref.hide_mail
-    user.pref['preftest'] = 'value'
-    assert user.pref.save
-
-    user.reload
-    assert_equal 'value', user.pref['preftest']
-  end
-
-  def test_others_hash
-    user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
-    user.login = "newuser"
-    user.password, user.password_confirmation = "password", "password"
-    assert user.save
-    assert_nil user.preference
-    up = UserPreference.new(:user => user)
-    assert_kind_of Hash, up.others
-    up.others = nil
-    assert_nil up.others
-    assert up.save
-    assert_kind_of Hash, up.others
-  end
-
-  def test_others_should_be_blank_after_initialization
-    pref = User.new.pref
-    assert_equal({}, pref.others)
-  end
-
-  def test_reading_value_from_nil_others_hash
-    up = UserPreference.new(:user => User.new)
-    up.others = nil
-    assert_nil up.others
-    assert_nil up[:foo]
-  end
-
-  def test_writing_value_to_nil_others_hash
-    up = UserPreference.new(:user => User.new)
-    up.others = nil
-    assert_nil up.others
-    up[:foo] = 'bar'
-    assert_equal 'bar', up[:foo]
-  end
-end
--- a/.svn/pristine/2a/2a59baf70fb68ac9f90f4306e930088af4138a70.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,437 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class ScmFetchError < Exception; end
-
-class Repository < ActiveRecord::Base
-  include Redmine::Ciphering
-  include Redmine::SafeAttributes
-
-  # Maximum length for repository identifiers
-  IDENTIFIER_MAX_LENGTH = 255
-
-  belongs_to :project
-  has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
-  has_many :filechanges, :class_name => 'Change', :through => :changesets
-
-  serialize :extra_info
-
-  before_save :check_default
-
-  # Raw SQL to delete changesets and changes in the database
-  # has_many :changesets, :dependent => :destroy is too slow for big repositories
-  before_destroy :clear_changesets
-
-  validates_length_of :password, :maximum => 255, :allow_nil => true
-  validates_length_of :identifier, :maximum => IDENTIFIER_MAX_LENGTH, :allow_blank => true
-  validates_presence_of :identifier, :unless => Proc.new { |r| r.is_default? || r.set_as_default? }
-  validates_uniqueness_of :identifier, :scope => :project_id, :allow_blank => true
-  validates_exclusion_of :identifier, :in => %w(show entry raw changes annotate diff show stats graph)
-  # donwcase letters, digits, dashes, underscores but not digits only
-  validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true
-  # Checks if the SCM is enabled when creating a repository
-  validate :repo_create_validation, :on => :create
-
-  safe_attributes 'identifier',
-    'login',
-    'password',
-    'path_encoding',
-    'log_encoding',
-    'is_default'
-
-  safe_attributes 'url',
-    :if => lambda {|repository, user| repository.new_record?}
-
-  def repo_create_validation
-    unless Setting.enabled_scm.include?(self.class.name.demodulize)
-      errors.add(:type, :invalid)
-    end
-  end
-
-  def self.human_attribute_name(attribute_key_name, *args)
-    attr_name = attribute_key_name.to_s
-    if attr_name == "log_encoding"
-      attr_name = "commit_logs_encoding"
-    end
-    super(attr_name, *args)
-  end
-
-  # Removes leading and trailing whitespace
-  def url=(arg)
-    write_attribute(:url, arg ? arg.to_s.strip : nil)
-  end
-
-  # Removes leading and trailing whitespace
-  def root_url=(arg)
-    write_attribute(:root_url, arg ? arg.to_s.strip : nil)
-  end
-
-  def password
-    read_ciphered_attribute(:password)
-  end
-
-  def password=(arg)
-    write_ciphered_attribute(:password, arg)
-  end
-
-  def scm_adapter
-    self.class.scm_adapter_class
-  end
-
-  def scm
-    unless @scm
-      @scm = self.scm_adapter.new(url, root_url,
-                                  login, password, path_encoding)
-      if root_url.blank? && @scm.root_url.present?
-        update_attribute(:root_url, @scm.root_url)
-      end
-    end
-    @scm
-  end
-
-  def scm_name
-    self.class.scm_name
-  end
-
-  def name
-    if identifier.present?
-      identifier
-    elsif is_default?
-      l(:field_repository_is_default)
-    else
-      scm_name
-    end
-  end
-
-  def identifier=(identifier)
-    super unless identifier_frozen?
-  end
-
-  def identifier_frozen?
-    errors[:identifier].blank? && !(new_record? || identifier.blank?)
-  end
-
-  def identifier_param
-    if is_default?
-      nil
-    elsif identifier.present?
-      identifier
-    else
-      id.to_s
-    end
-  end
-
-  def <=>(repository)
-    if is_default?
-      -1
-    elsif repository.is_default?
-      1
-    else
-      identifier.to_s <=> repository.identifier.to_s
-    end
-  end
-
-  def self.find_by_identifier_param(param)
-    if param.to_s =~ /^\d+$/
-      find_by_id(param)
-    else
-      find_by_identifier(param)
-    end
-  end
-
-  def merge_extra_info(arg)
-    h = extra_info || {}
-    return h if arg.nil?
-    h.merge!(arg)
-    write_attribute(:extra_info, h)
-  end
-
-  def report_last_commit
-    true
-  end
-
-  def supports_cat?
-    scm.supports_cat?
-  end
-
-  def supports_annotate?
-    scm.supports_annotate?
-  end
-
-  def supports_all_revisions?
-    true
-  end
-
-  def supports_directory_revisions?
-    false
-  end
-
-  def supports_revision_graph?
-    false
-  end
-
-  def entry(path=nil, identifier=nil)
-    scm.entry(path, identifier)
-  end
-
-  def entries(path=nil, identifier=nil)
-    entries = scm.entries(path, identifier)
-    load_entries_changesets(entries)
-    entries
-  end
-
-  def branches
-    scm.branches
-  end
-
-  def tags
-    scm.tags
-  end
-
-  def default_branch
-    nil
-  end
-
-  def properties(path, identifier=nil)
-    scm.properties(path, identifier)
-  end
-
-  def cat(path, identifier=nil)
-    scm.cat(path, identifier)
-  end
-
-  def diff(path, rev, rev_to)
-    scm.diff(path, rev, rev_to)
-  end
-
-  def diff_format_revisions(cs, cs_to, sep=':')
-    text = ""
-    text << cs_to.format_identifier + sep if cs_to
-    text << cs.format_identifier if cs
-    text
-  end
-
-  # Returns a path relative to the url of the repository
-  def relative_path(path)
-    path
-  end
-
-  # Finds and returns a revision with a number or the beginning of a hash
-  def find_changeset_by_name(name)
-    return nil if name.blank?
-    s = name.to_s
-    if s.match(/^\d*$/)
-      changesets.where("revision = ?", s).first
-    else
-      changesets.where("revision LIKE ?", s + '%').first
-    end
-  end
-
-  def latest_changeset
-    @latest_changeset ||= changesets.first
-  end
-
-  # Returns the latest changesets for +path+
-  # Default behaviour is to search in cached changesets
-  def latest_changesets(path, rev, limit=10)
-    if path.blank?
-      changesets.
-        reorder("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC").
-        limit(limit).
-        preload(:user).
-        all
-    else
-      filechanges.
-        where("path = ?", path.with_leading_slash).
-        reorder("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC").
-        limit(limit).
-        preload(:changeset => :user).
-        collect(&:changeset)
-    end
-  end
-
-  def scan_changesets_for_issue_ids
-    self.changesets.each(&:scan_comment_for_issue_ids)
-  end
-
-  # Returns an array of committers usernames and associated user_id
-  def committers
-    @committers ||= Changeset.connection.select_rows(
-         "SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
-  end
-
-  # Maps committers username to a user ids
-  def committer_ids=(h)
-    if h.is_a?(Hash)
-      committers.each do |committer, user_id|
-        new_user_id = h[committer]
-        if new_user_id && (new_user_id.to_i != user_id.to_i)
-          new_user_id = (new_user_id.to_i > 0 ? new_user_id.to_i : nil)
-          Changeset.update_all(
-               "user_id = #{ new_user_id.nil? ? 'NULL' : new_user_id }",
-               ["repository_id = ? AND committer = ?", id, committer])
-        end
-      end
-      @committers            = nil
-      @found_committer_users = nil
-      true
-    else
-      false
-    end
-  end
-
-  # Returns the Redmine User corresponding to the given +committer+
-  # It will return nil if the committer is not yet mapped and if no User
-  # with the same username or email was found
-  def find_committer_user(committer)
-    unless committer.blank?
-      @found_committer_users ||= {}
-      return @found_committer_users[committer] if @found_committer_users.has_key?(committer)
-
-      user = nil
-      c = changesets.where(:committer => committer).includes(:user).first
-      if c && c.user
-        user = c.user
-      elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/
-        username, email = $1.strip, $3
-        u = User.find_by_login(username)
-        u ||= User.find_by_mail(email) unless email.blank?
-        user = u
-      end
-      @found_committer_users[committer] = user
-      user
-    end
-  end
-
-  def repo_log_encoding
-    encoding = log_encoding.to_s.strip
-    encoding.blank? ? 'UTF-8' : encoding
-  end
-
-  # Fetches new changesets for all repositories of active projects
-  # Can be called periodically by an external script
-  # eg. ruby script/runner "Repository.fetch_changesets"
-  def self.fetch_changesets
-    Project.active.has_module(:repository).all.each do |project|
-      project.repositories.each do |repository|
-        begin
-          repository.fetch_changesets
-        rescue Redmine::Scm::Adapters::CommandFailed => e
-          logger.error "scm: error during fetching changesets: #{e.message}"
-        end
-      end
-    end
-  end
-
-  # scan changeset comments to find related and fixed issues for all repositories
-  def self.scan_changesets_for_issue_ids
-    all.each(&:scan_changesets_for_issue_ids)
-  end
-
-  def self.scm_name
-    'Abstract'
-  end
-
-  def self.available_scm
-    subclasses.collect {|klass| [klass.scm_name, klass.name]}
-  end
-
-  def self.factory(klass_name, *args)
-    klass = "Repository::#{klass_name}".constantize
-    klass.new(*args)
-  rescue
-    nil
-  end
-
-  def self.scm_adapter_class
-    nil
-  end
-
-  def self.scm_command
-    ret = ""
-    begin
-      ret = self.scm_adapter_class.client_command if self.scm_adapter_class
-    rescue Exception => e
-      logger.error "scm: error during get command: #{e.message}"
-    end
-    ret
-  end
-
-  def self.scm_version_string
-    ret = ""
-    begin
-      ret = self.scm_adapter_class.client_version_string if self.scm_adapter_class
-    rescue Exception => e
-      logger.error "scm: error during get version string: #{e.message}"
-    end
-    ret
-  end
-
-  def self.scm_available
-    ret = false
-    begin
-      ret = self.scm_adapter_class.client_available if self.scm_adapter_class
-    rescue Exception => e
-      logger.error "scm: error during get scm available: #{e.message}"
-    end
-    ret
-  end
-
-  def set_as_default?
-    new_record? && project && Repository.where(:project_id => project.id).empty?
-  end
-
-  protected
-
-  def check_default
-    if !is_default? && set_as_default?
-      self.is_default = true
-    end
-    if is_default? && is_default_changed?
-      Repository.update_all(["is_default = ?", false], ["project_id = ?", project_id])
-    end
-  end
-
-  def load_entries_changesets(entries)
-    if entries
-      entries.each do |entry|
-        if entry.lastrev && entry.lastrev.identifier
-          entry.changeset = find_changeset_by_name(entry.lastrev.identifier)
-        end
-      end
-    end
-  end
-
-  private
-
-  # Deletes repository data
-  def clear_changesets
-    cs = Changeset.table_name
-    ch = Change.table_name
-    ci = "#{table_name_prefix}changesets_issues#{table_name_suffix}"
-    cp = "#{table_name_prefix}changeset_parents#{table_name_suffix}"
-
-    connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
-    connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
-    connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
-    connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
-    clear_extra_info_of_changesets
-  end
-
-  def clear_extra_info_of_changesets
-  end
-end
--- a/.svn/pristine/2b/2b29654b95c6aadbc6d9e5c8347d2c96aa39a7e1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class BoardTest < ActiveSupport::TestCase
-  fixtures :projects, :boards, :messages, :attachments, :watchers
-
-  include Redmine::I18n
-
-  def setup
-    @project = Project.find(1)
-  end
-
-  def test_create
-    board = Board.new(:project => @project, :name => 'Test board', :description => 'Test board description')
-    assert board.save
-    board.reload
-    assert_equal 'Test board', board.name
-    assert_equal 'Test board description', board.description
-    assert_equal @project, board.project
-    assert_equal 0, board.topics_count
-    assert_equal 0, board.messages_count
-    assert_nil board.last_message
-    # last position
-    assert_equal @project.boards.size, board.position
-  end
-
-  def test_parent_should_be_in_same_project
-    set_language_if_valid 'en'
-    board = Board.new(:project_id => 3, :name => 'Test', :description => 'Test', :parent_id => 1)
-    assert !board.save
-    assert_include "Parent forum is invalid", board.errors.full_messages
-  end
-
-  def test_valid_parents_should_not_include_self_nor_a_descendant
-    board1 = Board.generate!(:project_id => 3)
-    board2 = Board.generate!(:project_id => 3, :parent => board1)
-    board3 = Board.generate!(:project_id => 3, :parent => board2)
-    board4 = Board.generate!(:project_id => 3)
-
-    assert_equal [board4], board1.reload.valid_parents.sort_by(&:id)
-    assert_equal [board1, board4], board2.reload.valid_parents.sort_by(&:id)
-    assert_equal [board1, board2, board4], board3.reload.valid_parents.sort_by(&:id)
-    assert_equal [board1, board2, board3], board4.reload.valid_parents.sort_by(&:id)
-  end
-
-  def test_position_should_be_assigned_with_parent_scope
-    parent1 = Board.generate!(:project_id => 3)
-    parent2 = Board.generate!(:project_id => 3)
-    child1 = Board.generate!(:project_id => 3, :parent => parent1)
-    child2 = Board.generate!(:project_id => 3, :parent => parent1)
-
-    assert_equal 1, parent1.reload.position
-    assert_equal 1, child1.reload.position
-    assert_equal 2, child2.reload.position
-    assert_equal 2, parent2.reload.position
-  end
-
-  def test_board_tree_should_yield_boards_with_level
-    parent1 = Board.generate!(:project_id => 3)
-    parent2 = Board.generate!(:project_id => 3)
-    child1 = Board.generate!(:project_id => 3, :parent => parent1)
-    child2 = Board.generate!(:project_id => 3, :parent => parent1)
-    child3 = Board.generate!(:project_id => 3, :parent => child1)
-
-    tree = Board.board_tree(Project.find(3).boards)
-
-    assert_equal [
-      [parent1, 0],
-      [child1,  1],
-      [child3,  2],
-      [child2,  1],
-      [parent2, 0]
-    ], tree
-  end
-
-  def test_destroy
-    board = Board.find(1)
-    assert_difference 'Message.count', -6 do
-      assert_difference 'Attachment.count', -1 do
-        assert_difference 'Watcher.count', -1 do
-          assert board.destroy
-        end
-      end
-    end
-    assert_equal 0, Message.where(:board_id => 1).count
-  end
-
-  def test_destroy_should_nullify_children
-    parent = Board.generate!(:project => @project)
-    child = Board.generate!(:project => @project, :parent => parent)
-    assert_equal parent, child.parent
-
-    assert parent.destroy
-    child.reload
-    assert_nil child.parent
-    assert_nil child.parent_id
-  end
-end
--- a/.svn/pristine/2b/2b52b333ebdd9a328bfca27bab6d9bb1f5c45425.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class ActivitiesController < ApplicationController
-  menu_item :activity
-  before_filter :find_optional_project
-  accept_rss_auth :index
-
-  def index
-    @days = Setting.activity_days_default.to_i
-
-    if params[:from]
-      begin; @date_to = params[:from].to_date + 1; rescue; end
-    end
-
-    @date_to ||= Date.today + 1
-    @date_from = @date_to - @days
-    @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
-    @author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id]))
-
-    @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project,
-                                                             :with_subprojects => @with_subprojects,
-                                                             :author => @author)
-    @activity.scope_select {|t| !params["show_#{t}"].nil?}
-    @activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty?
-
-    events = @activity.events(@date_from, @date_to)
-
-    if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, events.size, User.current, current_language])
-      respond_to do |format|
-        format.html {
-          @events_by_day = events.group_by {|event| User.current.time_to_date(event.event_datetime)}
-          render :layout => false if request.xhr?
-        }
-        format.atom {
-          title = l(:label_activity)
-          if @author
-            title = @author.name
-          elsif @activity.scope.size == 1
-            title = l("label_#{@activity.scope.first.singularize}_plural")
-          end
-          render_feed(events, :title => "#{@project || Setting.app_title}: #{title}")
-        }
-      end
-    end
-
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  private
-
-  # TODO: refactor, duplicated in projects_controller
-  def find_optional_project
-    return true unless params[:id]
-    @project = Project.find(params[:id])
-    authorize
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/2c/2cb77dbabbdb76fb313ca1932dc0b27e4c8922e1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class SortHelperTest < ActionView::TestCase
-  include SortHelper
-  include Redmine::I18n
-  include ERB::Util
-
-  def setup
-    @session = nil
-    @sort_param = nil
-  end
-
-  def test_default_sort_clause_with_array
-    sort_init 'attr1', 'desc'
-    sort_update(['attr1', 'attr2'])
-
-    assert_equal ['attr1 DESC'], sort_clause
-  end
-
-  def test_default_sort_clause_with_hash
-    sort_init 'attr1', 'desc'
-    sort_update({'attr1' => 'table1.attr1', 'attr2' => 'table2.attr2'})
-
-    assert_equal ['table1.attr1 DESC'], sort_clause
-  end
-
-  def test_default_sort_clause_with_multiple_columns
-    sort_init 'attr1', 'desc'
-    sort_update({'attr1' => ['table1.attr1', 'table1.attr2'], 'attr2' => 'table2.attr2'})
-
-    assert_equal ['table1.attr1 DESC', 'table1.attr2 DESC'], sort_clause
-  end
-
-  def test_params_sort
-    @sort_param = 'attr1,attr2:desc'
-
-    sort_init 'attr1', 'desc'
-    sort_update({'attr1' => 'table1.attr1', 'attr2' => 'table2.attr2'})
-
-    assert_equal ['table1.attr1', 'table2.attr2 DESC'], sort_clause
-    assert_equal 'attr1,attr2:desc', @session['foo_bar_sort']
-  end
-
-  def test_invalid_params_sort
-    @sort_param = 'invalid_key'
-
-    sort_init 'attr1', 'desc'
-    sort_update({'attr1' => 'table1.attr1', 'attr2' => 'table2.attr2'})
-
-    assert_equal ['table1.attr1 DESC'], sort_clause
-    assert_equal 'attr1:desc', @session['foo_bar_sort']
-  end
-
-  def test_invalid_order_params_sort
-    @sort_param = 'attr1:foo:bar,attr2'
-
-    sort_init 'attr1', 'desc'
-    sort_update({'attr1' => 'table1.attr1', 'attr2' => 'table2.attr2'})
-
-    assert_equal ['table1.attr1', 'table2.attr2'], sort_clause
-    assert_equal 'attr1,attr2', @session['foo_bar_sort']
-  end
-
-  private
-
-  def controller_name; 'foo'; end
-  def action_name; 'bar'; end
-  def params; {:sort => @sort_param}; end
-  def session; @session ||= {}; end
-end
--- a/.svn/pristine/2c/2cd1e675be2a1ca2a16f8842efaf3d36d343a516.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module ReportsHelper
-
-  def aggregate(data, criteria)
-    a = 0
-    data.each { |row|
-      match = 1
-      criteria.each { |k, v|
-        match = 0 unless (row[k].to_s == v.to_s) || (k == 'closed' &&  (v == 0 ? ['f', false] : ['t', true]).include?(row[k]))
-      } unless criteria.nil?
-      a = a + row["total"].to_i if match == 1
-    } unless data.nil?
-    a
-  end
-
-  def aggregate_link(data, criteria, *args)
-    a = aggregate data, criteria
-    a > 0 ? link_to(h(a), *args) : '-'
-  end
-
-  def aggregate_path(project, field, row, options={})
-    parameters = {:set_filter => 1, :subproject_id => '!*', field => row.id}.merge(options)
-    project_issues_path(row.is_a?(Project) ? row : project, parameters)
-  end
-end
--- a/.svn/pristine/2c/2cfeab9b9366f48fd720b77fb1dc5f6f878ef869.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/core_ext'
-
-begin
-  require 'RMagick' unless Object.const_defined?(:Magick)
-rescue LoadError
-  # RMagick is not available
-end
-
-require 'redmine/scm/base'
-require 'redmine/access_control'
-require 'redmine/access_keys'
-require 'redmine/activity'
-require 'redmine/activity/fetcher'
-require 'redmine/ciphering'
-require 'redmine/codeset_util'
-require 'redmine/custom_field_format'
-require 'redmine/i18n'
-require 'redmine/menu_manager'
-require 'redmine/notifiable'
-require 'redmine/platform'
-require 'redmine/mime_type'
-require 'redmine/notifiable'
-require 'redmine/search'
-require 'redmine/syntax_highlighting'
-require 'redmine/thumbnail'
-require 'redmine/unified_diff'
-require 'redmine/utils'
-require 'redmine/version'
-require 'redmine/wiki_formatting'
-
-require 'redmine/default_data/loader'
-require 'redmine/helpers/calendar'
-require 'redmine/helpers/diff'
-require 'redmine/helpers/gantt'
-require 'redmine/helpers/time_report'
-require 'redmine/views/other_formats_builder'
-require 'redmine/views/labelled_form_builder'
-require 'redmine/views/builders'
-
-require 'redmine/themes'
-require 'redmine/hook'
-require 'redmine/plugin'
-
-if RUBY_VERSION < '1.9'
-  require 'fastercsv'
-else
-  require 'csv'
-  FCSV = CSV
-end
-
-Redmine::Scm::Base.add "Subversion"
-Redmine::Scm::Base.add "Darcs"
-Redmine::Scm::Base.add "Mercurial"
-Redmine::Scm::Base.add "Cvs"
-Redmine::Scm::Base.add "Bazaar"
-Redmine::Scm::Base.add "Git"
-Redmine::Scm::Base.add "Filesystem"
-
-Redmine::CustomFieldFormat.map do |fields|
-  fields.register 'string'
-  fields.register 'text'
-  fields.register 'int', :label => :label_integer
-  fields.register 'float'
-  fields.register 'list'
-  fields.register 'date'
-  fields.register 'bool', :label => :label_boolean
-  fields.register 'user', :only => %w(Issue TimeEntry Version Project), :edit_as => 'list'
-  fields.register 'version', :only => %w(Issue TimeEntry Version Project), :edit_as => 'list'
-end
-
-# Permissions
-Redmine::AccessControl.map do |map|
-  map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true, :read => true
-  map.permission :search_project, {:search => :index}, :public => true, :read => true
-  map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
-  map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
-  map.permission :close_project, {:projects => [:close, :reopen]}, :require => :member, :read => true
-  map.permission :select_project_modules, {:projects => :modules}, :require => :member
-  map.permission :manage_members, {:projects => :settings, :members => [:index, :show, :create, :update, :destroy, :autocomplete]}, :require => :member
-  map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
-  map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
-
-  map.project_module :issue_tracking do |map|
-    # Issue categories
-    map.permission :manage_categories, {:projects => :settings, :issue_categories => [:index, :show, :new, :create, :edit, :update, :destroy]}, :require => :member
-    # Issues
-    map.permission :view_issues, {:issues => [:index, :show],
-                                  :auto_complete => [:issues],
-                                  :context_menus => [:issues],
-                                  :versions => [:index, :show, :status_by],
-                                  :journals => [:index, :diff],
-                                  :queries => :index,
-                                  :reports => [:issue_report, :issue_report_details]},
-                                  :read => true
-    map.permission :add_issues, {:issues => [:new, :create, :update_form], :attachments => :upload}
-    map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new], :attachments => :upload}
-    map.permission :manage_issue_relations, {:issue_relations => [:index, :show, :create, :destroy]}
-    map.permission :manage_subtasks, {}
-    map.permission :set_issues_private, {}
-    map.permission :set_own_issues_private, {}, :require => :loggedin
-    map.permission :add_issue_notes, {:issues => [:edit, :update, :update_form], :journals => [:new], :attachments => :upload}
-    map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
-    map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
-    map.permission :view_private_notes, {}, :read => true, :require => :member
-    map.permission :set_notes_private, {}, :require => :member
-    map.permission :move_issues, {:issues => [:bulk_edit, :bulk_update]}, :require => :loggedin
-    map.permission :delete_issues, {:issues => :destroy}, :require => :member
-    # Queries
-    map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member
-    map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
-    # Watchers
-    map.permission :view_issue_watchers, {}, :read => true
-    map.permission :add_issue_watchers, {:watchers => [:new, :create, :append, :autocomplete_for_user]}
-    map.permission :delete_issue_watchers, {:watchers => :destroy}
-  end
-
-  map.project_module :time_tracking do |map|
-    map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
-    map.permission :view_time_entries, {:timelog => [:index, :report, :show]}, :read => true
-    map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
-    map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
-    map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
-  end
-
-  map.project_module :news do |map|
-    map.permission :manage_news, {:news => [:new, :create, :edit, :update, :destroy], :comments => [:destroy]}, :require => :member
-    map.permission :view_news, {:news => [:index, :show]}, :public => true, :read => true
-    map.permission :comment_news, {:comments => :create}
-  end
-
-  map.project_module :documents do |map|
-    map.permission :add_documents, {:documents => [:new, :create, :add_attachment]}, :require => :loggedin
-    map.permission :edit_documents, {:documents => [:edit, :update, :add_attachment]}, :require => :loggedin
-    map.permission :delete_documents, {:documents => [:destroy]}, :require => :loggedin
-    map.permission :view_documents, {:documents => [:index, :show, :download]}, :read => true
-  end
-
-  map.project_module :files do |map|
-    map.permission :manage_files, {:files => [:new, :create]}, :require => :loggedin
-    map.permission :view_files, {:files => :index, :versions => :download}, :read => true
-  end
-
-  map.project_module :wiki do |map|
-    map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
-    map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
-    map.permission :delete_wiki_pages, {:wiki => [:destroy, :destroy_version]}, :require => :member
-    map.permission :view_wiki_pages, {:wiki => [:index, :show, :special, :date_index]}, :read => true
-    map.permission :export_wiki_pages, {:wiki => [:export]}, :read => true
-    map.permission :view_wiki_edits, {:wiki => [:history, :diff, :annotate]}, :read => true
-    map.permission :edit_wiki_pages, :wiki => [:edit, :update, :preview, :add_attachment]
-    map.permission :delete_wiki_pages_attachments, {}
-    map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
-  end
-
-  map.project_module :repository do |map|
-    map.permission :manage_repository, {:repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
-    map.permission :browse_repository, {:repositories => [:show, :browse, :entry, :raw, :annotate, :changes, :diff, :stats, :graph]}, :read => true
-    map.permission :view_changesets, {:repositories => [:show, :revisions, :revision]}, :read => true
-    map.permission :commit_access, {}
-    map.permission :manage_related_issues, {:repositories => [:add_related_issue, :remove_related_issue]}
-  end
-
-  map.project_module :boards do |map|
-    map.permission :manage_boards, {:boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
-    map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true, :read => true
-    map.permission :add_messages, {:messages => [:new, :reply, :quote]}
-    map.permission :edit_messages, {:messages => :edit}, :require => :member
-    map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
-    map.permission :delete_messages, {:messages => :destroy}, :require => :member
-    map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
-  end
-
-  map.project_module :calendar do |map|
-    map.permission :view_calendar, {:calendars => [:show, :update]}, :read => true
-  end
-
-  map.project_module :gantt do |map|
-    map.permission :view_gantt, {:gantts => [:show, :update]}, :read => true
-  end
-end
-
-Redmine::MenuManager.map :top_menu do |menu|
-  menu.push :home, :home_path
-  menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
-  menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
-  menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
-  menu.push :help, Redmine::Info.help_url, :last => true
-end
-
-Redmine::MenuManager.map :account_menu do |menu|
-  menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
-  menu.push :register, :register_path, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
-  menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
-  menu.push :logout, :signout_path, :html => {:method => 'post'}, :if => Proc.new { User.current.logged? }
-end
-
-Redmine::MenuManager.map :application_menu do |menu|
-  # Empty
-end
-
-Redmine::MenuManager.map :admin_menu do |menu|
-  menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
-  menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
-  menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
-  menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
-  menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
-  menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
-            :html => {:class => 'issue_statuses'}
-  menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
-  menu.push :custom_fields, {:controller => 'custom_fields'},  :caption => :label_custom_field_plural,
-            :html => {:class => 'custom_fields'}
-  menu.push :enumerations, {:controller => 'enumerations'}
-  menu.push :settings, {:controller => 'settings'}
-  menu.push :ldap_authentication, {:controller => 'auth_sources', :action => 'index'},
-            :html => {:class => 'server_authentication'}
-  menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
-  menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
-end
-
-Redmine::MenuManager.map :project_menu do |menu|
-  menu.push :overview, { :controller => 'projects', :action => 'show' }
-  menu.push :activity, { :controller => 'activities', :action => 'index' }
-  menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
-              :if => Proc.new { |p| p.shared_versions.any? }
-  menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
-  menu.push :new_issue, { :controller => 'issues', :action => 'new', :copy_from => nil }, :param => :project_id, :caption => :label_issue_new,
-              :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
-  menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
-  menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
-  menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
-  menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
-  menu.push :wiki, { :controller => 'wiki', :action => 'show', :id => nil }, :param => :project_id,
-              :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
-  menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
-              :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
-  menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
-  menu.push :repository, { :controller => 'repositories', :action => 'show', :repository_id => nil, :path => nil, :rev => nil },
-              :if => Proc.new { |p| p.repository && !p.repository.new_record? }
-  menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
-end
-
-Redmine::Activity.map do |activity|
-  activity.register :issues, :class_name => %w(Issue Journal)
-  activity.register :changesets
-  activity.register :news
-  activity.register :documents, :class_name => %w(Document Attachment)
-  activity.register :files, :class_name => 'Attachment'
-  activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
-  activity.register :messages, :default => false
-  activity.register :time_entries, :default => false
-end
-
-Redmine::Search.map do |search|
-  search.register :issues
-  search.register :news
-  search.register :documents
-  search.register :changesets
-  search.register :wiki_pages
-  search.register :messages
-  search.register :projects
-end
-
-Redmine::WikiFormatting.map do |format|
-  format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
-end
-
-ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler
--- a/.svn/pristine/2d/2d3d652686003e0e75f2451ee9050de946a60dda.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-# Generic exception for when the AuthSource can not be reached
-# (eg. can not connect to the LDAP)
-class AuthSourceException < Exception; end
-class AuthSourceTimeoutException < AuthSourceException; end
-
-class AuthSource < ActiveRecord::Base
-  include Redmine::SubclassFactory
-  include Redmine::Ciphering
-
-  has_many :users
-
-  validates_presence_of :name
-  validates_uniqueness_of :name
-  validates_length_of :name, :maximum => 60
-
-  def authenticate(login, password)
-  end
-
-  def test_connection
-  end
-
-  def auth_method_name
-    "Abstract"
-  end
-
-  def account_password
-    read_ciphered_attribute(:account_password)
-  end
-
-  def account_password=(arg)
-    write_ciphered_attribute(:account_password, arg)
-  end
-
-  def searchable?
-    false
-  end
-
-  def self.search(q)
-    results = []
-    AuthSource.all.each do |source|
-      begin
-        if source.searchable?
-          results += source.search(q)
-        end
-      rescue AuthSourceException => e
-        logger.error "Error while searching users in #{source.name}: #{e.message}"
-      end
-    end
-    results
-  end
-
-  def allow_password_changes?
-    self.class.allow_password_changes?
-  end
-
-  # Does this auth source backend allow password changes?
-  def self.allow_password_changes?
-    false
-  end
-
-  # Try to authenticate a user not yet registered against available sources
-  def self.authenticate(login, password)
-    AuthSource.where(:onthefly_register => true).all.each do |source|
-      begin
-        logger.debug "Authenticating '#{login}' against '#{source.name}'" if logger && logger.debug?
-        attrs = source.authenticate(login, password)
-      rescue => e
-        logger.error "Error during authentication: #{e.message}"
-        attrs = nil
-      end
-      return attrs if attrs
-    end
-    return nil
-  end
-end
--- a/.svn/pristine/2d/2d85d0783f59c365e1251c736bcbc44da38bc043.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WikiPageTest < ActiveSupport::TestCase
-  fixtures :projects, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
-
-  def setup
-    @wiki = Wiki.find(1)
-    @page = @wiki.pages.first
-  end
-
-  def test_create
-    page = WikiPage.new(:wiki => @wiki)
-    assert !page.save
-    assert_equal 1, page.errors.count
-
-    page.title = "Page"
-    assert page.save
-    page.reload
-    assert !page.protected?
-
-    @wiki.reload
-    assert @wiki.pages.include?(page)
-  end
-
-  def test_sidebar_should_be_protected_by_default
-    page = @wiki.find_or_new_page('sidebar')
-    assert page.new_record?
-    assert page.protected?
-  end
-
-  def test_find_or_new_page
-    page = @wiki.find_or_new_page("CookBook documentation")
-    assert_kind_of WikiPage, page
-    assert !page.new_record?
-
-    page = @wiki.find_or_new_page("Non existing page")
-    assert_kind_of WikiPage, page
-    assert page.new_record?
-  end
-
-  def test_parent_title
-    page = WikiPage.find_by_title('Another_page')
-    assert_nil page.parent_title
-
-    page = WikiPage.find_by_title('Page_with_an_inline_image')
-    assert_equal 'CookBook documentation', page.parent_title
-  end
-
-  def test_assign_parent
-    page = WikiPage.find_by_title('Another_page')
-    page.parent_title = 'CookBook documentation'
-    assert page.save
-    page.reload
-    assert_equal WikiPage.find_by_title('CookBook_documentation'), page.parent
-  end
-
-  def test_unassign_parent
-    page = WikiPage.find_by_title('Page_with_an_inline_image')
-    page.parent_title = ''
-    assert page.save
-    page.reload
-    assert_nil page.parent
-  end
-
-  def test_parent_validation
-    page = WikiPage.find_by_title('CookBook_documentation')
-
-    # A page that doesn't exist
-    page.parent_title = 'Unknown title'
-    assert !page.save
-    assert_include I18n.translate('activerecord.errors.messages.invalid'),
-                   page.errors[:parent_title]
-    # A child page
-    page.parent_title = 'Page_with_an_inline_image'
-    assert !page.save
-    assert_include I18n.translate('activerecord.errors.messages.circular_dependency'),
-                   page.errors[:parent_title]
-    # The page itself
-    page.parent_title = 'CookBook_documentation'
-    assert !page.save
-    assert_include I18n.translate('activerecord.errors.messages.circular_dependency'),
-                   page.errors[:parent_title]
-    page.parent_title = 'Another_page'
-    assert page.save
-  end
-
-  def test_destroy
-    page = WikiPage.find(1)
-    page.destroy
-    assert_nil WikiPage.find_by_id(1)
-    # make sure that page content and its history are deleted
-    assert WikiContent.find_all_by_page_id(1).empty?
-    assert WikiContent.versioned_class.find_all_by_page_id(1).empty?
-  end
-
-  def test_destroy_should_not_nullify_children
-    page = WikiPage.find(2)
-    child_ids = page.child_ids
-    assert child_ids.any?
-    page.destroy
-    assert_nil WikiPage.find_by_id(2)
-
-    children = WikiPage.find_all_by_id(child_ids)
-    assert_equal child_ids.size, children.size
-    children.each do |child|
-      assert_nil child.parent_id
-    end
-  end
-
-  def test_updated_on_eager_load
-    page = WikiPage.with_updated_on.first(:order => 'id')
-    assert page.is_a?(WikiPage)
-    assert_not_nil page.read_attribute(:updated_on)
-    assert_equal Time.gm(2007, 3, 6, 23, 10, 51), page.content.updated_on
-    assert_equal page.content.updated_on, page.updated_on
-    assert_not_nil page.read_attribute(:version)
-  end
-
-  def test_descendants
-    page = WikiPage.create!(:wiki => @wiki, :title => 'Parent')
-    child1 = WikiPage.create!(:wiki => @wiki, :title => 'Child1', :parent => page)
-    child11 = WikiPage.create!(:wiki => @wiki, :title => 'Child11', :parent => child1)
-    child111 = WikiPage.create!(:wiki => @wiki, :title => 'Child111', :parent => child11)
-    child2 = WikiPage.create!(:wiki => @wiki, :title => 'Child2', :parent => page)
-
-    assert_equal %w(Child1 Child11 Child111 Child2), page.descendants.map(&:title).sort
-    assert_equal %w(Child1 Child11 Child111 Child2), page.descendants(nil).map(&:title).sort
-    assert_equal %w(Child1 Child11 Child2), page.descendants(2).map(&:title).sort
-    assert_equal %w(Child1 Child2), page.descendants(1).map(&:title).sort
-
-    assert_equal %w(Child1 Child11 Child111 Child2 Parent), page.self_and_descendants.map(&:title).sort
-    assert_equal %w(Child1 Child11 Child111 Child2 Parent), page.self_and_descendants(nil).map(&:title).sort
-    assert_equal %w(Child1 Child11 Child2 Parent), page.self_and_descendants(2).map(&:title).sort
-    assert_equal %w(Child1 Child2 Parent), page.self_and_descendants(1).map(&:title).sort
-  end
-
-  def test_diff_for_page_with_deleted_version_should_pick_the_previous_available_version
-    WikiContent::Version.find_by_page_id_and_version(1, 2).destroy
-
-    page = WikiPage.find(1)
-    diff = page.diff(3)
-    assert_not_nil diff
-    assert_equal 3, diff.content_to.version
-    assert_equal 1, diff.content_from.version
-  end
-end
--- a/.svn/pristine/2d/2dbd0564d495b47bea2303b32f1609a8bf5c4b1a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingJournalsTest < ActionController::IntegrationTest
-  def test_journals
-    assert_routing(
-        { :method => 'post', :path => "/issues/1/quoted" },
-        { :controller => 'journals', :action => 'new', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/changes" },
-        { :controller => 'journals', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/journals/diff/1" },
-        { :controller => 'journals', :action => 'diff', :id => '1' }
-      )
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/journals/edit/1" },
-          { :controller => 'journals', :action => 'edit', :id => '1' }
-        )
-    end
-  end
-end
--- a/.svn/pristine/2d/2dc8d26abfe6ba28f20c56a8a294830b5d124597.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class VersionsController < ApplicationController
-  menu_item :roadmap
-  model_object Version
-  before_filter :find_model_object, :except => [:index, :new, :create, :close_completed]
-  before_filter :find_project_from_association, :except => [:index, :new, :create, :close_completed]
-  before_filter :find_project_by_project_id, :only => [:index, :new, :create, :close_completed]
-  before_filter :authorize
-
-  accept_api_auth :index, :show, :create, :update, :destroy
-
-  helper :custom_fields
-  helper :projects
-
-  def index
-    respond_to do |format|
-      format.html {
-        @trackers = @project.trackers.sorted.all
-        retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?})
-        @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
-        project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id]
-
-        @versions = @project.shared_versions || []
-        @versions += @project.rolled_up_versions.visible if @with_subprojects
-        @versions = @versions.uniq.sort
-        unless params[:completed]
-          @completed_versions = @versions.select {|version| version.closed? || version.completed? }
-          @versions -= @completed_versions
-        end
-
-        @issues_by_version = {}
-        if @selected_tracker_ids.any? && @versions.any?
-          issues = Issue.visible.
-            includes(:project, :tracker).
-            preload(:status, :priority, :fixed_version).
-            where(:tracker_id => @selected_tracker_ids, :project_id => project_ids, :fixed_version_id => @versions.map(&:id)).
-            order("#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
-          @issues_by_version = issues.group_by(&:fixed_version)
-        end
-        @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
-      }
-      format.api {
-        @versions = @project.shared_versions.all
-      }
-    end
-  end
-
-  def show
-    respond_to do |format|
-      format.html {
-        @issues = @version.fixed_issues.visible.
-          includes(:status, :tracker, :priority).
-          reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id").
-          all
-      }
-      format.api
-    end
-  end
-
-  def new
-    @version = @project.versions.build
-    @version.safe_attributes = params[:version]
-
-    respond_to do |format|
-      format.html
-      format.js
-    end
-  end
-
-  def create
-    @version = @project.versions.build
-    if params[:version]
-      attributes = params[:version].dup
-      attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
-      @version.safe_attributes = attributes
-    end
-
-    if request.post?
-      if @version.save
-        respond_to do |format|
-          format.html do
-            flash[:notice] = l(:notice_successful_create)
-            redirect_back_or_default settings_project_path(@project, :tab => 'versions')
-          end
-          format.js
-          format.api do
-            render :action => 'show', :status => :created, :location => version_url(@version)
-          end
-        end
-      else
-        respond_to do |format|
-          format.html { render :action => 'new' }
-          format.js   { render :action => 'new' }
-          format.api  { render_validation_errors(@version) }
-        end
-      end
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    if request.put? && params[:version]
-      attributes = params[:version].dup
-      attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
-      @version.safe_attributes = attributes
-      if @version.save
-        respond_to do |format|
-          format.html {
-            flash[:notice] = l(:notice_successful_update)
-            redirect_back_or_default settings_project_path(@project, :tab => 'versions')
-          }
-          format.api  { render_api_ok }
-        end
-      else
-        respond_to do |format|
-          format.html { render :action => 'edit' }
-          format.api  { render_validation_errors(@version) }
-        end
-      end
-    end
-  end
-
-  def close_completed
-    if request.put?
-      @project.close_completed_versions
-    end
-    redirect_to settings_project_path(@project, :tab => 'versions')
-  end
-
-  def destroy
-    if @version.fixed_issues.empty?
-      @version.destroy
-      respond_to do |format|
-        format.html { redirect_back_or_default settings_project_path(@project, :tab => 'versions') }
-        format.api  { render_api_ok }
-      end
-    else
-      respond_to do |format|
-        format.html {
-          flash[:error] = l(:notice_unable_delete_version)
-          redirect_to settings_project_path(@project, :tab => 'versions')
-        }
-        format.api  { head :unprocessable_entity }
-      end
-    end
-  end
-
-  def status_by
-    respond_to do |format|
-      format.html { render :action => 'show' }
-      format.js
-    end
-  end
-
-  private
-
-  def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil)
-    if ids = params[:tracker_ids]
-      @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
-    else
-      @selected_tracker_ids = (default_trackers || selectable_trackers).collect {|t| t.id.to_s }
-    end
-  end
-end
--- a/.svn/pristine/2d/2dfab9f6389ac98654c616cc002d4ad37cf273c9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,372 +0,0 @@
-# -*- coding: utf-8 -*-
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class TimeEntryReportsControllerTest < ActionController::TestCase
-  tests TimelogController
-
-  fixtures :projects, :enabled_modules, :roles, :members, :member_roles,
-           :issues, :time_entries, :users, :trackers, :enumerations,
-           :issue_statuses, :custom_fields, :custom_values
-
-  include Redmine::I18n
-
-  def setup
-    Setting.default_language = "en"
-  end
-
-  def test_report_at_project_level
-    get :report, :project_id => 'ecookbook'
-    assert_response :success
-    assert_template 'report'
-    assert_tag :form,
-      :attributes => {:action => "/projects/ecookbook/time_entries/report", :id => 'query_form'}
-  end
-
-  def test_report_all_projects
-    get :report
-    assert_response :success
-    assert_template 'report'
-    assert_tag :form,
-      :attributes => {:action => "/time_entries/report", :id => 'query_form'}
-  end
-
-  def test_report_all_projects_denied
-    r = Role.anonymous
-    r.permissions.delete(:view_time_entries)
-    r.permissions_will_change!
-    r.save
-    get :report
-    assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Ftime_entries%2Freport'
-  end
-
-  def test_report_all_projects_one_criteria
-    get :report, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']
-    assert_response :success
-    assert_template 'report'
-    assert_not_nil assigns(:report)
-    assert_equal "8.65", "%.2f" % assigns(:report).total_hours
-  end
-
-  def test_report_all_time
-    get :report, :project_id => 1, :criteria => ['project', 'issue']
-    assert_response :success
-    assert_template 'report'
-    assert_not_nil assigns(:report)
-    assert_equal "162.90", "%.2f" % assigns(:report).total_hours
-  end
-
-  def test_report_all_time_by_day
-    get :report, :project_id => 1, :criteria => ['project', 'issue'], :columns => 'day'
-    assert_response :success
-    assert_template 'report'
-    assert_not_nil assigns(:report)
-    assert_equal "162.90", "%.2f" % assigns(:report).total_hours
-    assert_tag :tag => 'th', :content => '2007-03-12'
-  end
-
-  def test_report_one_criteria
-    get :report, :project_id => 1, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']
-    assert_response :success
-    assert_template 'report'
-    assert_not_nil assigns(:report)
-    assert_equal "8.65", "%.2f" % assigns(:report).total_hours
-  end
-
-  def test_report_two_criteria
-    get :report, :project_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criteria => ["user", "activity"]
-    assert_response :success
-    assert_template 'report'
-    assert_not_nil assigns(:report)
-    assert_equal "162.90", "%.2f" % assigns(:report).total_hours
-  end
-
-  def test_report_custom_field_criteria_with_multiple_values
-    field = TimeEntryCustomField.create!(:name => 'multi', :field_format => 'list', :possible_values => ['value1', 'value2'])
-    entry = TimeEntry.create!(:project => Project.find(1), :hours => 1, :activity_id => 10, :user => User.find(2), :spent_on => Date.today)
-    CustomValue.create!(:customized => entry, :custom_field => field, :value => 'value1')
-    CustomValue.create!(:customized => entry, :custom_field => field, :value => 'value2')
-
-    get :report, :project_id => 1, :columns => 'day', :criteria => ["cf_#{field.id}"]
-    assert_response :success
-  end
-
-  def test_report_one_day
-    get :report, :project_id => 1, :columns => 'day', :from => "2007-03-23", :to => "2007-03-23", :criteria => ["user", "activity"]
-    assert_response :success
-    assert_template 'report'
-    assert_not_nil assigns(:report)
-    assert_equal "4.25", "%.2f" % assigns(:report).total_hours
-  end
-
-  def test_report_at_issue_level
-    get :report, :project_id => 1, :issue_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criteria => ["user", "activity"]
-    assert_response :success
-    assert_template 'report'
-    assert_not_nil assigns(:report)
-    assert_equal "154.25", "%.2f" % assigns(:report).total_hours
-    assert_tag :form,
-      :attributes => {:action => "/projects/ecookbook/issues/1/time_entries/report", :id => 'query_form'}
-  end
-
-  def test_report_by_week_should_use_commercial_year
-    TimeEntry.delete_all
-    TimeEntry.generate!(:hours => '2', :spent_on => '2009-12-25') # 2009-52
-    TimeEntry.generate!(:hours => '4', :spent_on => '2009-12-31') # 2009-53
-    TimeEntry.generate!(:hours => '8', :spent_on => '2010-01-01') # 2009-53
-    TimeEntry.generate!(:hours => '16', :spent_on => '2010-01-05') # 2010-1
-
-    get :report, :columns => 'week', :from => "2009-12-25", :to => "2010-01-05", :criteria => ["project"]
-    assert_response :success
-
-    assert_select '#time-report thead tr' do
-      assert_select 'th:nth-child(1)', :text => 'Project'
-      assert_select 'th:nth-child(2)', :text => '2009-52'
-      assert_select 'th:nth-child(3)', :text => '2009-53'
-      assert_select 'th:nth-child(4)', :text => '2010-1'
-      assert_select 'th:nth-child(5)', :text => 'Total time'
-    end
-    assert_select '#time-report tbody tr' do
-      assert_select 'td:nth-child(1)', :text => 'eCookbook'
-      assert_select 'td:nth-child(2)', :text => '2.00'
-      assert_select 'td:nth-child(3)', :text => '12.00'
-      assert_select 'td:nth-child(4)', :text => '16.00'
-      assert_select 'td:nth-child(5)', :text => '30.00' # Total
-    end
-  end
-
-  def test_report_should_propose_association_custom_fields
-    get :report
-    assert_response :success
-    assert_template 'report'
-
-    assert_select 'select[name=?]', 'criteria[]' do
-      assert_select 'option[value=cf_1]', {:text => 'Database'}, 'Issue custom field not found'
-      assert_select 'option[value=cf_3]', {:text => 'Development status'}, 'Project custom field not found'
-      assert_select 'option[value=cf_7]', {:text => 'Billable'}, 'TimeEntryActivity custom field not found'
-    end
-  end
-
-  def test_report_with_association_custom_fields
-    get :report, :criteria => ['cf_1', 'cf_3', 'cf_7']
-    assert_response :success
-    assert_template 'report'
-    assert_not_nil assigns(:report)
-    assert_equal 3, assigns(:report).criteria.size
-    assert_equal "162.90", "%.2f" % assigns(:report).total_hours
-
-    # Custom fields columns
-    assert_select 'th', :text => 'Database'
-    assert_select 'th', :text => 'Development status'
-    assert_select 'th', :text => 'Billable'
-
-    # Custom field row
-    assert_select 'tr' do
-      assert_select 'td', :text => 'MySQL'
-      assert_select 'td.hours', :text => '1.00'
-    end
-  end
-
-  def test_report_one_criteria_no_result
-    get :report, :project_id => 1, :columns => 'week', :from => "1998-04-01", :to => "1998-04-30", :criteria => ['project']
-    assert_response :success
-    assert_template 'report'
-    assert_not_nil assigns(:report)
-    assert_equal "0.00", "%.2f" % assigns(:report).total_hours
-  end
-
-  def test_report_status_criterion
-    get :report, :project_id => 1, :criteria => ['status']
-    assert_response :success
-    assert_template 'report'
-    assert_tag :tag => 'th', :content => 'Status'
-    assert_tag :tag => 'td', :content => 'New'
-  end
-
-  def test_report_all_projects_csv_export
-    get :report, :columns => 'month', :from => "2007-01-01", :to => "2007-06-30",
-        :criteria => ["project", "user", "activity"], :format => "csv"
-    assert_response :success
-    assert_equal 'text/csv; header=present', @response.content_type
-    lines = @response.body.chomp.split("\n")
-    # Headers
-    assert_equal 'Project,User,Activity,2007-3,2007-4,Total time', lines.first
-    # Total row
-    assert_equal 'Total time,"","",154.25,8.65,162.90', lines.last
-  end
-
-  def test_report_csv_export
-    get :report, :project_id => 1, :columns => 'month',
-        :from => "2007-01-01", :to => "2007-06-30",
-        :criteria => ["project", "user", "activity"], :format => "csv"
-    assert_response :success
-    assert_equal 'text/csv; header=present', @response.content_type
-    lines = @response.body.chomp.split("\n")
-    # Headers
-    assert_equal 'Project,User,Activity,2007-3,2007-4,Total time', lines.first
-    # Total row
-    assert_equal 'Total time,"","",154.25,8.65,162.90', lines.last
-  end
-
-  def test_csv_big_5
-    Setting.default_language = "zh-TW"
-    str_utf8  = "\xe4\xb8\x80\xe6\x9c\x88"
-    str_big5  = "\xa4@\xa4\xeb"
-    if str_utf8.respond_to?(:force_encoding)
-      str_utf8.force_encoding('UTF-8')
-      str_big5.force_encoding('Big5')
-    end
-    user = User.find_by_id(3)
-    user.firstname = str_utf8
-    user.lastname  = "test-lastname"
-    assert user.save
-    comments = "test_csv_big_5"
-    te1 = TimeEntry.create(:spent_on => '2011-11-11',
-                           :hours    => 7.3,
-                           :project  => Project.find(1),
-                           :user     => user,
-                           :activity => TimeEntryActivity.find_by_name('Design'),
-                           :comments => comments)
-
-    te2 = TimeEntry.find_by_comments(comments)
-    assert_not_nil te2
-    assert_equal 7.3, te2.hours
-    assert_equal 3, te2.user_id
-
-    get :report, :project_id => 1, :columns => 'day',
-        :from => "2011-11-11", :to => "2011-11-11",
-        :criteria => ["user"], :format => "csv"
-    assert_response :success
-    assert_equal 'text/csv; header=present', @response.content_type
-    lines = @response.body.chomp.split("\n")    
-    # Headers
-    s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp"
-    s2 = "\xa4u\xae\xc9\xc1`\xadp"
-    if s1.respond_to?(:force_encoding)
-      s1.force_encoding('Big5')
-      s2.force_encoding('Big5')
-    end
-    assert_equal s1, lines.first
-    # Total row
-    assert_equal "#{str_big5} #{user.lastname},7.30,7.30", lines[1]
-    assert_equal "#{s2},7.30,7.30", lines[2]
-
-    str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)"
-    if str_tw.respond_to?(:force_encoding)
-      str_tw.force_encoding('UTF-8')
-    end
-    assert_equal str_tw, l(:general_lang_name)
-    assert_equal 'Big5', l(:general_csv_encoding)
-    assert_equal ',', l(:general_csv_separator)
-    assert_equal '.', l(:general_csv_decimal_separator)
-  end
-
-  def test_csv_cannot_convert_should_be_replaced_big_5
-    Setting.default_language = "zh-TW"
-    str_utf8  = "\xe4\xbb\xa5\xe5\x86\x85"
-    if str_utf8.respond_to?(:force_encoding)
-      str_utf8.force_encoding('UTF-8')
-    end
-    user = User.find_by_id(3)
-    user.firstname = str_utf8
-    user.lastname  = "test-lastname"
-    assert user.save
-    comments = "test_replaced"
-    te1 = TimeEntry.create(:spent_on => '2011-11-11',
-                           :hours    => 7.3,
-                           :project  => Project.find(1),
-                           :user     => user,
-                           :activity => TimeEntryActivity.find_by_name('Design'),
-                           :comments => comments)
-
-    te2 = TimeEntry.find_by_comments(comments)
-    assert_not_nil te2
-    assert_equal 7.3, te2.hours
-    assert_equal 3, te2.user_id
-
-    get :report, :project_id => 1, :columns => 'day',
-        :from => "2011-11-11", :to => "2011-11-11",
-        :criteria => ["user"], :format => "csv"
-    assert_response :success
-    assert_equal 'text/csv; header=present', @response.content_type
-    lines = @response.body.chomp.split("\n")    
-    # Headers
-    s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp"
-    if s1.respond_to?(:force_encoding)
-      s1.force_encoding('Big5')
-    end
-    assert_equal s1, lines.first
-    # Total row
-    s2 = ""
-    if s2.respond_to?(:force_encoding)
-      s2 = "\xa5H?"
-      s2.force_encoding('Big5')
-    elsif RUBY_PLATFORM == 'java'
-      s2 = "??"
-    else
-      s2 = "\xa5H???"
-    end
-    assert_equal "#{s2} #{user.lastname},7.30,7.30", lines[1]
-  end
-
-  def test_csv_fr
-    with_settings :default_language => "fr" do
-      str1  = "test_csv_fr"
-      user = User.find_by_id(3)
-      te1 = TimeEntry.create(:spent_on => '2011-11-11',
-                             :hours    => 7.3,
-                             :project  => Project.find(1),
-                             :user     => user,
-                             :activity => TimeEntryActivity.find_by_name('Design'),
-                             :comments => str1)
-
-      te2 = TimeEntry.find_by_comments(str1)
-      assert_not_nil te2
-      assert_equal 7.3, te2.hours
-      assert_equal 3, te2.user_id
-
-      get :report, :project_id => 1, :columns => 'day',
-          :from => "2011-11-11", :to => "2011-11-11",
-          :criteria => ["user"], :format => "csv"
-      assert_response :success
-      assert_equal 'text/csv; header=present', @response.content_type
-      lines = @response.body.chomp.split("\n")    
-      # Headers
-      s1 = "Utilisateur;2011-11-11;Temps total"
-      s2 = "Temps total"
-      if s1.respond_to?(:force_encoding)
-        s1.force_encoding('ISO-8859-1')
-        s2.force_encoding('ISO-8859-1')
-      end
-      assert_equal s1, lines.first
-      # Total row
-      assert_equal "#{user.firstname} #{user.lastname};7,30;7,30", lines[1]
-      assert_equal "#{s2};7,30;7,30", lines[2]
-
-      str_fr = "Fran\xc3\xa7ais"
-      if str_fr.respond_to?(:force_encoding)
-        str_fr.force_encoding('UTF-8')
-      end
-      assert_equal str_fr, l(:general_lang_name)
-      assert_equal 'ISO-8859-1', l(:general_csv_encoding)
-      assert_equal ';', l(:general_csv_separator)
-      assert_equal ',', l(:general_csv_decimal_separator)
-    end
-  end
-end
--- a/.svn/pristine/2e/2e0a51818d267797dffec1a0e20aa3a664a20e28.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::EnumerationsTest < Redmine::ApiTest::Base
-  fixtures :enumerations
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /enumerations/issue_priorities.xml should return priorities" do
-    get '/enumerations/issue_priorities.xml'
-    assert_response :success
-    assert_equal 'application/xml', response.content_type
-    assert_select 'issue_priorities[type=array]' do
-      assert_select 'issue_priority' do
-        assert_select 'id', :text => '6'
-        assert_select 'name', :text => 'High'
-      end
-    end
-  end
-end
--- a/.svn/pristine/2e/2e26af3877bdd2fe792449a4fd743a6ba7463f7e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class PreviewsController < ApplicationController
-  before_filter :find_project, :find_attachments
-
-  def issue
-    @issue = @project.issues.find_by_id(params[:id]) unless params[:id].blank?
-    if @issue
-      @description = params[:issue] && params[:issue][:description]
-      if @description && @description.gsub(/(\r?\n|\n\r?)/, "\n") == @issue.description.to_s.gsub(/(\r?\n|\n\r?)/, "\n")
-        @description = nil
-      end
-      # params[:notes] is useful for preview of notes in issue history
-      @notes = params[:notes] || (params[:issue] ? params[:issue][:notes] : nil)
-    else
-      @description = (params[:issue] ? params[:issue][:description] : nil)
-    end
-    render :layout => false
-  end
-
-  def news
-    if params[:id].present? && news = News.visible.find_by_id(params[:id])
-      @previewed = news
-    end
-    @text = (params[:news] ? params[:news][:description] : nil)
-    render :partial => 'common/preview'
-  end
-
-  private
-
-  def find_project
-    project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
-    @project = Project.find(project_id)
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-end
--- a/.svn/pristine/2e/2e330182b29b2891c9c2bca0816fa09b38e7c57b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::Hook::ManagerTest < ActionView::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles,
-           :groups_users,
-           :trackers, :projects_trackers,
-           :enabled_modules,
-           :versions,
-           :issue_statuses, :issue_categories, :issue_relations,
-           :enumerations,
-           :issues
-
-  # Some hooks that are manually registered in these tests
-  class TestHook < Redmine::Hook::ViewListener; end
-
-  class TestHook1 < TestHook
-    def view_layouts_base_html_head(context)
-      'Test hook 1 listener.'
-    end
-  end
-
-  class TestHook2 < TestHook
-    def view_layouts_base_html_head(context)
-      'Test hook 2 listener.'
-    end
-  end
-
-  class TestHook3 < TestHook
-    def view_layouts_base_html_head(context)
-      "Context keys: #{context.keys.collect(&:to_s).sort.join(', ')}."
-    end
-  end
-
-  class TestLinkToHook < TestHook
-    def view_layouts_base_html_head(context)
-      link_to('Issues', :controller => 'issues')
-    end
-  end
-
-  class TestHookHelperController < ActionController::Base
-    include Redmine::Hook::Helper
-  end
-
-  class TestHookHelperView < ActionView::Base
-    include Redmine::Hook::Helper
-  end
-
-  Redmine::Hook.clear_listeners
-
-  def setup
-    @hook_module = Redmine::Hook
-  end
-
-  def teardown
-    @hook_module.clear_listeners
-  end
-
-  def test_clear_listeners
-    assert_equal 0, @hook_module.hook_listeners(:view_layouts_base_html_head).size
-    @hook_module.add_listener(TestHook1)
-    @hook_module.add_listener(TestHook2)
-    assert_equal 2, @hook_module.hook_listeners(:view_layouts_base_html_head).size
-
-    @hook_module.clear_listeners
-    assert_equal 0, @hook_module.hook_listeners(:view_layouts_base_html_head).size
-  end
-
-  def test_add_listener
-    assert_equal 0, @hook_module.hook_listeners(:view_layouts_base_html_head).size
-    @hook_module.add_listener(TestHook1)
-    assert_equal 1, @hook_module.hook_listeners(:view_layouts_base_html_head).size
-  end
-
-  def test_call_hook
-    @hook_module.add_listener(TestHook1)
-    assert_equal ['Test hook 1 listener.'], hook_helper.call_hook(:view_layouts_base_html_head)
-  end
-
-  def test_call_hook_with_context
-    @hook_module.add_listener(TestHook3)
-    assert_equal ['Context keys: bar, controller, foo, hook_caller, project, request.'],
-                 hook_helper.call_hook(:view_layouts_base_html_head, :foo => 1, :bar => 'a')
-  end
-
-  def test_call_hook_with_multiple_listeners
-    @hook_module.add_listener(TestHook1)
-    @hook_module.add_listener(TestHook2)
-    assert_equal ['Test hook 1 listener.', 'Test hook 2 listener.'], hook_helper.call_hook(:view_layouts_base_html_head)
-  end
-
-  # Context: Redmine::Hook::Helper.call_hook default_url
-  def test_call_hook_default_url_options
-    @hook_module.add_listener(TestLinkToHook)
-
-    assert_equal ['<a href="/issues">Issues</a>'], hook_helper.call_hook(:view_layouts_base_html_head)
-  end
-
-  # Context: Redmine::Hook::Helper.call_hook
-  def test_call_hook_with_project_added_to_context
-    @hook_module.add_listener(TestHook3)
-    assert_match /project/i, hook_helper.call_hook(:view_layouts_base_html_head)[0]
-  end
-
-  def test_call_hook_from_controller_with_controller_added_to_context
-    @hook_module.add_listener(TestHook3)
-    assert_match /controller/i, hook_helper.call_hook(:view_layouts_base_html_head)[0]
-  end
-
-  def test_call_hook_from_controller_with_request_added_to_context
-    @hook_module.add_listener(TestHook3)
-    assert_match /request/i, hook_helper.call_hook(:view_layouts_base_html_head)[0]
-  end
-
-  def test_call_hook_from_view_with_project_added_to_context
-    @hook_module.add_listener(TestHook3)
-    assert_match /project/i, view_hook_helper.call_hook(:view_layouts_base_html_head)
-  end
-
-  def test_call_hook_from_view_with_controller_added_to_context
-    @hook_module.add_listener(TestHook3)
-    assert_match /controller/i, view_hook_helper.call_hook(:view_layouts_base_html_head)
-  end
-
-  def test_call_hook_from_view_with_request_added_to_context
-    @hook_module.add_listener(TestHook3)
-    assert_match /request/i, view_hook_helper.call_hook(:view_layouts_base_html_head)
-  end
-
-  def test_call_hook_from_view_should_join_responses_with_a_space
-    @hook_module.add_listener(TestHook1)
-    @hook_module.add_listener(TestHook2)
-    assert_equal 'Test hook 1 listener. Test hook 2 listener.',
-                 view_hook_helper.call_hook(:view_layouts_base_html_head)
-  end
-
-  def test_call_hook_should_not_change_the_default_url_for_email_notifications
-    issue = Issue.find(1)
-
-    ActionMailer::Base.deliveries.clear
-    Mailer.deliver_issue_add(issue)
-    mail = ActionMailer::Base.deliveries.last
-
-    @hook_module.add_listener(TestLinkToHook)
-    hook_helper.call_hook(:view_layouts_base_html_head)
-
-    ActionMailer::Base.deliveries.clear
-    Mailer.deliver_issue_add(issue)
-    mail2 = ActionMailer::Base.deliveries.last
-
-    assert_equal mail_body(mail), mail_body(mail2)
-  end
-
-  def hook_helper
-    @hook_helper ||= TestHookHelperController.new
-  end
-
-  def view_hook_helper
-    @view_hook_helper ||= TestHookHelperView.new(Rails.root.to_s + '/app/views')
-  end
-end
-
--- a/.svn/pristine/2e/2e9778d3950cea9aad42938a07deac546bf3beda.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class ThemesTest < ActionController::IntegrationTest
-
-  def setup
-    @theme = Redmine::Themes.themes.last
-    Setting.ui_theme = @theme.id
-  end
-
-  def teardown
-    Setting.ui_theme = ''
-  end
-
-  def test_application_css
-    get '/'
-
-    assert_response :success
-    assert_tag :tag => 'link',
-      :attributes => {:href => %r{^/themes/#{@theme.dir}/stylesheets/application.css}}
-  end
-
-  def test_without_theme_js
-    get '/'
-
-    assert_response :success
-    assert_no_tag :tag => 'script',
-      :attributes => {:src => %r{^/themes/#{@theme.dir}/javascripts/theme.js}}
-  end
-
-  def test_with_theme_js
-    # Simulates a theme.js
-    @theme.javascripts << 'theme'
-    get '/'
-
-    assert_response :success
-    assert_tag :tag => 'script',
-      :attributes => {:src => %r{^/themes/#{@theme.dir}/javascripts/theme.js}}
-
-  ensure
-    @theme.javascripts.delete 'theme'
-  end
-
-  def test_with_sub_uri
-    Redmine::Utils.relative_url_root = '/foo'
-    @theme.javascripts << 'theme'
-    get '/'
-
-    assert_response :success
-    assert_tag :tag => 'link',
-      :attributes => {:href => %r{^/foo/themes/#{@theme.dir}/stylesheets/application.css}}
-    assert_tag :tag => 'script',
-      :attributes => {:src => %r{^/foo/themes/#{@theme.dir}/javascripts/theme.js}}
-
-  ensure
-    Redmine::Utils.relative_url_root = ''
-  end
-end
--- a/.svn/pristine/2e/2edea84d520ab6a5b95483c3c5399a71bdf3d4fa.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,221 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class JournalTest < ActiveSupport::TestCase
-  fixtures :projects, :issues, :issue_statuses, :journals, :journal_details,
-           :users, :members, :member_roles, :roles, :enabled_modules,
-           :projects_trackers, :trackers
-
-  def setup
-    @journal = Journal.find 1
-  end
-
-  def test_journalized_is_an_issue
-    issue = @journal.issue
-    assert_kind_of Issue, issue
-    assert_equal 1, issue.id
-  end
-
-  def test_new_status
-    status = @journal.new_status
-    assert_not_nil status
-    assert_kind_of IssueStatus, status
-    assert_equal 2, status.id
-  end
-
-  def test_create_should_send_email_notification
-    ActionMailer::Base.deliveries.clear
-    issue = Issue.first
-    user = User.first
-    journal = issue.init_journal(user, issue)
-
-    assert journal.save
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_should_not_save_journal_with_blank_notes_and_no_details
-    journal = Journal.new(:journalized => Issue.first, :user => User.first)
-
-    assert_no_difference 'Journal.count' do
-      assert_equal false, journal.save
-    end
-  end
-
-  def test_create_should_not_split_non_private_notes
-    assert_difference 'Journal.count' do
-      assert_no_difference 'JournalDetail.count' do
-        journal = Journal.generate!(:notes => 'Notes')
-      end
-    end
-
-    assert_difference 'Journal.count' do
-      assert_difference 'JournalDetail.count' do
-        journal = Journal.generate!(:notes => 'Notes', :details => [JournalDetail.new])
-      end
-    end
-
-    assert_difference 'Journal.count' do
-      assert_difference 'JournalDetail.count' do
-        journal = Journal.generate!(:notes => '', :details => [JournalDetail.new])
-      end
-    end
-  end
-
-  def test_create_should_split_private_notes
-    assert_difference 'Journal.count' do
-      assert_no_difference 'JournalDetail.count' do
-        journal = Journal.generate!(:notes => 'Notes', :private_notes => true)
-        journal.reload
-        assert_equal true, journal.private_notes
-        assert_equal 'Notes', journal.notes
-      end
-    end
-
-    assert_difference 'Journal.count', 2 do
-      assert_difference 'JournalDetail.count' do
-        journal = Journal.generate!(:notes => 'Notes', :private_notes => true, :details => [JournalDetail.new])
-        journal.reload
-        assert_equal true, journal.private_notes
-        assert_equal 'Notes', journal.notes
-        assert_equal 0, journal.details.size
-
-        journal_with_changes = Journal.order('id DESC').offset(1).first
-        assert_equal false, journal_with_changes.private_notes
-        assert_nil journal_with_changes.notes
-        assert_equal 1, journal_with_changes.details.size
-        assert_equal journal.created_on, journal_with_changes.created_on
-      end
-    end
-
-    assert_difference 'Journal.count' do
-      assert_difference 'JournalDetail.count' do
-        journal = Journal.generate!(:notes => '', :private_notes => true, :details => [JournalDetail.new])
-        journal.reload
-        assert_equal false, journal.private_notes
-        assert_equal '', journal.notes
-        assert_equal 1, journal.details.size
-      end
-    end
-  end
-
-  def test_visible_scope_for_anonymous
-    # Anonymous user should see issues of public projects only
-    journals = Journal.visible(User.anonymous).all
-    assert journals.any?
-    assert_nil journals.detect {|journal| !journal.issue.project.is_public?}
-    # Anonymous user should not see issues without permission
-    Role.anonymous.remove_permission!(:view_issues)
-    journals = Journal.visible(User.anonymous).all
-    assert journals.empty?
-  end
-
-  def test_visible_scope_for_user
-    user = User.find(9)
-    assert user.projects.empty?
-    # Non member user should see issues of public projects only
-    journals = Journal.visible(user).all
-    assert journals.any?
-    assert_nil journals.detect {|journal| !journal.issue.project.is_public?}
-    # Non member user should not see issues without permission
-    Role.non_member.remove_permission!(:view_issues)
-    user.reload
-    journals = Journal.visible(user).all
-    assert journals.empty?
-    # User should see issues of projects for which user has view_issues permissions only
-    Member.create!(:principal => user, :project_id => 1, :role_ids => [1])
-    user.reload
-    journals = Journal.visible(user).all
-    assert journals.any?
-    assert_nil journals.detect {|journal| journal.issue.project_id != 1}
-  end
-
-  def test_visible_scope_for_admin
-    user = User.find(1)
-    user.members.each(&:destroy)
-    assert user.projects.empty?
-    journals = Journal.visible(user).all
-    assert journals.any?
-    # Admin should see issues on private projects that admin does not belong to
-    assert journals.detect {|journal| !journal.issue.project.is_public?}
-  end
-
-  def test_preload_journals_details_custom_fields_should_set_custom_field_instance_variable
-    d = JournalDetail.new(:property => 'cf', :prop_key => '2')
-    journals = [Journal.new(:details => [d])]
-
-    d.expects(:instance_variable_set).with("@custom_field", CustomField.find(2)).once
-    Journal.preload_journals_details_custom_fields(journals)
-  end
-
-  def test_preload_journals_details_custom_fields_with_empty_set
-    assert_nothing_raised do
-      Journal.preload_journals_details_custom_fields([])
-    end
-  end
-
-  def test_details_should_normalize_dates
-    j = JournalDetail.create!(:old_value => Date.parse('2012-11-03'), :value => Date.parse('2013-01-02'))
-    j.reload
-    assert_equal '2012-11-03', j.old_value
-    assert_equal '2013-01-02', j.value
-  end
-
-  def test_details_should_normalize_true_values
-    j = JournalDetail.create!(:old_value => true, :value => true)
-    j.reload
-    assert_equal '1', j.old_value
-    assert_equal '1', j.value
-  end
-
-  def test_details_should_normalize_false_values
-    j = JournalDetail.create!(:old_value => false, :value => false)
-    j.reload
-    assert_equal '0', j.old_value
-    assert_equal '0', j.value
-  end
-
-  def test_custom_field_should_return_custom_field_for_cf_detail
-    d = JournalDetail.new(:property => 'cf', :prop_key => '2')
-    assert_equal CustomField.find(2), d.custom_field
-  end
-
-  def test_custom_field_should_return_nil_for_non_cf_detail
-    d = JournalDetail.new(:property => 'subject')
-    assert_equal nil, d.custom_field
-  end
-
-  def test_visible_details_should_include_relations_to_visible_issues_only
-    issue = Issue.generate!
-    visible_issue = Issue.generate!
-    IssueRelation.create!(:issue_from => issue, :issue_to => visible_issue, :relation_type => 'relates')
-    hidden_issue = Issue.generate!(:is_private => true)
-    IssueRelation.create!(:issue_from => issue, :issue_to => hidden_issue, :relation_type => 'relates')
-    issue.reload
-    assert_equal 1, issue.journals.size
-    journal = issue.journals.first
-    assert_equal 2, journal.details.size
-
-    visible_details = journal.visible_details(User.anonymous)
-    assert_equal 1, visible_details.size
-    assert_equal visible_issue.id.to_s, visible_details.first.value
-
-    visible_details = journal.visible_details(User.find(2))
-    assert_equal 2, visible_details.size
-  end
-end
--- a/.svn/pristine/2f/2f133168a880fffbd35ca248f3d226a5ea263cb4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class NewsTest < ActiveSupport::TestCase
-  fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :news
-
-  def valid_news
-    { :title => 'Test news', :description => 'Lorem ipsum etc', :author => User.first }
-  end
-
-  def setup
-  end
-
-  def test_create_should_send_email_notification
-    ActionMailer::Base.deliveries.clear
-    news = Project.find(1).news.new(valid_news)
-
-    with_settings :notified_events => %w(news_added) do
-      assert news.save
-    end
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_should_include_news_for_projects_with_news_enabled
-    project = projects(:projects_001)
-    assert project.enabled_modules.any?{ |em| em.name == 'news' }
-
-    # News.latest should return news from projects_001
-    assert News.latest.any? { |news| news.project == project }
-  end
-
-  def test_should_not_include_news_for_projects_with_news_disabled
-    EnabledModule.delete_all(["project_id = ? AND name = ?", 2, 'news'])
-    project = Project.find(2)
-
-    # Add a piece of news to the project
-    news = project.news.create(valid_news)
-
-    # News.latest should not return that new piece of news
-    assert News.latest.include?(news) == false
-  end
-
-  def test_should_only_include_news_from_projects_visibly_to_the_user
-    assert News.latest(User.anonymous).all? { |news| news.project.is_public? }
-  end
-
-  def test_should_limit_the_amount_of_returned_news
-    # Make sure we have a bunch of news stories
-    10.times { projects(:projects_001).news.create(valid_news) }
-    assert_equal 2, News.latest(users(:users_002), 2).size
-    assert_equal 6, News.latest(users(:users_002), 6).size
-  end
-
-  def test_should_return_5_news_stories_by_default
-    # Make sure we have a bunch of news stories
-    10.times { projects(:projects_001).news.create(valid_news) }
-    assert_equal 5, News.latest(users(:users_004)).size
-  end
-
-  def test_attachments_should_be_visible
-    assert News.find(1).attachments_visible?(User.anonymous)
-  end
-
-  def test_attachments_should_be_deletable_with_manage_news_permission
-    manager = User.find(2)
-    assert News.find(1).attachments_deletable?(manager)
-  end
-
-  def test_attachments_should_not_be_deletable_without_manage_news_permission
-    manager = User.find(2)
-    Role.find_by_name('Manager').remove_permission!(:manage_news)
-    assert !News.find(1).attachments_deletable?(manager)
-  end
-end
--- a/.svn/pristine/30/301185c13f555c3833de6896f8f45895314d605b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingCommentsTest < ActionController::IntegrationTest
-  def test_comments
-    assert_routing(
-        { :method => 'post', :path => "/news/567/comments" },
-        { :controller => 'comments', :action => 'create', :id => '567' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/news/567/comments/15" },
-        { :controller => 'comments', :action => 'destroy', :id => '567',
-          :comment_id => '15' }
-      )
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/30/3027fca91424b88657f6c91d9b6b5ddfc109c616.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,37 @@
+require 'rexml/document'
+
+module Redmine
+  module VERSION #:nodoc:
+    MAJOR = 2
+    MINOR = 4
+    TINY  = 6
+
+    # Branch values:
+    # * official release: nil
+    # * stable branch:    stable
+    # * trunk:            devel
+    BRANCH = 'stable'
+
+    # Retrieves the revision from the working copy
+    def self.revision
+      if File.directory?(File.join(Rails.root, '.svn'))
+        begin
+          path = Redmine::Scm::Adapters::AbstractAdapter.shell_quote(Rails.root.to_s)
+          if `svn info --xml #{path}` =~ /revision="(\d+)"/
+            return $1.to_i
+          end
+        rescue
+          # Could not find the current revision
+        end
+      end
+      nil
+    end
+
+    REVISION = self.revision
+    ARRAY    = [MAJOR, MINOR, TINY, BRANCH, REVISION].compact
+    STRING   = ARRAY.join('.')
+
+    def self.to_a; ARRAY  end
+    def self.to_s; STRING end
+  end
+end
--- a/.svn/pristine/30/30802f3b65425b8bb22f7cebacbf8ac4352f1e79.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,841 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class Redmine::Helpers::GanttHelperTest < ActionView::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :journals, :journal_details,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :versions,
-           :groups_users
-
-  include ApplicationHelper
-  include ProjectsHelper
-  include IssuesHelper
-  include ERB::Util
-  include Rails.application.routes.url_helpers
-
-  def setup
-    setup_with_controller
-    User.current = User.find(1)
-  end
-
-  def today
-    @today ||= Date.today
-  end
-
-  # Creates a Gantt chart for a 4 week span
-  def create_gantt(project=Project.generate!, options={})
-    @project = project
-    @gantt = Redmine::Helpers::Gantt.new(options)
-    @gantt.project = @project
-    @gantt.query = IssueQuery.create!(:project => @project, :name => 'Gantt')
-    @gantt.view = self
-    @gantt.instance_variable_set('@date_from', options[:date_from] || (today - 14))
-    @gantt.instance_variable_set('@date_to', options[:date_to] || (today + 14))
-  end
-
-  context "#number_of_rows" do
-    context "with one project" do
-      should "return the number of rows just for that project" do
-        p1, p2 = Project.generate!, Project.generate!
-        i1, i2 = Issue.generate!(:project => p1), Issue.generate!(:project => p2)
-        create_gantt(p1)
-        assert_equal 2, @gantt.number_of_rows
-      end
-    end
-
-    context "with no project" do
-      should "return the total number of rows for all the projects, resursively" do
-        p1, p2 = Project.generate!, Project.generate!
-        create_gantt(nil)
-        #fix the return value of #number_of_rows_on_project() to an arbitrary value
-        #so that we really only test #number_of_rows
-        @gantt.stubs(:number_of_rows_on_project).returns(7)
-        #also fix #projects because we want to test #number_of_rows in isolation
-        @gantt.stubs(:projects).returns(Project.all)
-        #actual test
-        assert_equal Project.count*7, @gantt.number_of_rows
-      end
-    end
-
-    should "not exceed max_rows option" do
-      p = Project.generate!
-      5.times do
-        Issue.generate!(:project => p)
-      end
-      create_gantt(p)
-      @gantt.render
-      assert_equal 6, @gantt.number_of_rows
-      assert !@gantt.truncated
-      create_gantt(p, :max_rows => 3)
-      @gantt.render
-      assert_equal 3, @gantt.number_of_rows
-      assert @gantt.truncated
-    end
-  end
-
-  context "#number_of_rows_on_project" do
-    setup do
-      create_gantt
-    end
-
-    should "count 0 for an empty the project" do
-      assert_equal 0, @gantt.number_of_rows_on_project(@project)
-    end
-
-    should "count the number of issues without a version" do
-      @project.issues << Issue.generate!(:project => @project, :fixed_version => nil)
-      assert_equal 2, @gantt.number_of_rows_on_project(@project)
-    end
-
-    should "count the number of issues on versions, including cross-project" do
-      version = Version.generate!
-      @project.versions << version
-      @project.issues << Issue.generate!(:project => @project, :fixed_version => version)
-      assert_equal 3, @gantt.number_of_rows_on_project(@project)
-    end
-  end
-
-  # TODO: more of an integration test
-  context "#subjects" do
-    setup do
-      create_gantt
-      @project.enabled_module_names = [:issue_tracking]
-      @tracker = Tracker.generate!
-      @project.trackers << @tracker
-      @version = Version.generate!(:effective_date => (today + 7), :sharing => 'none')
-      @project.versions << @version
-      @issue = Issue.generate!(:fixed_version => @version,
-                               :subject => "gantt#line_for_project",
-                               :tracker => @tracker,
-                               :project => @project,
-                               :done_ratio => 30,
-                               :start_date => (today - 1),
-                               :due_date => (today + 7))
-      @project.issues << @issue
-    end
-
-    context "project" do
-      should "be rendered" do
-        @output_buffer = @gantt.subjects
-        assert_select "div.project-name a", /#{@project.name}/
-      end
-
-      should "have an indent of 4" do
-        @output_buffer = @gantt.subjects
-        assert_select "div.project-name[style*=left:4px]"
-      end
-    end
-
-    context "version" do
-      should "be rendered" do
-        @output_buffer = @gantt.subjects
-        assert_select "div.version-name a", /#{@version.name}/
-      end
-
-      should "be indented 24 (one level)" do
-        @output_buffer = @gantt.subjects
-        assert_select "div.version-name[style*=left:24px]"
-      end
-
-      context "without assigned issues" do
-        setup do
-          @version = Version.generate!(:effective_date => (today + 14),
-                                       :sharing => 'none',
-                                       :name => 'empty_version')
-          @project.versions << @version
-        end
-
-        should "not be rendered" do
-          @output_buffer = @gantt.subjects
-          assert_select "div.version-name a", :text => /#{@version.name}/, :count => 0
-        end
-      end
-    end
-
-    context "issue" do
-      should "be rendered" do
-        @output_buffer = @gantt.subjects
-        assert_select "div.issue-subject", /#{@issue.subject}/
-      end
-
-      should "be indented 44 (two levels)" do
-        @output_buffer = @gantt.subjects
-        assert_select "div.issue-subject[style*=left:44px]"
-      end
-
-      context "assigned to a shared version of another project" do
-        setup do
-          p = Project.generate!
-          p.enabled_module_names = [:issue_tracking]
-          @shared_version = Version.generate!(:sharing => 'system')
-          p.versions << @shared_version
-          # Reassign the issue to a shared version of another project
-          @issue = Issue.generate!(:fixed_version => @shared_version,
-                                   :subject => "gantt#assigned_to_shared_version",
-                                   :tracker => @tracker,
-                                   :project => @project,
-                                   :done_ratio => 30,
-                                   :start_date => (today - 1),
-                                   :due_date => (today + 7))
-          @project.issues << @issue
-        end
-
-        should "be rendered" do
-          @output_buffer = @gantt.subjects
-          assert_select "div.issue-subject", /#{@issue.subject}/
-        end
-      end
-
-      context "with subtasks" do
-        setup do
-          attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version}
-          @child1 = Issue.generate!(
-                       attrs.merge(:subject => 'child1',
-                                   :parent_issue_id => @issue.id,
-                                   :start_date => (today - 1),
-                                   :due_date => (today + 2))
-                      )
-          @child2 = Issue.generate!(
-                       attrs.merge(:subject => 'child2',
-                                   :parent_issue_id => @issue.id,
-                                   :start_date => today,
-                                   :due_date => (today + 7))
-                       )
-          @grandchild = Issue.generate!(
-                          attrs.merge(:subject => 'grandchild',
-                                      :parent_issue_id => @child1.id,
-                                      :start_date => (today - 1),
-                                      :due_date => (today + 2))
-                          )
-        end
-
-        should "indent subtasks" do
-          @output_buffer = @gantt.subjects
-          # parent task 44px
-          assert_select "div.issue-subject[style*=left:44px]", /#{@issue.subject}/
-          # children 64px
-          assert_select "div.issue-subject[style*=left:64px]", /child1/
-          assert_select "div.issue-subject[style*=left:64px]", /child2/
-          # grandchild 84px
-          assert_select "div.issue-subject[style*=left:84px]", /grandchild/, @output_buffer
-        end
-      end
-    end
-  end
-
-  context "#lines" do
-    setup do
-      create_gantt
-      @project.enabled_module_names = [:issue_tracking]
-      @tracker = Tracker.generate!
-      @project.trackers << @tracker
-      @version = Version.generate!(:effective_date => (today + 7))
-      @project.versions << @version
-      @issue = Issue.generate!(:fixed_version => @version,
-                               :subject => "gantt#line_for_project",
-                               :tracker => @tracker,
-                               :project => @project,
-                               :done_ratio => 30,
-                               :start_date => (today - 1),
-                               :due_date => (today + 7))
-      @project.issues << @issue
-      @output_buffer = @gantt.lines
-    end
-
-    context "project" do
-      should "be rendered" do
-        assert_select "div.project.task_todo"
-        assert_select "div.project.starting"
-        assert_select "div.project.ending"
-        assert_select "div.label.project", /#{@project.name}/
-      end
-    end
-
-    context "version" do
-      should "be rendered" do
-        assert_select "div.version.task_todo"
-        assert_select "div.version.starting"
-        assert_select "div.version.ending"
-        assert_select "div.label.version", /#{@version.name}/
-      end
-    end
-
-    context "issue" do
-      should "be rendered" do
-        assert_select "div.task_todo"
-        assert_select "div.task.label", /#{@issue.done_ratio}/
-        assert_select "div.tooltip", /#{@issue.subject}/
-      end
-    end
-  end
-
-  context "#render_project" do
-    should "be tested"
-  end
-
-  context "#render_issues" do
-    should "be tested"
-  end
-
-  context "#render_version" do
-    should "be tested"
-  end
-
-  context "#subject_for_project" do
-    setup do
-      create_gantt
-    end
-
-    context ":html format" do
-      should "add an absolute positioned div" do
-        @output_buffer = @gantt.subject_for_project(@project, {:format => :html})
-        assert_select "div[style*=absolute]"
-      end
-
-      should "use the indent option to move the div to the right" do
-        @output_buffer = @gantt.subject_for_project(@project, {:format => :html, :indent => 40})
-        assert_select "div[style*=left:40]"
-      end
-
-      should "include the project name" do
-        @output_buffer = @gantt.subject_for_project(@project, {:format => :html})
-        assert_select 'div', :text => /#{@project.name}/
-      end
-
-      should "include a link to the project" do
-        @output_buffer = @gantt.subject_for_project(@project, {:format => :html})
-        assert_select 'a[href=?]', "/projects/#{@project.identifier}", :text => /#{@project.name}/
-      end
-
-      should "style overdue projects" do
-        @project.enabled_module_names = [:issue_tracking]
-        @project.versions << Version.generate!(:effective_date => (today - 1))
-        assert @project.reload.overdue?, "Need an overdue project for this test"
-        @output_buffer = @gantt.subject_for_project(@project, {:format => :html})
-        assert_select 'div span.project-overdue'
-      end
-    end
-    should "test the PNG format"
-    should "test the PDF format"
-  end
-
-  context "#line_for_project" do
-    setup do
-      create_gantt
-      @project.enabled_module_names = [:issue_tracking]
-      @tracker = Tracker.generate!
-      @project.trackers << @tracker
-      @version = Version.generate!(:effective_date => (today - 1))
-      @project.versions << @version
-      @project.issues << Issue.generate!(:fixed_version => @version,
-                                         :subject => "gantt#line_for_project",
-                                         :tracker => @tracker,
-                                         :project => @project,
-                                         :done_ratio => 30,
-                                         :start_date => (today - 7),
-                                         :due_date => (today + 7))
-    end
-
-    context ":html format" do
-      context "todo line" do
-        should "start from the starting point on the left" do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.task_todo[style*=left:28px]", true, @output_buffer
-        end
-
-        should "be the total width of the project" do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.task_todo[style*=width:58px]", true, @output_buffer
-        end
-      end
-
-      context "late line" do
-        should_eventually "start from the starting point on the left" do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.task_late[style*=left:28px]", true, @output_buffer
-        end
-
-        should_eventually "be the total delayed width of the project" do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.task_late[style*=width:30px]", true, @output_buffer
-        end
-      end
-
-      context "done line" do
-        should_eventually "start from the starting point on the left" do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.task_done[style*=left:28px]", true, @output_buffer
-        end
-
-        should_eventually "Be the total done width of the project"  do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.task_done[style*=width:18px]", true, @output_buffer
-        end
-      end
-
-      context "starting marker" do
-        should "not appear if the starting point is off the gantt chart" do
-          # Shift the date range of the chart
-          @gantt.instance_variable_set('@date_from', today)
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.starting", false, @output_buffer
-        end
-
-        should "appear at the starting point" do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.starting[style*=left:28px]", true, @output_buffer
-        end
-      end
-
-      context "ending marker" do
-        should "not appear if the starting point is off the gantt chart" do
-          # Shift the date range of the chart
-          @gantt.instance_variable_set('@date_to', (today - 14))
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.ending", false, @output_buffer
-        end
-
-        should "appear at the end of the date range" do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.ending[style*=left:88px]", true, @output_buffer
-        end
-      end
-
-      context "status content" do
-        should "appear at the far left, even if it's far in the past" do
-          @gantt.instance_variable_set('@date_to', (today - 14))
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.label", /#{@project.name}/
-        end
-
-        should "show the project name" do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.label", /#{@project.name}/
-        end
-
-        should_eventually "show the percent complete" do
-          @output_buffer = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
-          assert_select "div.project.label", /0%/
-        end
-      end
-    end
-    should "test the PNG format"
-    should "test the PDF format"
-  end
-
-  context "#subject_for_version" do
-    setup do
-      create_gantt
-      @project.enabled_module_names = [:issue_tracking]
-      @tracker = Tracker.generate!
-      @project.trackers << @tracker
-      @version = Version.generate!(:effective_date => (today - 1))
-      @project.versions << @version
-      @project.issues << Issue.generate!(:fixed_version => @version,
-                                         :subject => "gantt#subject_for_version",
-                                         :tracker => @tracker,
-                                         :project => @project,
-                                         :start_date => today)
-
-    end
-
-    context ":html format" do
-      should "add an absolute positioned div" do
-        @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
-        assert_select "div[style*=absolute]"
-      end
-
-      should "use the indent option to move the div to the right" do
-        @output_buffer = @gantt.subject_for_version(@version, {:format => :html, :indent => 40})
-        assert_select "div[style*=left:40]"
-      end
-
-      should "include the version name" do
-        @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
-        assert_select 'div', :text => /#{@version.name}/
-      end
-
-      should "include a link to the version" do
-        @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
-        assert_select 'a[href=?]', Regexp.escape("/versions/#{@version.to_param}"), :text => /#{@version.name}/
-      end
-
-      should "style late versions" do
-        assert @version.overdue?, "Need an overdue version for this test"
-        @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
-        assert_select 'div span.version-behind-schedule'
-      end
-
-      should "style behind schedule versions" do
-        assert @version.behind_schedule?, "Need a behind schedule version for this test"
-        @output_buffer = @gantt.subject_for_version(@version, {:format => :html})
-        assert_select 'div span.version-behind-schedule'
-      end
-    end
-    should "test the PNG format"
-    should "test the PDF format"
-  end
-
-  context "#line_for_version" do
-    setup do
-      create_gantt
-      @project.enabled_module_names = [:issue_tracking]
-      @tracker = Tracker.generate!
-      @project.trackers << @tracker
-      @version = Version.generate!(:effective_date => (today + 7))
-      @project.versions << @version
-      @project.issues << Issue.generate!(:fixed_version => @version,
-                                         :subject => "gantt#line_for_project",
-                                         :tracker => @tracker,
-                                         :project => @project,
-                                         :done_ratio => 30,
-                                         :start_date => (today - 7),
-                                         :due_date => (today + 7))
-    end
-
-    context ":html format" do
-      context "todo line" do
-        should "start from the starting point on the left" do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.task_todo[style*=left:28px]", true, @output_buffer
-        end
-
-        should "be the total width of the version" do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.task_todo[style*=width:58px]", true, @output_buffer
-        end
-      end
-
-      context "late line" do
-        should "start from the starting point on the left" do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.task_late[style*=left:28px]", true, @output_buffer
-        end
-
-        should "be the total delayed width of the version" do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.task_late[style*=width:30px]", true, @output_buffer
-        end
-      end
-
-      context "done line" do
-        should "start from the starting point on the left" do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.task_done[style*=left:28px]", true, @output_buffer
-        end
-
-        should "be the total done width of the version"  do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.task_done[style*=width:16px]", true, @output_buffer
-        end
-      end
-
-      context "starting marker" do
-        should "not appear if the starting point is off the gantt chart" do
-          # Shift the date range of the chart
-          @gantt.instance_variable_set('@date_from', today)
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.starting", false
-        end
-
-        should "appear at the starting point" do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.starting[style*=left:28px]", true, @output_buffer
-        end
-      end
-
-      context "ending marker" do
-        should "not appear if the starting point is off the gantt chart" do
-          # Shift the date range of the chart
-          @gantt.instance_variable_set('@date_to', (today - 14))
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.ending", false
-        end
-
-        should "appear at the end of the date range" do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.ending[style*=left:88px]", true, @output_buffer
-        end
-      end
-
-      context "status content" do
-        should "appear at the far left, even if it's far in the past" do
-          @gantt.instance_variable_set('@date_to', (today - 14))
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.label", /#{@version.name}/
-        end
-
-        should "show the version name" do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.label", /#{@version.name}/
-        end
-
-        should "show the percent complete" do
-          @output_buffer = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
-          assert_select "div.version.label", /30%/
-        end
-      end
-    end
-    should "test the PNG format"
-    should "test the PDF format"
-  end
-
-  context "#subject_for_issue" do
-    setup do
-      create_gantt
-      @project.enabled_module_names = [:issue_tracking]
-      @tracker = Tracker.generate!
-      @project.trackers << @tracker
-      @issue = Issue.generate!(:subject => "gantt#subject_for_issue",
-                               :tracker => @tracker,
-                               :project => @project,
-                               :start_date => (today - 3),
-                               :due_date => (today - 1))
-      @project.issues << @issue
-    end
-
-    context ":html format" do
-      should "add an absolute positioned div" do
-        @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html})
-        assert_select "div[style*=absolute]"
-      end
-
-      should "use the indent option to move the div to the right" do
-        @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html, :indent => 40})
-        assert_select "div[style*=left:40]"
-      end
-
-      should "include the issue subject" do
-        @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html})
-        assert_select 'div', :text => /#{@issue.subject}/
-      end
-
-      should "include a link to the issue" do
-        @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html})
-        assert_select 'a[href=?]', Regexp.escape("/issues/#{@issue.to_param}"), :text => /#{@tracker.name} ##{@issue.id}/
-      end
-
-      should "style overdue issues" do
-        assert @issue.overdue?, "Need an overdue issue for this test"
-        @output_buffer = @gantt.subject_for_issue(@issue, {:format => :html})
-        assert_select 'div span.issue-overdue'
-      end
-    end
-    should "test the PNG format"
-    should "test the PDF format"
-  end
-
-  context "#line_for_issue" do
-    setup do
-      create_gantt
-      @project.enabled_module_names = [:issue_tracking]
-      @tracker = Tracker.generate!
-      @project.trackers << @tracker
-      @version = Version.generate!(:effective_date => (today + 7))
-      @project.versions << @version
-      @issue = Issue.generate!(:fixed_version => @version,
-                               :subject => "gantt#line_for_project",
-                               :tracker => @tracker,
-                               :project => @project,
-                               :done_ratio => 30,
-                               :start_date => (today - 7),
-                               :due_date => (today + 7))
-      @project.issues << @issue
-    end
-
-    context ":html format" do
-      context "todo line" do
-        should "start from the starting point on the left" do
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          assert_select "div.task_todo[style*=left:28px]", true, @output_buffer
-        end
-
-        should "be the total width of the issue" do
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          assert_select "div.task_todo[style*=width:58px]", true, @output_buffer
-        end
-      end
-
-      context "late line" do
-        should "start from the starting point on the left" do
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          assert_select "div.task_late[style*=left:28px]", true, @output_buffer
-        end
-
-        should "be the total delayed width of the issue" do
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          assert_select "div.task_late[style*=width:30px]", true, @output_buffer
-        end
-      end
-
-      context "done line" do
-        should "start from the starting point on the left" do
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          assert_select "div.task_done[style*=left:28px]", true, @output_buffer
-        end
-
-        should "be the total done width of the issue"  do
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          # 15 days * 4 px * 30% - 2 px for borders = 16 px
-          assert_select "div.task_done[style*=width:16px]", true, @output_buffer
-        end
-
-        should "not be the total done width if the chart starts after issue start date"  do
-          create_gantt(@project, :date_from => (today - 5))
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          assert_select "div.task_done[style*=left:0px]", true, @output_buffer
-          assert_select "div.task_done[style*=width:8px]", true, @output_buffer
-        end
-
-        context "for completed issue" do
-          setup do
-            @issue.done_ratio = 100
-          end
-
-          should "be the total width of the issue"  do
-            @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-            assert_select "div.task_done[style*=width:58px]", true, @output_buffer
-          end
-
-          should "be the total width of the issue with due_date=start_date"  do
-            @issue.due_date = @issue.start_date
-            @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-            assert_select "div.task_done[style*=width:2px]", true, @output_buffer
-          end
-        end
-      end
-
-      context "status content" do
-        should "appear at the far left, even if it's far in the past" do
-          @gantt.instance_variable_set('@date_to', (today - 14))
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          assert_select "div.task.label", true, @output_buffer
-        end
-
-        should "show the issue status" do
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          assert_select "div.task.label", /#{@issue.status.name}/
-        end
-
-        should "show the percent complete" do
-          @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-          assert_select "div.task.label", /30%/
-        end
-      end
-    end
-
-    should "have an issue tooltip" do
-      @output_buffer = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
-      assert_select "div.tooltip", /#{@issue.subject}/
-    end
-    should "test the PNG format"
-    should "test the PDF format"
-  end
-
-  context "#to_image" do
-    should "be tested"
-  end
-
-  context "#to_pdf" do
-    should "be tested"
-  end
-
-  def test_sort_issues_no_date
-    project = Project.generate!
-    issue1 = Issue.generate!(:subject => "test", :project => project)
-    issue2 = Issue.generate!(:subject => "test", :project => project)
-    assert issue1.root_id < issue2.root_id
-    child1 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
-                             :project => project)
-    child2 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
-                             :project => project)
-    child3 = Issue.generate!(:parent_issue_id => child1.id, :subject => 'child',
-                             :project => project)
-    assert_equal child1.root_id, child2.root_id
-    assert child1.lft < child2.lft
-    assert child3.lft < child2.lft
-    issues = [child3, child2, child1, issue2, issue1]
-    Redmine::Helpers::Gantt.sort_issues!(issues)
-    assert_equal [issue1.id, child1.id, child3.id, child2.id, issue2.id],
-                  issues.map{|v| v.id}
-  end
-
-  def test_sort_issues_root_only
-    project = Project.generate!
-    issue1 = Issue.generate!(:subject => "test", :project => project)
-    issue2 = Issue.generate!(:subject => "test", :project => project)
-    issue3 = Issue.generate!(:subject => "test", :project => project,
-                             :start_date => (today - 1))
-    issue4 = Issue.generate!(:subject => "test", :project => project,
-                             :start_date => (today - 2))
-    issues = [issue4, issue3, issue2, issue1]
-    Redmine::Helpers::Gantt.sort_issues!(issues)
-    assert_equal [issue1.id, issue2.id, issue4.id, issue3.id],
-                  issues.map{|v| v.id}
-  end
-
-  def test_sort_issues_tree
-    project = Project.generate!
-    issue1 = Issue.generate!(:subject => "test", :project => project)
-    issue2 = Issue.generate!(:subject => "test", :project => project,
-                             :start_date => (today - 2))
-    issue1_child1 =
-             Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
-                             :project => project)
-    issue1_child2 =
-             Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
-                             :project => project, :start_date => (today - 10))
-    issue1_child1_child1 =
-             Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
-                             :project => project, :start_date => (today - 8))
-    issue1_child1_child2 =
-             Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
-                             :project => project, :start_date => (today - 9))
-    issue1_child1_child1_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child1)
-    assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
-                  [today - 8, issue1_child1_child1.id]],
-                 issue1_child1_child1_logic
-    issue1_child1_child2_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child2)
-    assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
-                  [today - 9, issue1_child1_child2.id]],
-                 issue1_child1_child2_logic
-    issues = [issue1_child1_child2, issue1_child1_child1, issue1_child2,
-              issue1_child1, issue2, issue1]
-    Redmine::Helpers::Gantt.sort_issues!(issues)
-    assert_equal [issue1.id, issue1_child1.id, issue1_child2.id,
-                  issue1_child1_child2.id, issue1_child1_child1.id, issue2.id],
-                 issues.map{|v| v.id}
-  end
-
-  def test_sort_versions
-    project = Project.generate!
-    version1 = Version.create!(:project => project, :name => 'test1')
-    version2 = Version.create!(:project => project, :name => 'test2', :effective_date => '2013-10-25')
-    version3 = Version.create!(:project => project, :name => 'test3')
-    version4 = Version.create!(:project => project, :name => 'test4', :effective_date => '2013-10-02')
-
-    assert_equal versions.sort, Redmine::Helpers::Gantt.sort_versions!(versions)
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/31/3190ee598f70a34c3d3f93dfd554a0ad83b8e462.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,637 @@
+# Redmine - project management software
+# Copyright (C) 2006-2014  Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'uri'
+require 'cgi'
+
+class Unauthorized < Exception; end
+
+class ApplicationController < ActionController::Base
+  include Redmine::I18n
+  include Redmine::Pagination
+  include RoutesHelper
+  helper :routes
+
+  class_attribute :accept_api_auth_actions
+  class_attribute :accept_rss_auth_actions
+  class_attribute :model_object
+
+  layout 'base'
+
+  protect_from_forgery
+
+  def verify_authenticity_token
+    unless api_request?
+      super
+    end
+  end
+
+  def handle_unverified_request
+    unless api_request?
+      super
+      cookies.delete(autologin_cookie_name)
+      self.logged_user = nil
+      render_error :status => 422, :message => "Invalid form authenticity token."
+    end
+  end
+
+  before_filter :session_expiration, :user_setup, :check_if_login_required, :check_password_change, :set_localization
+
+  rescue_from ::Unauthorized, :with => :deny_access
+  rescue_from ::ActionView::MissingTemplate, :with => :missing_template
+
+  include Redmine::Search::Controller
+  include Redmine::MenuManager::MenuController
+  helper Redmine::MenuManager::MenuHelper
+
+  def session_expiration
+    if session[:user_id]
+      if session_expired? && !try_to_autologin
+        reset_session
+        flash[:error] = l(:error_session_expired)
+        redirect_to signin_url
+      else
+        session[:atime] = Time.now.utc.to_i
+      end
+    end
+  end
+
+  def session_expired?
+    if Setting.session_lifetime?
+      unless session[:ctime] && (Time.now.utc.to_i - session[:ctime].to_i <= Setting.session_lifetime.to_i * 60)
+        return true
+      end
+    end
+    if Setting.session_timeout?
+      unless session[:atime] && (Time.now.utc.to_i - session[:atime].to_i <= Setting.session_timeout.to_i * 60)
+        return true
+      end
+    end
+    false
+  end
+
+  def start_user_session(user)
+    session[:user_id] = user.id
+    session[:ctime] = Time.now.utc.to_i
+    session[:atime] = Time.now.utc.to_i
+    if user.must_change_password?
+      session[:pwd] = '1'
+    end
+  end
+
+  def user_setup
+    # Check the settings cache for each request
+    Setting.check_cache
+    # Find the current user
+    User.current = find_current_user
+    logger.info("  Current user: " + (User.current.logged? ? "#{User.current.login} (id=#{User.current.id})" : "anonymous")) if logger
+  end
+
+  # Returns the current user or nil if no user is logged in
+  # and starts a session if needed
+  def find_current_user
+    user = nil
+    unless api_request?
+      if session[:user_id]
+        # existing session
+        user = (User.active.find(session[:user_id]) rescue nil)
+      elsif autologin_user = try_to_autologin
+        user = autologin_user
+      elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
+        # RSS key authentication does not start a session
+        user = User.find_by_rss_key(params[:key])
+      end
+    end
+    if user.nil? && Setting.rest_api_enabled? && accept_api_auth?
+      if (key = api_key_from_request)
+        # Use API key
+        user = User.find_by_api_key(key)
+      else
+        # HTTP Basic, either username/password or API key/random
+        authenticate_with_http_basic do |username, password|
+          user = User.try_to_login(username, password) || User.find_by_api_key(username)
+        end
+        if user && user.must_change_password?
+          render_error :message => 'You must change your password', :status => 403
+          return
+        end
+      end
+      # Switch user if requested by an admin user
+      if user && user.admin? && (username = api_switch_user_from_request)
+        su = User.find_by_login(username)
+        if su && su.active?
+          logger.info("  User switched by: #{user.login} (id=#{user.id})") if logger
+          user = su
+        else
+          render_error :message => 'Invalid X-Redmine-Switch-User header', :status => 412
+        end
+      end
+    end
+    user
+  end
+
+  def autologin_cookie_name
+    Redmine::Configuration['autologin_cookie_name'].presence || 'autologin'
+  end
+
+  def try_to_autologin
+    if cookies[autologin_cookie_name] && Setting.autologin?
+      # auto-login feature starts a new session
+      user = User.try_to_autologin(cookies[autologin_cookie_name])
+      if user
+        reset_session
+        start_user_session(user)
+      end
+      user
+    end
+  end
+
+  # Sets the logged in user
+  def logged_user=(user)
+    reset_session
+    if user && user.is_a?(User)
+      User.current = user
+      start_user_session(user)
+    else
+      User.current = User.anonymous
+    end
+  end
+
+  # Logs out current user
+  def logout_user
+    if User.current.logged?
+      cookies.delete(autologin_cookie_name)
+      Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin'])
+      self.logged_user = nil
+    end
+  end
+
+  # check if login is globally required to access the application
+  def check_if_login_required
+    # no check needed if user is already logged in
+    return true if User.current.logged?
+    require_login if Setting.login_required?
+  end
+
+  def check_password_change
+    if session[:pwd]
+      if User.current.must_change_password?
+        redirect_to my_password_path
+      else
+        session.delete(:pwd)
+      end
+    end
+  end
+
+  def set_localization
+    lang = nil
+    if User.current.logged?
+      lang = find_language(User.current.language)
+    end
+    if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
+      accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first
+      if !accept_lang.blank?
+        accept_lang = accept_lang.downcase
+        lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
+      end
+    end
+    lang ||= Setting.default_language
+    set_language_if_valid(lang)
+  end
+
+  def require_login
+    if !User.current.logged?
+      # Extract only the basic url parameters on non-GET requests
+      if request.get?
+        url = url_for(params)
+      else
+        url = url_for(:controller => params[:controller], :action => params[:action], :id => params[:id], :project_id => params[:project_id])
+      end
+      respond_to do |format|
+        format.html {
+          if request.xhr?
+            head :unauthorized
+          else
+            redirect_to :controller => "account", :action => "login", :back_url => url
+          end
+        }
+        format.atom { redirect_to :controller => "account", :action => "login", :back_url => url }
+        format.xml  { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
+        format.js   { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
+        format.json { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
+      end
+      return false
+    end
+    true
+  end
+
+  def require_admin
+    return unless require_login
+    if !User.current.admin?
+      render_403
+      return false
+    end
+    true
+  end
+
+  def deny_access
+    User.current.logged? ? render_403 : require_login
+  end
+
+  # Authorize the user for the requested action
+  def authorize(ctrl = params[:controller], action = params[:action], global = false)
+    allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global)
+    if allowed
+      true
+    else
+      if @project && @project.archived?
+        render_403 :message => :notice_not_authorized_archived_project
+      else
+        deny_access
+      end
+    end
+  end
+
+  # Authorize the user for the requested action outside a project
+  def authorize_global(ctrl = params[:controller], action = params[:action], global = true)
+    authorize(ctrl, action, global)
+  end
+
+  # Find project of id params[:id]
+  def find_project
+    @project = Project.find(params[:id])
+  rescue ActiveRecord::RecordNotFound
+    render_404
+  end
+
+  # Find project of id params[:project_id]
+  def find_project_by_project_id
+    @project = Project.find(params[:project_id])
+  rescue ActiveRecord::RecordNotFound
+    render_404
+  end
+
+  # Find a project based on params[:project_id]
+  # TODO: some subclasses override this, see about merging their logic
+  def find_optional_project
+    @project = Project.find(params[:project_id]) unless params[:project_id].blank?
+    allowed = User.current.allowed_to?({:controller => params[:controller], :action => params[:action]}, @project, :global => true)
+    allowed ? true : deny_access
+  rescue ActiveRecord::RecordNotFound
+    render_404
+  end
+
+  # Finds and sets @project based on @object.project
+  def find_project_from_association
+    render_404 unless @object.present?
+
+    @project = @object.project
+  end
+
+  def find_model_object
+    model = self.class.model_object
+    if model
+      @object = model.find(params[:id])
+      self.instance_variable_set('@' + controller_name.singularize, @object) if @object
+    end
+  rescue ActiveRecord::RecordNotFound
+    render_404
+  end
+
+  def self.model_object(model)
+    self.model_object = model
+  end
+
+  # Find the issue whose id is the :id parameter
+  # Raises a Unauthorized exception if the issue is not visible
+  def find_issue
+    # Issue.visible.find(...) can not be used to redirect user to the login form
+    # if the issue actually exists but requires authentication
+    @issue = Issue.find(params[:id])
+    raise Unauthorized unless @issue.visible?
+    @project = @issue.project
+  rescue ActiveRecord::RecordNotFound
+    render_404
+  end
+
+  # Find issues with a single :id param or :ids array param
+  # Raises a Unauthorized exception if one of the issues is not visible
+  def find_issues
+    @issues = Issue.where(:id => (params[:id] || params[:ids])).preload(:project, :status, :tracker, :priority, :author, :assigned_to, :relations_to).to_a
+    raise ActiveRecord::RecordNotFound if @issues.empty?
+    raise Unauthorized unless @issues.all?(&:visible?)
+    @projects = @issues.collect(&:project).compact.uniq
+    @project = @projects.first if @projects.size == 1
+  rescue ActiveRecord::RecordNotFound
+    render_404
+  end
+
+  def find_attachments
+    if (attachments = params[:attachments]).present?
+      att = attachments.values.collect do |attachment|
+        Attachment.find_by_token( attachment[:token] ) if attachment[:token].present?
+      end
+      att.compact!
+    end
+    @attachments = att || []
+  end
+
+  # make sure that the user is a member of the project (or admin) if project is private
+  # used as a before_filter for actions that do not require any particular permission on the project
+  def check_project_privacy
+    if @project && !@project.archived?
+      if @project.visible?
+        true
+      else
+        deny_access
+      end
+    else
+      @project = nil
+      render_404
+      false
+    end
+  end
+
+  def back_url
+    url = params[:back_url]
+    if url.nil? && referer = request.env['HTTP_REFERER']
+      url = CGI.unescape(referer.to_s)
+    end
+    url
+  end
+
+  def redirect_back_or_default(default)
+    back_url = params[:back_url].to_s
+    if back_url.present? && valid_back_url?(back_url)
+      redirect_to(back_url)
+      return
+    end
+    redirect_to default
+    false
+  end
+
+  # Returns true if back_url is a valid url for redirection, otherwise false
+  def valid_back_url?(back_url)
+    if CGI.unescape(back_url).include?('..')
+      return false
+    end
+
+    begin
+      uri = URI.parse(back_url)
+    rescue URI::InvalidURIError
+      return false
+    end
+
+    if uri.host.present? && uri.host != request.host
+      return false
+    end
+
+    if uri.path.match(%r{/(login|account/register)})
+      return false
+    end
+
+    if relative_url_root.present? && !uri.path.starts_with?(relative_url_root)
+      return false
+    end
+
+    return true
+  end
+  private :valid_back_url?
+
+  # Redirects to the request referer if present, redirects to args or call block otherwise.
+  def redirect_to_referer_or(*args, &block)
+    redirect_to :back
+  rescue ::ActionController::RedirectBackError
+    if args.any?
+      redirect_to *args
+    elsif block_given?
+      block.call
+    else
+      raise "#redirect_to_referer_or takes arguments or a block"
+    end
+  end
+
+  def render_403(options={})
+    @project = nil
+    render_error({:message => :notice_not_authorized, :status => 403}.merge(options))
+    return false
+  end
+
+  def render_404(options={})
+    render_error({:message => :notice_file_not_found, :status => 404}.merge(options))
+    return false
+  end
+
+  # Renders an error response
+  def render_error(arg)
+    arg = {:message => arg} unless arg.is_a?(Hash)
+
+    @message = arg[:message]
+    @message = l(@message) if @message.is_a?(Symbol)
+    @status = arg[:status] || 500
+
+    respond_to do |format|
+      format.html {
+        render :template => 'common/error', :layout => use_layout, :status => @status
+      }
+      format.any { head @status }
+    end
+  end
+
+  # Handler for ActionView::MissingTemplate exception
+  def missing_template
+    logger.warn "Missing template, responding with 404"
+    @project = nil
+    render_404
+  end
+
+  # Filter for actions that provide an API response
+  # but have no HTML representation for non admin users
+  def require_admin_or_api_request
+    return true if api_request?
+    if User.current.admin?
+      true
+    elsif User.current.logged?
+      render_error(:status => 406)
+    else
+      deny_access
+    end
+  end
+
+  # Picks which layout to use based on the request
+  #
+  # @return [boolean, string] name of the layout to use or false for no layout
+  def use_layout
+    request.xhr? ? false : 'base'
+  end
+
+  def render_feed(items, options={})
+    @items = items || []
+    @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
+    @items = @items.slice(0, Setting.feeds_limit.to_i)
+    @title = options[:title] || Setting.app_title
+    render :template => "common/feed", :formats => [:atom], :layout => false,
+           :content_type => 'application/atom+xml'
+  end
+
+  def self.accept_rss_auth(*actions)
+    if actions.any?
+      self.accept_rss_auth_actions = actions
+    else
+      self.accept_rss_auth_actions || []
+    end
+  end
+
+  def accept_rss_auth?(action=action_name)
+    self.class.accept_rss_auth.include?(action.to_sym)
+  end
+
+  def self.accept_api_auth(*actions)
+    if actions.any?
+      self.accept_api_auth_actions = actions
+    else
+      self.accept_api_auth_actions || []
+    end
+  end
+
+  def accept_api_auth?(action=action_name)
+    self.class.accept_api_auth.include?(action.to_sym)
+  end
+
+  # Returns the number of objects that should be displayed
+  # on the paginated list
+  def per_page_option
+    per_page = nil
+    if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i)
+      per_page = params[:per_page].to_s.to_i
+      session[:per_page] = per_page
+    elsif session[:per_page]
+      per_page = session[:per_page]
+    else
+      per_page = Setting.per_page_options_array.first || 25
+    end
+    per_page
+  end
+
+  # Returns offset and limit used to retrieve objects
+  # for an API response based on offset, limit and page parameters
+  def api_offset_and_limit(options=params)
+    if options[:offset].present?
+      offset = options[:offset].to_i
+      if offset < 0
+        offset = 0
+      end
+    end
+    limit = options[:limit].to_i
+    if limit < 1
+      limit = 25
+    elsif limit > 100
+      limit = 100
+    end
+    if offset.nil? && options[:page].present?
+      offset = (options[:page].to_i - 1) * limit
+      offset = 0 if offset < 0
+    end
+    offset ||= 0
+
+    [offset, limit]
+  end
+
+  # qvalues http header parser
+  # code taken from webrick
+  def parse_qvalues(value)
+    tmp = []
+    if value
+      parts = value.split(/,\s*/)
+      parts.each {|part|
+        if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
+          val = m[1]
+          q = (m[2] or 1).to_f
+          tmp.push([val, q])
+        end
+      }
+      tmp = tmp.sort_by{|val, q| -q}
+      tmp.collect!{|val, q| val}
+    end
+    return tmp
+  rescue
+    nil
+  end
+
+  # Returns a string that can be used as filename value in Content-Disposition header
+  def filename_for_content_disposition(name)
+    request.env['HTTP_USER_AGENT'] =~ %r{(MSIE|Trident)} ? ERB::Util.url_encode(name) : name
+  end
+
+  def api_request?
+    %w(xml json).include? params[:format]
+  end
+
+  # Returns the API key present in the request
+  def api_key_from_request
+    if params[:key].present?
+      params[:key].to_s
+    elsif request.headers["X-Redmine-API-Key"].present?
+      request.headers["X-Redmine-API-Key"].to_s
+    end
+  end
+
+  # Returns the API 'switch user' value if present
+  def api_switch_user_from_request
+    request.headers["X-Redmine-Switch-User"].to_s.presence
+  end
+
+  # Renders a warning flash if obj has unsaved attachments
+  def render_attachment_warning_if_needed(obj)
+    flash[:warning] = l(:warning_attachments_not_saved, obj.unsaved_attachments.size) if obj.unsaved_attachments.present?
+  end
+
+  # Rescues an invalid query statement. Just in case...
+  def query_statement_invalid(exception)
+    logger.error "Query::StatementInvalid: #{exception.message}" if logger
+    session.delete(:query)
+    sort_clear if respond_to?(:sort_clear)
+    render_error "An error occurred while executing the query and has been logged. Please report this error to your Redmine administrator."
+  end
+
+  # Renders a 200 response for successfull updates or deletions via the API
+  def render_api_ok
+    render_api_head :ok
+  end
+
+  # Renders a head API response
+  def render_api_head(status)
+    # #head would return a response body with one space
+    render :text => '', :status => status, :layout => nil
+  end
+
+  # Renders API response on validation failure
+  def render_validation_errors(objects)
+    if objects.is_a?(Array)
+      @error_messages = objects.map {|object| object.errors.full_messages}.flatten
+    else
+      @error_messages = objects.errors.full_messages
+    end
+    render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => nil
+  end
+
+  # Overrides #_include_layout? so that #render with no arguments
+  # doesn't use the layout for api requests
+  def _include_layout?(*args)
+    api_request? ? false : super
+  end
+end
--- a/.svn/pristine/32/3223a76e70547eaec39a0a66a9b27b9eba0314ac.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AttachmentTest < ActiveSupport::TestCase
-  fixtures :users, :projects, :roles, :members, :member_roles,
-           :enabled_modules, :issues, :trackers, :attachments
-  
-  class MockFile
-    attr_reader :original_filename, :content_type, :content, :size
-    
-    def initialize(attributes)
-      @original_filename = attributes[:original_filename]
-      @content_type = attributes[:content_type]
-      @content = attributes[:content] || "Content"
-      @size = content.size
-    end
-  end
-
-  def setup
-    set_tmp_attachments_directory
-  end
-
-  def test_container_for_new_attachment_should_be_nil
-    assert_nil Attachment.new.container
-  end
-
-  def test_filename_should_remove_eols
-    assert_equal "line_feed", Attachment.new(:filename => "line\nfeed").filename
-    assert_equal "line_feed", Attachment.new(:filename => "some\npath/line\nfeed").filename
-    assert_equal "carriage_return", Attachment.new(:filename => "carriage\rreturn").filename
-    assert_equal "carriage_return", Attachment.new(:filename => "some\rpath/carriage\rreturn").filename
-  end
-
-  def test_create
-    a = Attachment.new(:container => Issue.find(1),
-                       :file => uploaded_test_file("testfile.txt", "text/plain"),
-                       :author => User.find(1))
-    assert a.save
-    assert_equal 'testfile.txt', a.filename
-    assert_equal 59, a.filesize
-    assert_equal 'text/plain', a.content_type
-    assert_equal 0, a.downloads
-    assert_equal '1478adae0d4eb06d35897518540e25d6', a.digest
-
-    assert a.disk_directory
-    assert_match %r{\A\d{4}/\d{2}\z}, a.disk_directory
-
-    assert File.exist?(a.diskfile)
-    assert_equal 59, File.size(a.diskfile)
-  end
-
-  def test_copy_should_preserve_attributes
-    a = Attachment.find(1)
-    copy = a.copy
-
-    assert_save copy
-    copy = Attachment.order('id DESC').first
-    %w(filename filesize content_type author_id created_on description digest disk_filename disk_directory diskfile).each do |attribute|
-      assert_equal a.send(attribute), copy.send(attribute), "#{attribute} was different"
-    end
-  end
-
-  def test_size_should_be_validated_for_new_file
-    with_settings :attachment_max_size => 0 do
-      a = Attachment.new(:container => Issue.find(1),
-                         :file => uploaded_test_file("testfile.txt", "text/plain"),
-                         :author => User.find(1))
-      assert !a.save
-    end
-  end
-
-  def test_size_should_not_be_validated_when_copying
-    a = Attachment.create!(:container => Issue.find(1),
-                           :file => uploaded_test_file("testfile.txt", "text/plain"),
-                           :author => User.find(1))
-    with_settings :attachment_max_size => 0 do
-      copy = a.copy
-      assert copy.save
-    end
-  end
-
-  def test_description_length_should_be_validated
-    a = Attachment.new(:description => 'a' * 300)
-    assert !a.save
-    assert_not_equal [], a.errors[:description]
-  end
-
-  def test_destroy
-    a = Attachment.new(:container => Issue.find(1),
-                       :file => uploaded_test_file("testfile.txt", "text/plain"),
-                       :author => User.find(1))
-    assert a.save
-    assert_equal 'testfile.txt', a.filename
-    assert_equal 59, a.filesize
-    assert_equal 'text/plain', a.content_type
-    assert_equal 0, a.downloads
-    assert_equal '1478adae0d4eb06d35897518540e25d6', a.digest
-    diskfile = a.diskfile
-    assert File.exist?(diskfile)
-    assert_equal 59, File.size(a.diskfile)
-    assert a.destroy
-    assert !File.exist?(diskfile)
-  end
-
-  def test_destroy_should_not_delete_file_referenced_by_other_attachment
-    a = Attachment.create!(:container => Issue.find(1),
-                           :file => uploaded_test_file("testfile.txt", "text/plain"),
-                           :author => User.find(1))
-    diskfile = a.diskfile
-
-    copy = a.copy
-    copy.save!
-
-    assert File.exists?(diskfile)
-    a.destroy
-    assert File.exists?(diskfile)
-    copy.destroy
-    assert !File.exists?(diskfile)
-  end
-
-  def test_create_should_auto_assign_content_type
-    a = Attachment.new(:container => Issue.find(1),
-                       :file => uploaded_test_file("testfile.txt", ""),
-                       :author => User.find(1))
-    assert a.save
-    assert_equal 'text/plain', a.content_type
-  end
-
-  def test_identical_attachments_at_the_same_time_should_not_overwrite
-    a1 = Attachment.create!(:container => Issue.find(1),
-                            :file => uploaded_test_file("testfile.txt", ""),
-                            :author => User.find(1))
-    a2 = Attachment.create!(:container => Issue.find(1),
-                            :file => uploaded_test_file("testfile.txt", ""),
-                            :author => User.find(1))
-    assert a1.disk_filename != a2.disk_filename
-  end
-  
-  def test_filename_should_be_basenamed
-    a = Attachment.new(:file => MockFile.new(:original_filename => "path/to/the/file"))
-    assert_equal 'file', a.filename
-  end
-  
-  def test_filename_should_be_sanitized
-    a = Attachment.new(:file => MockFile.new(:original_filename => "valid:[] invalid:?%*|\"'<>chars"))
-    assert_equal 'valid_[] invalid_chars', a.filename
-  end
-
-  def test_diskfilename
-    assert Attachment.disk_filename("test_file.txt") =~ /^\d{12}_test_file.txt$/
-    assert_equal 'test_file.txt', Attachment.disk_filename("test_file.txt")[13..-1]
-    assert_equal '770c509475505f37c2b8fb6030434d6b.txt', Attachment.disk_filename("test_accentué.txt")[13..-1]
-    assert_equal 'f8139524ebb8f32e51976982cd20a85d', Attachment.disk_filename("test_accentué")[13..-1]
-    assert_equal 'cbb5b0f30978ba03731d61f9f6d10011', Attachment.disk_filename("test_accentué.ça")[13..-1]
-  end
-
-  def test_title
-    a = Attachment.new(:filename => "test.png")
-    assert_equal "test.png", a.title
-
-    a = Attachment.new(:filename => "test.png", :description => "Cool image")
-    assert_equal "test.png (Cool image)", a.title
-  end
-
-  def test_prune_should_destroy_old_unattached_attachments
-    Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1, :created_on => 2.days.ago)
-    Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1, :created_on => 2.days.ago)
-    Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1)
-
-    assert_difference 'Attachment.count', -2 do
-      Attachment.prune
-    end
-  end
-
-  def test_move_from_root_to_target_directory_should_move_root_files
-    a = Attachment.find(20)
-    assert a.disk_directory.blank?
-    # Create a real file for this fixture
-    File.open(a.diskfile, "w") do |f|
-      f.write "test file at the root of files directory"
-    end
-    assert a.readable?
-    Attachment.move_from_root_to_target_directory
-
-    a.reload
-    assert_equal '2012/05', a.disk_directory
-    assert a.readable?
-  end
-
-  test "Attachmnet.attach_files should attach the file" do
-    issue = Issue.first
-    assert_difference 'Attachment.count' do
-      Attachment.attach_files(issue,
-        '1' => {
-          'file' => uploaded_test_file('testfile.txt', 'text/plain'),
-          'description' => 'test'
-        })
-    end
-
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_equal issue, attachment.container
-    assert_equal 'testfile.txt', attachment.filename
-    assert_equal 59, attachment.filesize
-    assert_equal 'test', attachment.description
-    assert_equal 'text/plain', attachment.content_type
-    assert File.exists?(attachment.diskfile)
-    assert_equal 59, File.size(attachment.diskfile)
-  end
-
-  test "Attachmnet.attach_files should add unsaved files to the object as unsaved attachments" do
-    # Max size of 0 to force Attachment creation failures
-    with_settings(:attachment_max_size => 0) do
-      @project = Project.find(1)
-      response = Attachment.attach_files(@project, {
-                                           '1' => {'file' => mock_file, 'description' => 'test'},
-                                           '2' => {'file' => mock_file, 'description' => 'test'}
-                                         })
-
-      assert response[:unsaved].present?
-      assert_equal 2, response[:unsaved].length
-      assert response[:unsaved].first.new_record?
-      assert response[:unsaved].second.new_record?
-      assert_equal response[:unsaved], @project.unsaved_attachments
-    end
-  end
-
-  def test_latest_attach
-    set_fixtures_attachments_directory
-    a1 = Attachment.find(16)
-    assert_equal "testfile.png", a1.filename
-    assert a1.readable?
-    assert (! a1.visible?(User.anonymous))
-    assert a1.visible?(User.find(2))
-    a2 = Attachment.find(17)
-    assert_equal "testfile.PNG", a2.filename
-    assert a2.readable?
-    assert (! a2.visible?(User.anonymous))
-    assert a2.visible?(User.find(2))
-    assert a1.created_on < a2.created_on
-
-    la1 = Attachment.latest_attach([a1, a2], "testfile.png")
-    assert_equal 17, la1.id
-    la2 = Attachment.latest_attach([a1, a2], "Testfile.PNG")
-    assert_equal 17, la2.id
-
-    set_tmp_attachments_directory
-  end
-
-  def test_thumbnailable_should_be_true_for_images
-    assert_equal true, Attachment.new(:filename => 'test.jpg').thumbnailable?
-  end
-
-  def test_thumbnailable_should_be_true_for_non_images
-    assert_equal false, Attachment.new(:filename => 'test.txt').thumbnailable?
-  end
-
-  if convert_installed?
-    def test_thumbnail_should_generate_the_thumbnail
-      set_fixtures_attachments_directory
-      attachment = Attachment.find(16)
-      Attachment.clear_thumbnails
-
-      assert_difference "Dir.glob(File.join(Attachment.thumbnails_storage_path, '*.thumb')).size" do
-        thumbnail = attachment.thumbnail
-        assert_equal "16_8e0294de2441577c529f170b6fb8f638_100.thumb", File.basename(thumbnail)
-        assert File.exists?(thumbnail)
-      end
-    end
-  else
-    puts '(ImageMagick convert not available)'
-  end
-end
--- a/.svn/pristine/32/323d1bcc86907f9d5a2126f30f3d7a3ae8693252.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Watcher < ActiveRecord::Base
-  belongs_to :watchable, :polymorphic => true
-  belongs_to :user
-
-  validates_presence_of :user
-  validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id]
-  validate :validate_user
-
-  # Returns true if at least one object among objects is watched by user
-  def self.any_watched?(objects, user)
-    objects = objects.reject(&:new_record?)
-    if objects.any?
-      objects.group_by {|object| object.class.base_class}.each do |base_class, objects|
-        if Watcher.where(:watchable_type => base_class.name, :watchable_id => objects.map(&:id), :user_id => user.id).exists?
-          return true
-        end
-      end
-    end
-    false
-  end
-
-  # Unwatch things that users are no longer allowed to view
-  def self.prune(options={})
-    if options.has_key?(:user)
-      prune_single_user(options[:user], options)
-    else
-      pruned = 0
-      User.where("id IN (SELECT DISTINCT user_id FROM #{table_name})").all.each do |user|
-        pruned += prune_single_user(user, options)
-      end
-      pruned
-    end
-  end
-
-  protected
-
-  def validate_user
-    errors.add :user_id, :invalid unless user.nil? || user.active?
-  end
-
-  private
-
-  def self.prune_single_user(user, options={})
-    return unless user.is_a?(User)
-    pruned = 0
-    where(:user_id => user.id).all.each do |watcher|
-      next if watcher.watchable.nil?
-
-      if options.has_key?(:project)
-        next unless watcher.watchable.respond_to?(:project) && watcher.watchable.project == options[:project]
-      end
-
-      if watcher.watchable.respond_to?(:visible?)
-        unless watcher.watchable.visible?(user)
-          watcher.destroy
-          pruned += 1
-        end
-      end
-    end
-    pruned
-  end
-end
--- a/.svn/pristine/32/326a62adc02ab48e12d9e9d717fea2e84b8c44cf.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,601 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoryGitTest < ActiveSupport::TestCase
-  fixtures :projects, :repositories, :enabled_modules, :users, :roles
-
-  include Redmine::I18n
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
-  REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
-
-  NUM_REV = 28
-  NUM_HEAD = 6
-
-  FELIX_HEX  = "Felix Sch\xC3\xA4fer"
-  CHAR_1_HEX = "\xc3\x9c"
-
-  ## Git, Mercurial and CVS path encodings are binary.
-  ## Subversion supports URL encoding for path.
-  ## Redmine Mercurial adapter and extension use URL encoding.
-  ## Git accepts only binary path in command line parameter.
-  ## So, there is no way to use binary command line parameter in JRuby.
-  JRUBY_SKIP     = (RUBY_PLATFORM == 'java')
-  JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
-
-  def setup
-    @project = Project.find(3)
-    @repository = Repository::Git.create(
-                        :project       => @project,
-                        :url           => REPOSITORY_PATH,
-                        :path_encoding => 'ISO-8859-1'
-                        )
-    assert @repository
-    @char_1        = CHAR_1_HEX.dup
-    if @char_1.respond_to?(:force_encoding)
-      @char_1.force_encoding('UTF-8')
-    end
-  end
-
-  def test_blank_path_to_repository_error_message
-    set_language_if_valid 'en'
-    repo = Repository::Git.new(
-                          :project      => @project,
-                          :identifier   => 'test'
-                        )
-    assert !repo.save
-    assert_include "Path to repository can't be blank",
-                   repo.errors.full_messages
-  end
-
-  def test_blank_path_to_repository_error_message_fr
-    set_language_if_valid 'fr'
-    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    repo = Repository::Git.new(
-                          :project      => @project,
-                          :url          => "",
-                          :identifier   => 'test',
-                          :path_encoding => ''
-                        )
-    assert !repo.save
-    assert_include str, repo.errors.full_messages
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    ## Ruby uses ANSI api to fork a process on Windows.
-    ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
-    ## and these are incompatible with ASCII.
-    ## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10
-    ## http://code.google.com/p/msysgit/issues/detail?id=80
-    ## So, Latin-1 path tests fail on Japanese Windows
-    WINDOWS_PASS = (Redmine::Platform.mswin? &&
-                         Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10]))
-    WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10"
-
-    def test_scm_available
-      klass = Repository::Git
-      assert_equal "Git", klass.scm_name
-      assert klass.scm_adapter_class
-      assert_not_equal "", klass.scm_command
-      assert_equal true, klass.scm_available
-    end
-
-    def test_entries
-      entries = @repository.entries
-      assert_kind_of Redmine::Scm::Adapters::Entries, entries
-    end
-
-    def test_fetch_changesets_from_scratch
-      assert_nil @repository.extra_info
-
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_equal 39, @repository.filechanges.count
-
-      commit = @repository.changesets.find_by_revision("7234cb2750b63f47bff735edc50a1c0a433c2518")
-      assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518", commit.scmid
-      assert_equal "Initial import.\nThe repository contains 3 files.", commit.comments
-      assert_equal "jsmith <jsmith@foo.bar>", commit.committer
-      assert_equal User.find_by_login('jsmith'), commit.user
-      # TODO: add a commit with commit time <> author time to the test repository
-      assert_equal "2007-12-14 09:22:52".to_time, commit.committed_on
-      assert_equal "2007-12-14".to_date, commit.commit_date
-      assert_equal 3, commit.filechanges.count
-      change = commit.filechanges.sort_by(&:path).first
-      assert_equal "README", change.path
-      assert_equal nil, change.from_path
-      assert_equal "A", change.action
-
-      assert_equal NUM_HEAD, @repository.extra_info["heads"].size
-    end
-
-    def test_fetch_changesets_incremental
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      extra_info_heads = @repository.extra_info["heads"].dup
-      assert_equal NUM_HEAD, extra_info_heads.size
-      extra_info_heads.delete_if { |x| x == "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c" }
-      assert_equal 4, extra_info_heads.size
-
-      del_revs = [
-          "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
-          "ed5bb786bbda2dee66a2d50faf51429dbc043a7b",
-          "4f26664364207fa8b1af9f8722647ab2d4ac5d43",
-          "deff712f05a90d96edbd70facc47d944be5897e3",
-          "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
-          "7e61ac704deecde634b51e59daa8110435dcb3da",
-         ]
-      @repository.changesets.each do |rev|
-        rev.destroy if del_revs.detect {|r| r == rev.scmid.to_s }
-      end
-      @project.reload
-      cs1 = @repository.changesets
-      assert_equal NUM_REV - 6, cs1.count
-      extra_info_heads << "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8"
-      h = {}
-      h["heads"] = extra_info_heads
-      @repository.merge_extra_info(h)
-      @repository.save
-      @project.reload
-      assert @repository.extra_info["heads"].index("4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8")
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_equal NUM_HEAD, @repository.extra_info["heads"].size
-      assert @repository.extra_info["heads"].index("83ca5fd546063a3c7dc2e568ba3355661a9e2b2c")
-    end
-
-    def test_fetch_changesets_history_editing
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      extra_info_heads = @repository.extra_info["heads"].dup
-      assert_equal NUM_HEAD, extra_info_heads.size
-      extra_info_heads.delete_if { |x| x == "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c" }
-      assert_equal 4, extra_info_heads.size
-
-      del_revs = [
-          "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
-          "ed5bb786bbda2dee66a2d50faf51429dbc043a7b",
-          "4f26664364207fa8b1af9f8722647ab2d4ac5d43",
-          "deff712f05a90d96edbd70facc47d944be5897e3",
-          "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
-          "7e61ac704deecde634b51e59daa8110435dcb3da",
-         ]
-      @repository.changesets.each do |rev|
-        rev.destroy if del_revs.detect {|r| r == rev.scmid.to_s }
-      end
-      @project.reload
-      assert_equal NUM_REV - 6, @repository.changesets.count
-
-      c = Changeset.new(:repository   => @repository,
-                        :committed_on => Time.now,
-                        :revision     => "abcd1234efgh",
-                        :scmid        => "abcd1234efgh",
-                        :comments     => 'test')
-      assert c.save
-      @project.reload
-      assert_equal NUM_REV - 5, @repository.changesets.count
-
-      extra_info_heads << "1234abcd5678"
-      h = {}
-      h["heads"] = extra_info_heads
-      @repository.merge_extra_info(h)
-      @repository.save
-      @project.reload
-      h1 = @repository.extra_info["heads"].dup
-      assert h1.index("1234abcd5678")
-      assert_equal 5, h1.size
-
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV - 5, @repository.changesets.count
-      h2 = @repository.extra_info["heads"].dup
-      assert_equal h1, h2
-    end
-
-    def test_keep_extra_report_last_commit_in_clear_changesets
-      assert_nil @repository.extra_info
-      h = {}
-      h["extra_report_last_commit"] = "1"
-      @repository.merge_extra_info(h)
-      @repository.save
-      @project.reload
-
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-
-      assert_equal NUM_REV, @repository.changesets.count
-      @repository.send(:clear_changesets)
-      assert_equal 1, @repository.extra_info.size
-      assert_equal "1", @repository.extra_info["extra_report_last_commit"]
-    end
-
-    def test_refetch_after_clear_changesets
-      assert_nil @repository.extra_info
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      @repository.send(:clear_changesets)
-      @project.reload
-      assert_equal 0, @repository.changesets.count
-
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-    end
-
-    def test_parents
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      r1 = @repository.find_changeset_by_name("7234cb2750b63")
-      assert_equal [], r1.parents
-      r2 = @repository.find_changeset_by_name("899a15dba03a3")
-      assert_equal 1, r2.parents.length
-      assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
-                   r2.parents[0].identifier
-      r3 = @repository.find_changeset_by_name("32ae898b720c2")
-      assert_equal 2, r3.parents.length
-      r4 = [r3.parents[0].identifier, r3.parents[1].identifier].sort
-      assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", r4[0]
-      assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da", r4[1]
-    end
-
-    def test_db_consistent_ordering_init
-      assert_nil @repository.extra_info
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal 1, @repository.extra_info["db_consistent"]["ordering"]
-    end
-
-    def test_db_consistent_ordering_before_1_2
-      assert_nil @repository.extra_info
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_not_nil @repository.extra_info
-      h = {}
-      h["heads"] = []
-      h["branches"] = {}
-      h["db_consistent"] = {}
-      @repository.merge_extra_info(h)
-      @repository.save
-      assert_equal NUM_REV, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal 0, @repository.extra_info["db_consistent"]["ordering"]
-
-      extra_info_heads = @repository.extra_info["heads"].dup
-      extra_info_heads.delete_if { |x| x == "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c" }
-      del_revs = [
-          "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
-          "ed5bb786bbda2dee66a2d50faf51429dbc043a7b",
-          "4f26664364207fa8b1af9f8722647ab2d4ac5d43",
-          "deff712f05a90d96edbd70facc47d944be5897e3",
-          "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
-          "7e61ac704deecde634b51e59daa8110435dcb3da",
-         ]
-      @repository.changesets.each do |rev|
-        rev.destroy if del_revs.detect {|r| r == rev.scmid.to_s }
-      end
-      @project.reload
-      cs1 = @repository.changesets
-      assert_equal NUM_REV - 6, cs1.count
-      assert_equal 0, @repository.extra_info["db_consistent"]["ordering"]
-
-      extra_info_heads << "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8"
-      h = {}
-      h["heads"] = extra_info_heads
-      @repository.merge_extra_info(h)
-      @repository.save
-      @project.reload
-      assert @repository.extra_info["heads"].index("4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8")
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_equal NUM_HEAD, @repository.extra_info["heads"].size
-
-      assert_equal 0, @repository.extra_info["db_consistent"]["ordering"]
-    end
-
-    def test_heads_from_branches_hash
-      assert_nil @repository.extra_info
-      assert_equal 0, @repository.changesets.count
-      assert_equal [], @repository.heads_from_branches_hash
-      h = {}
-      h["branches"] = {}
-      h["branches"]["test1"] = {}
-      h["branches"]["test1"]["last_scmid"] = "1234abcd"
-      h["branches"]["test2"] = {}
-      h["branches"]["test2"]["last_scmid"] = "abcd1234"
-      @repository.merge_extra_info(h)
-      @repository.save
-      @project.reload
-      assert_equal ["1234abcd", "abcd1234"], @repository.heads_from_branches_hash.sort
-    end
-
-    def test_latest_changesets
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      # with limit
-      changesets = @repository.latest_changesets('', 'master', 2)
-      assert_equal 2, changesets.size
-
-      # with path
-      changesets = @repository.latest_changesets('images', 'master')
-      assert_equal [
-              'deff712f05a90d96edbd70facc47d944be5897e3',
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-              '7234cb2750b63f47bff735edc50a1c0a433c2518',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README', nil)
-      assert_equal [
-              '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf',
-              '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8',
-              '713f4944648826f558cf548222f813dabe7cbb04',
-              '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-              '7234cb2750b63f47bff735edc50a1c0a433c2518',
-          ], changesets.collect(&:revision)
-
-      # with path, revision and limit
-      changesets = @repository.latest_changesets('images', '899a15dba')
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-              '7234cb2750b63f47bff735edc50a1c0a433c2518',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('images', '899a15dba', 1)
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README', '899a15dba')
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-              '7234cb2750b63f47bff735edc50a1c0a433c2518',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README', '899a15dba', 1)
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-          ], changesets.collect(&:revision)
-
-      # with path, tag and limit
-      changesets = @repository.latest_changesets('images', 'tag01.annotated')
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-              '7234cb2750b63f47bff735edc50a1c0a433c2518',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('images', 'tag01.annotated', 1)
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README', 'tag01.annotated')
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-              '7234cb2750b63f47bff735edc50a1c0a433c2518',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README', 'tag01.annotated', 1)
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-          ], changesets.collect(&:revision)
-
-      # with path, branch and limit
-      changesets = @repository.latest_changesets('images', 'test_branch')
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-              '7234cb2750b63f47bff735edc50a1c0a433c2518',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('images', 'test_branch', 1)
-      assert_equal [
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README', 'test_branch')
-      assert_equal [
-              '713f4944648826f558cf548222f813dabe7cbb04',
-              '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
-              '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
-              '7234cb2750b63f47bff735edc50a1c0a433c2518',
-          ], changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README', 'test_branch', 2)
-      assert_equal [
-              '713f4944648826f558cf548222f813dabe7cbb04',
-              '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
-          ], changesets.collect(&:revision)
-
-      if WINDOWS_PASS
-        puts WINDOWS_SKIP_STR
-      elsif JRUBY_SKIP
-        puts JRUBY_SKIP_STR
-      else
-        # latin-1 encoding path
-        changesets = @repository.latest_changesets(
-                      "latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89')
-        assert_equal [
-              '64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
-              '4fc55c43bf3d3dc2efb66145365ddc17639ce81e',
-          ], changesets.collect(&:revision)
-
-        changesets = @repository.latest_changesets(
-                    "latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89', 1)
-        assert_equal [
-              '64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
-          ], changesets.collect(&:revision)
-      end
-    end
-
-    def test_latest_changesets_latin_1_dir
-      if WINDOWS_PASS
-        puts WINDOWS_SKIP_STR
-      elsif JRUBY_SKIP
-        puts JRUBY_SKIP_STR
-      else
-        assert_equal 0, @repository.changesets.count
-        @repository.fetch_changesets
-        @project.reload
-        assert_equal NUM_REV, @repository.changesets.count
-        changesets = @repository.latest_changesets(
-                    "latin-1-dir/test-#{@char_1}-subdir", '1ca7f5ed')
-        assert_equal [
-              '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127',
-          ], changesets.collect(&:revision)
-      end
-    end
-
-    def test_find_changeset_by_name
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['7234cb2750b63f47bff735edc50a1c0a433c2518', '7234cb2750b'].each do |r|
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518',
-                     @repository.find_changeset_by_name(r).revision
-      end
-    end
-
-    def test_find_changeset_by_empty_name
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['', ' ', nil].each do |r|
-        assert_nil @repository.find_changeset_by_name(r)
-      end
-    end
-
-    def test_identifier
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      c = @repository.changesets.find_by_revision(
-                          '7234cb2750b63f47bff735edc50a1c0a433c2518')
-      assert_equal c.scmid, c.identifier
-    end
-
-    def test_format_identifier
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      c = @repository.changesets.find_by_revision(
-                          '7234cb2750b63f47bff735edc50a1c0a433c2518')
-      assert_equal '7234cb27', c.format_identifier
-    end
-
-    def test_activities
-      c = Changeset.new(:repository => @repository,
-                        :committed_on => Time.now,
-                        :revision => 'abc7234cb2750b63f47bff735edc50a1c0a433c2',
-                        :scmid    => 'abc7234cb2750b63f47bff735edc50a1c0a433c2',
-                        :comments => 'test')
-      assert c.event_title.include?('abc7234c:')
-      assert_equal 'abc7234cb2750b63f47bff735edc50a1c0a433c2', c.event_url[:rev]
-    end
-
-    def test_log_utf8
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      str_felix_hex  = FELIX_HEX.dup
-      if str_felix_hex.respond_to?(:force_encoding)
-          str_felix_hex.force_encoding('UTF-8')
-      end
-      c = @repository.changesets.find_by_revision(
-                        'ed5bb786bbda2dee66a2d50faf51429dbc043a7b')
-      assert_equal "#{str_felix_hex} <felix@fachschaften.org>", c.committer
-    end
-
-    def test_previous
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      %w|1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127 1ca7f5ed|.each do |r1|
-        changeset = @repository.find_changeset_by_name(r1)
-        %w|64f1f3e89ad1cb57976ff0ad99a107012ba3481d 64f1f3e89ad1|.each do |r2|
-          assert_equal @repository.find_changeset_by_name(r2), changeset.previous
-        end
-      end
-    end
-
-    def test_previous_nil
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      %w|7234cb2750b63f47bff735edc50a1c0a433c2518 7234cb275|.each do |r1|
-        changeset = @repository.find_changeset_by_name(r1)
-        assert_nil changeset.previous
-      end
-    end
-
-    def test_next
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      %w|64f1f3e89ad1cb57976ff0ad99a107012ba3481d 64f1f3e89ad1|.each do |r2|
-        changeset = @repository.find_changeset_by_name(r2)
-        %w|1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127 1ca7f5ed|.each do |r1|
-        assert_equal @repository.find_changeset_by_name(r1), changeset.next
-        end
-      end
-    end
-
-    def test_next_nil
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      %w|2a682156a3b6e77a8bf9cd4590e8db757f3c6c78 2a682156a3b6e77a|.each do |r1|
-        changeset = @repository.find_changeset_by_name(r1)
-        assert_nil changeset.next
-      end
-    end
-  else
-    puts "Git test repository NOT FOUND. Skipping unit tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/32/327b76cc374d806380bae0c4d024997da523a2a5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,526 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesMercurialControllerTest < ActionController::TestCase
-  tests RepositoriesController
-
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :repositories, :enabled_modules
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
-  CHAR_1_HEX = "\xc3\x9c"
-  PRJ_ID     = 3
-  NUM_REV    = 32
-
-  ruby19_non_utf8_pass =
-     (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
-
-  def setup
-    User.current = nil
-    @project    = Project.find(PRJ_ID)
-    @repository = Repository::Mercurial.create(
-                      :project => @project,
-                      :url     => REPOSITORY_PATH,
-                      :path_encoding => 'ISO-8859-1'
-                      )
-    assert @repository
-    @diff_c_support = true
-    @char_1        = CHAR_1_HEX.dup
-    @tag_char_1    = "tag-#{CHAR_1_HEX}-00"
-    @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
-    @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
-    if @char_1.respond_to?(:force_encoding)
-      @char_1.force_encoding('UTF-8')
-      @tag_char_1.force_encoding('UTF-8')
-      @branch_char_0.force_encoding('UTF-8')
-      @branch_char_1.force_encoding('UTF-8')
-    end
-  end
-
-  if ruby19_non_utf8_pass
-    puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
-         "and Encoding.default_external is not UTF-8. " +
-         "Current value is '#{Encoding.default_external.to_s}'"
-    def test_fake; assert true end
-  elsif File.directory?(REPOSITORY_PATH)
-
-    def test_get_new
-      @request.session[:user_id] = 1
-      @project.repository.destroy
-      get :new, :project_id => 'subproject1', :repository_scm => 'Mercurial'
-      assert_response :success
-      assert_template 'new'
-      assert_kind_of Repository::Mercurial, assigns(:repository)
-      assert assigns(:repository).new_record?
-    end
-
-    def test_show_root
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal 4, assigns(:entries).size
-      assert assigns(:entries).detect {|e| e.name == 'images'  && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'README'  && e.kind == 'file'}
-      assert_not_nil assigns(:changesets)
-      assert assigns(:changesets).size > 0
-    end
-
-    def test_show_directory
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
-      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
-      assert_not_nil entry
-      assert_equal 'file', entry.kind
-      assert_equal 'images/edit.png', entry.path
-      assert_not_nil assigns(:changesets)
-      assert assigns(:changesets).size > 0
-    end
-
-    def test_show_at_given_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      [0, '0', '0885933ad4f6'].each do |r1|
-        get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
-            :rev => r1
-        assert_response :success
-        assert_template 'show'
-        assert_not_nil assigns(:entries)
-        assert_equal ['delete.png'], assigns(:entries).collect(&:name)
-        assert_not_nil assigns(:changesets)
-        assert assigns(:changesets).size > 0
-      end
-    end
-
-    def test_show_directory_sql_escape_percent
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      [13, '13', '3a330eb32958'].each do |r1|
-        get :show, :id => PRJ_ID,
-            :path => repository_path_hash(['sql_escape', 'percent%dir'])[:param],
-            :rev => r1
-        assert_response :success
-        assert_template 'show'
-
-        assert_not_nil assigns(:entries)
-        assert_equal ['percent%file1.txt', 'percentfile1.txt'],
-                     assigns(:entries).collect(&:name)
-        changesets = assigns(:changesets)
-        assert_not_nil changesets
-        assert assigns(:changesets).size > 0
-        assert_equal %w(13 11 10 9), changesets.collect(&:revision)
-      end
-    end
-
-    def test_show_directory_latin_1_path
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      [21, '21', 'adf805632193'].each do |r1|
-        get :show, :id => PRJ_ID,
-            :path => repository_path_hash(['latin-1-dir'])[:param],
-            :rev => r1
-        assert_response :success
-        assert_template 'show'
-
-        assert_not_nil assigns(:entries)
-        assert_equal ["make-latin-1-file.rb",
-                      "test-#{@char_1}-1.txt",
-                      "test-#{@char_1}-2.txt",
-                      "test-#{@char_1}.txt"], assigns(:entries).collect(&:name)
-        changesets = assigns(:changesets)
-        assert_not_nil changesets
-        assert_equal %w(21 20 19 18 17), changesets.collect(&:revision)
-      end
-    end
-
-    def show_should_show_branch_selection_form
-      @repository.fetch_changesets
-      @project.reload
-      get :show, :id => PRJ_ID
-      assert_tag 'form', :attributes => {:id => 'revision_selector', :action => '/projects/subproject1/repository/show'}
-      assert_tag 'select', :attributes => {:name => 'branch'},
-        :child => {:tag => 'option', :attributes => {:value => 'test-branch-01'}},
-        :parent => {:tag => 'form', :attributes => {:id => 'revision_selector'}}
-    end
-
-    def test_show_branch
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-       [
-          'default',
-          @branch_char_1,
-          'branch (1)[2]&,%.-3_4',
-          @branch_char_0,
-          'test_branch.latin-1',
-          'test-branch-00',
-      ].each do |bra|
-        get :show, :id => PRJ_ID, :rev => bra
-        assert_response :success
-        assert_template 'show'
-        assert_not_nil assigns(:entries)
-        assert assigns(:entries).size > 0
-        assert_not_nil assigns(:changesets)
-        assert assigns(:changesets).size > 0
-      end
-    end
-
-    def test_show_tag
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-       [
-        @tag_char_1,
-        'tag_test.00',
-        'tag-init-revision'
-      ].each do |tag|
-        get :show, :id => PRJ_ID, :rev => tag
-        assert_response :success
-        assert_template 'show'
-        assert_not_nil assigns(:entries)
-        assert assigns(:entries).size > 0
-        assert_not_nil assigns(:changesets)
-        assert assigns(:changesets).size > 0
-      end
-    end
-
-    def test_changes
-      get :changes, :id => PRJ_ID,
-          :path => repository_path_hash(['images', 'edit.png'])[:param]
-      assert_response :success
-      assert_template 'changes'
-      assert_tag :tag => 'h2', :content => 'edit.png'
-    end
-
-    def test_entry_show
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
-      assert_response :success
-      assert_template 'entry'
-      # Line 10
-      assert_tag :tag => 'th',
-                 :content => '10',
-                 :attributes => { :class => 'line-num' },
-                 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
-    end
-
-    def test_entry_show_latin_1_path
-      [21, '21', 'adf805632193'].each do |r1|
-        get :entry, :id => PRJ_ID,
-            :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
-            :rev => r1
-        assert_response :success
-        assert_template 'entry'
-        assert_tag :tag => 'th',
-                 :content => '1',
-                 :attributes => { :class => 'line-num' },
-                 :sibling => { :tag => 'td',
-                               :content => /Mercurial is a distributed version control system/ }
-      end
-    end
-
-    def test_entry_show_latin_1_contents
-      with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-        [27, '27', '7bbf4c738e71'].each do |r1|
-          get :entry, :id => PRJ_ID,
-              :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
-              :rev => r1
-          assert_response :success
-          assert_template 'entry'
-          assert_tag :tag => 'th',
-                 :content => '1',
-                 :attributes => { :class => 'line-num' },
-                 :sibling => { :tag => 'td',
-                               :content => /test-#{@char_1}.txt/ }
-        end
-      end
-    end
-
-    def test_entry_download
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
-          :format => 'raw'
-      assert_response :success
-      # File content
-      assert @response.body.include?('WITHOUT ANY WARRANTY')
-    end
-
-    def test_entry_binary_force_download
-      get :entry, :id => PRJ_ID, :rev => 1,
-          :path => repository_path_hash(['images', 'edit.png'])[:param]
-      assert_response :success
-      assert_equal 'image/png', @response.content_type
-    end
-
-    def test_directory_entry
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entry)
-      assert_equal 'sources', assigns(:entry).name
-    end
-
-    def test_diff
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      [4, '4', 'def6d2f1254a'].each do |r1|
-        # Full diff of changeset 4
-        ['inline', 'sbs'].each do |dt|
-          get :diff, :id => PRJ_ID, :rev => r1, :type => dt
-          assert_response :success
-          assert_template 'diff'
-          if @diff_c_support
-            # Line 22 removed
-            assert_tag :tag => 'th',
-                       :content => '22',
-                       :sibling => { :tag => 'td',
-                                     :attributes => { :class => /diff_out/ },
-                                     :content => /def remove/ }
-            assert_tag :tag => 'h2', :content => /4:def6d2f1254a/
-          end
-        end
-      end
-    end
-
-    def test_diff_two_revs
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      [2, '400bb8672109', '400', 400].each do |r1|
-        [4, 'def6d2f1254a'].each do |r2|
-          ['inline', 'sbs'].each do |dt|
-            get :diff,
-                :id     => PRJ_ID,
-                :rev    => r1,
-                :rev_to => r2,
-                :type => dt
-            assert_response :success
-            assert_template 'diff'
-            diff = assigns(:diff)
-            assert_not_nil diff
-            assert_tag :tag => 'h2',
-                       :content => /4:def6d2f1254a 2:400bb8672109/
-          end
-        end
-      end
-    end
-
-    def test_diff_latin_1_path
-      with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-        [21, 'adf805632193'].each do |r1|
-          ['inline', 'sbs'].each do |dt|
-            get :diff, :id => PRJ_ID, :rev => r1, :type => dt
-            assert_response :success
-            assert_template 'diff'
-            assert_tag :tag => 'thead',
-                       :descendant => {
-                         :tag => 'th',
-                         :attributes => { :class => 'filename' } ,
-                         :content => /latin-1-dir\/test-#{@char_1}-2.txt/ ,
-                        },
-                       :sibling => {
-                         :tag => 'tbody',
-                         :descendant => {
-                            :tag => 'td',
-                            :attributes => { :class => /diff_in/ },
-                            :content => /It is written in Python/
-                         }
-                       }
-          end
-        end
-      end
-    end
-
-    def test_diff_should_show_modified_filenames
-      get :diff, :id => PRJ_ID, :rev => '400bb8672109', :type => 'inline'
-      assert_response :success
-      assert_template 'diff'
-      assert_select 'th.filename', :text => 'sources/watchers_controller.rb'
-    end
-
-    def test_diff_should_show_deleted_filenames
-      get :diff, :id => PRJ_ID, :rev => 'b3a615152df8', :type => 'inline'
-      assert_response :success
-      assert_template 'diff'
-      assert_select 'th.filename', :text => 'sources/welcome_controller.rb'
-    end
-
-    def test_annotate
-      get :annotate, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
-      assert_response :success
-      assert_template 'annotate'
-
-      # Line 22, revision 4:def6d2f1254a
-      assert_select 'tr' do
-        assert_select 'th.line-num', :text => '22'
-        assert_select 'td.revision', :text => '4:def6d2f1254a'
-        assert_select 'td.author', :text => 'jsmith'
-        assert_select 'td', :text => /remove_watcher/
-      end
-    end
-
-    def test_annotate_not_in_tip
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :annotate, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'welcome_controller.rb'])[:param]
-      assert_response 404
-      assert_error_tag :content => /was not found/
-    end
-
-    def test_annotate_at_given_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      [2, '400bb8672109', '400', 400].each do |r1|
-        get :annotate, :id => PRJ_ID, :rev => r1,
-            :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
-        assert_response :success
-        assert_template 'annotate'
-        assert_tag :tag => 'h2', :content => /@ 2:400bb8672109/
-      end
-    end
-
-    def test_annotate_latin_1_path
-      [21, '21', 'adf805632193'].each do |r1|
-        get :annotate, :id => PRJ_ID,
-            :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
-            :rev => r1
-        assert_response :success
-        assert_template 'annotate'
-        assert_select "th.line-num", :text => '1' do
-          assert_select "+ td.revision" do
-            assert_select "a", :text => '20:709858aafd1b'
-            assert_select "+ td.author", :text => "jsmith" do
-              assert_select "+ td",
-                            :text => "Mercurial is a distributed version control system."
-            end
-          end
-        end
-      end
-    end
-
-    def test_annotate_latin_1_contents
-      with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-        [27, '7bbf4c738e71'].each do |r1|
-          get :annotate, :id => PRJ_ID,
-              :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
-              :rev => r1
-          assert_tag :tag => 'th',
-                     :content => '1',
-                     :attributes => { :class => 'line-num' },
-                     :sibling => { :tag => 'td',
-                                   :content => /test-#{@char_1}.txt/ }
-        end
-      end
-    end
-
-    def test_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['1', '9d5b5b', '9d5b5b004199'].each do |r|
-        with_settings :default_language => "en" do
-          get :revision, :id => PRJ_ID, :rev => r
-          assert_response :success
-          assert_template 'revision'
-          assert_select 'title',
-                        :text => 'Revision 1:9d5b5b004199 - Added 2 files and modified one. - eCookbook Subproject 1 - Redmine'
-          end
-      end
-    end
-
-    def test_empty_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['', ' ', nil].each do |r|
-        get :revision, :id => PRJ_ID, :rev => r
-        assert_response 404
-        assert_error_tag :content => /was not found/
-      end
-    end
-
-    def test_destroy_valid_repository
-      @request.session[:user_id] = 1 # admin
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      assert_equal NUM_REV, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-
-    def test_destroy_invalid_repository
-      @request.session[:user_id] = 1 # admin
-      @project.repository.destroy
-      @repository = Repository::Mercurial.create!(
-                      :project => Project.find(PRJ_ID),
-                      :url     => "/invalid",
-                      :path_encoding => 'ISO-8859-1'
-                      )
-      @repository.fetch_changesets
-      assert_equal 0, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-  else
-    puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/32/32b666007142e154714e20e7baa96c56a45356e5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-#!/usr/bin/env ruby
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'net/http'
-require 'net/https'
-require 'uri'
-require 'optparse'
-
-module Net
-  class HTTPS < HTTP
-    def self.post_form(url, params, headers, options={})
-      request = Post.new(url.path)
-      request.form_data = params
-      request.initialize_http_header(headers)
-      request.basic_auth url.user, url.password if url.user
-      http = new(url.host, url.port)
-      http.use_ssl = (url.scheme == 'https')
-      if options[:no_check_certificate]
-        http.verify_mode = OpenSSL::SSL::VERIFY_NONE
-      end
-      http.start {|h| h.request(request) }
-    end
-  end
-end
-
-class RedmineMailHandler
-  VERSION = '0.2.3'
-
-  attr_accessor :verbose, :issue_attributes, :allow_override, :unknown_user, :default_group, :no_permission_check,
-    :url, :key, :no_check_certificate, :no_account_notice, :no_notification
-
-  def initialize
-    self.issue_attributes = {}
-
-    optparse = OptionParser.new do |opts|
-      opts.banner = "Usage: rdm-mailhandler.rb [options] --url=<Redmine URL> --key=<API key>"
-      opts.separator("")
-      opts.separator("Reads an email from standard input and forwards it to a Redmine server through a HTTP request.")
-      opts.separator("")
-      opts.separator("Required arguments:")
-      opts.on("-u", "--url URL",              "URL of the Redmine server") {|v| self.url = v}
-      opts.on("-k", "--key KEY",              "Redmine API key") {|v| self.key = v}
-      opts.separator("")
-      opts.separator("General options:")
-      opts.on("--no-permission-check",        "disable permission checking when receiving",
-                                              "the email") {self.no_permission_check = '1'}
-      opts.on("--key-file FILE",              "full path to a file that contains your Redmine",
-                                              "API key (use this option instead of --key if",
-                                              "you don't want the key to appear in the command",
-                                              "line)") {|v| read_key_from_file(v)}
-      opts.on("--no-check-certificate",       "do not check server certificate") {self.no_check_certificate = true}
-      opts.on("-h", "--help",                 "show this help") {puts opts; exit 1}
-      opts.on("-v", "--verbose",              "show extra information") {self.verbose = true}
-      opts.on("-V", "--version",              "show version information and exit") {puts VERSION; exit}
-      opts.separator("")
-      opts.separator("User creation options:")
-      opts.on("--unknown-user ACTION",        "how to handle emails from an unknown user",
-                                              "ACTION can be one of the following values:",
-                                              "* ignore: email is ignored (default)",
-                                              "* accept: accept as anonymous user",
-                                              "* create: create a user account") {|v| self.unknown_user = v}
-      opts.on("--default-group GROUP",        "add created user to GROUP (none by default)",
-                                              "GROUP can be a comma separated list of groups") { |v| self.default_group = v}
-      opts.on("--no-account-notice",          "don't send account information to the newly",
-                                              "created user") { |v| self.no_account_notice = '1'}
-      opts.on("--no-notification",            "disable email notifications for the created",
-                                              "user") { |v| self.no_notification = '1'}
-      opts.separator("")
-      opts.separator("Issue attributes control options:")
-      opts.on("-p", "--project PROJECT",      "identifier of the target project") {|v| self.issue_attributes['project'] = v}
-      opts.on("-s", "--status STATUS",        "name of the target status") {|v| self.issue_attributes['status'] = v}
-      opts.on("-t", "--tracker TRACKER",      "name of the target tracker") {|v| self.issue_attributes['tracker'] = v}
-      opts.on(      "--category CATEGORY",    "name of the target category") {|v| self.issue_attributes['category'] = v}
-      opts.on(      "--priority PRIORITY",    "name of the target priority") {|v| self.issue_attributes['priority'] = v}
-      opts.on("-o", "--allow-override ATTRS", "allow email content to override attributes",
-                                              "specified by previous options",
-                                              "ATTRS is a comma separated list of attributes") {|v| self.allow_override = v}
-      opts.separator("")
-      opts.separator("Examples:")
-      opts.separator("No project specified, emails MUST contain the 'Project' keyword:")
-      opts.separator("  rdm-mailhandler.rb --url http://redmine.domain.foo --key secret")
-      opts.separator("")
-      opts.separator("Fixed project and default tracker specified, but emails can override")
-      opts.separator("both tracker and priority attributes using keywords:")
-      opts.separator("  rdm-mailhandler.rb --url https://domain.foo/redmine --key secret \\")
-      opts.separator("    --project foo \\")
-      opts.separator("    --tracker bug \\")
-      opts.separator("    --allow-override tracker,priority")
-
-      opts.summary_width = 27
-    end
-    optparse.parse!
-
-    unless url && key
-      puts "Some arguments are missing. Use `rdm-mailhandler.rb --help` for getting help."
-      exit 1
-    end
-  end
-
-  def submit(email)
-    uri = url.gsub(%r{/*$}, '') + '/mail_handler'
-
-    headers = { 'User-Agent' => "Redmine mail handler/#{VERSION}" }
-
-    data = { 'key' => key, 'email' => email,
-                           'allow_override' => allow_override,
-                           'unknown_user' => unknown_user,
-                           'default_group' => default_group,
-                           'no_account_notice' => no_account_notice,
-                           'no_notification' => no_notification,
-                           'no_permission_check' => no_permission_check}
-    issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
-
-    debug "Posting to #{uri}..."
-    begin
-      response = Net::HTTPS.post_form(URI.parse(uri), data, headers, :no_check_certificate => no_check_certificate)
-    rescue SystemCallError => e # connection refused, etc.
-      warn "An error occured while contacting your Redmine server: #{e.message}"
-      return 75 # temporary failure
-    end
-    debug "Response received: #{response.code}"
-
-    case response.code.to_i
-      when 403
-        warn "Request was denied by your Redmine server. " +
-             "Make sure that 'WS for incoming emails' is enabled in application settings and that you provided the correct API key."
-        return 77
-      when 422
-        warn "Request was denied by your Redmine server. " +
-             "Possible reasons: email is sent from an invalid email address or is missing some information."
-        return 77
-      when 400..499
-        warn "Request was denied by your Redmine server (#{response.code})."
-        return 77
-      when 500..599
-        warn "Failed to contact your Redmine server (#{response.code})."
-        return 75
-      when 201
-        debug "Proccessed successfully"
-        return 0
-      else
-        return 1
-    end
-  end
-
-  private
-
-  def debug(msg)
-    puts msg if verbose
-  end
-
-  def read_key_from_file(filename)
-    begin
-      self.key = File.read(filename).strip
-    rescue Exception => e
-      $stderr.puts "Unable to read the key from #{filename}:\n#{e.message}"
-      exit 1
-    end
-  end
-end
-
-handler = RedmineMailHandler.new
-exit(handler.submit(STDIN.read))
--- a/.svn/pristine/33/339df18b16b4ab05fedfba76e31080e6dda3b82a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingMailHandlerTest < ActionController::IntegrationTest
-  def test_mail_handler
-    assert_routing(
-        { :method => "post", :path => "/mail_handler" },
-        { :controller => 'mail_handler', :action => 'index' }
-      )
-  end
-end
--- a/.svn/pristine/35/35e985416112eca8f5c8494cbf66a6a622c59107.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class CalendarsControllerTest < ActionController::TestCase
-  fixtures :projects,
-           :trackers,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def test_show
-    get :show, :project_id => 1
-    assert_response :success
-    assert_template 'calendar'
-    assert_not_nil assigns(:calendar)
-  end
-
-  def test_show_should_run_custom_queries
-    @query = IssueQuery.create!(:name => 'Calendar', :visibility => IssueQuery::VISIBILITY_PUBLIC)
-
-    get :show, :query_id => @query.id
-    assert_response :success
-  end
-
-  def test_cross_project_calendar
-    get :show
-    assert_response :success
-    assert_template 'calendar'
-    assert_not_nil assigns(:calendar)
-  end
-
-  def test_week_number_calculation
-    Setting.start_of_week = 7
-
-    get :show, :month => '1', :year => '2010'
-    assert_response :success
-
-    assert_select 'tr' do
-      assert_select 'td.week-number', :text => '53'
-      assert_select 'td.odd', :text => '27'
-      assert_select 'td.even', :text => '2'
-    end
-
-    assert_select 'tr' do
-      assert_select 'td.week-number', :text => '1'
-      assert_select 'td.odd', :text => '3'
-      assert_select 'td.even', :text => '9'
-    end
-
-    Setting.start_of_week = 1
-    get :show, :month => '1', :year => '2010'
-    assert_response :success
-
-    assert_select 'tr' do
-      assert_select 'td.week-number', :text => '53'
-      assert_select 'td.even', :text => '28'
-      assert_select 'td.even', :text => '3'
-    end
-
-    assert_select 'tr' do
-      assert_select 'td.week-number', :text => '1'
-      assert_select 'td.even', :text => '4'
-      assert_select 'td.even', :text => '10'
-    end
-  end
-end
--- a/.svn/pristine/37/3761b0e47a324667f29e56ceb9695ed94f68fe4d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class AutoCompletesController < ApplicationController
-  before_filter :find_project
-
-  def issues
-    @issues = []
-    q = (params[:q] || params[:term]).to_s.strip
-    if q.present?
-      scope = (params[:scope] == "all" || @project.nil? ? Issue : @project.issues).visible
-      if q.match(/\A#?(\d+)\z/)
-        @issues << scope.find_by_id($1.to_i)
-      end
-      @issues += scope.where("LOWER(#{Issue.table_name}.subject) LIKE LOWER(?)", "%#{q}%").order("#{Issue.table_name}.id DESC").limit(10).all
-      @issues.compact!
-    end
-    render :layout => false
-  end
-
-  private
-
-  def find_project
-    if params[:project_id].present?
-      @project = Project.find(params[:project_id])
-    end
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/39/390d75b45f1cb36da0ca09b41de1406635eaa338.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1123 +0,0 @@
-pt-BR:
-  direction: ltr
-  date:
-    formats:
-      default: "%d/%m/%Y"
-      short: "%d de %B"
-      long: "%d de %B de %Y"
-      only_day: "%d"
-
-    day_names: [Domingo, Segunda, Terça, Quarta, Quinta, Sexta, Sábado]
-    abbr_day_names: [Dom, Seg, Ter, Qua, Qui, Sex, Sáb]
-    month_names: [~, Janeiro, Fevereiro, Março, Abril, Maio, Junho, Julho, Agosto, Setembro, Outubro, Novembro, Dezembro]
-    abbr_month_names: [~, Jan, Fev, Mar, Abr, Mai, Jun, Jul, Ago, Set, Out, Nov, Dez]
-    order:
-      - :day
-      - :month
-      - :year
-
-  time:
-    formats:
-      default: "%A, %d de %B de %Y, %H:%M h"
-      time: "%H:%M h"
-      short: "%d/%m, %H:%M h"
-      long: "%A, %d de %B de %Y, %H:%M h"
-      only_second: "%S"
-      datetime:
-        formats:
-          default: "%Y-%m-%dT%H:%M:%S%Z"
-    am: ''
-    pm: ''
-
-  # date helper distancia em palavras
-  datetime:
-    distance_in_words:
-      half_a_minute: 'meio minuto'
-      less_than_x_seconds:
-        one: 'menos de 1 segundo'
-        other: 'menos de %{count} segundos'
-
-      x_seconds:
-        one: '1 segundo'
-        other: '%{count} segundos'
-
-      less_than_x_minutes:
-        one: 'menos de um minuto'
-        other: 'menos de %{count} minutos'
-
-      x_minutes:
-        one: '1 minuto'
-        other: '%{count} minutos'
-
-      about_x_hours:
-        one: 'aproximadamente 1 hora'
-        other: 'aproximadamente %{count} horas'
-      x_hours:
-        one:   "1 hora"
-        other: "%{count} horas"
-
-      x_days:
-        one: '1 dia'
-        other: '%{count} dias'
-
-      about_x_months:
-        one: 'aproximadamente 1 mês'
-        other: 'aproximadamente %{count} meses'
-
-      x_months:
-        one: '1 mês'
-        other: '%{count} meses'
-
-      about_x_years:
-        one: 'aproximadamente 1 ano'
-        other: 'aproximadamente %{count} anos'
-
-      over_x_years:
-        one: 'mais de 1 ano'
-        other: 'mais de %{count} anos'
-      almost_x_years:
-        one:   "quase 1 ano"
-        other: "quase %{count} anos"
-
-  # numeros
-  number:
-    format:
-      precision: 3
-      separator: ','
-      delimiter: '.'
-    currency:
-      format:
-        unit: 'R$'
-        precision: 2
-        format: '%u %n'
-        separator: ','
-        delimiter: '.'
-    percentage:
-      format:
-        delimiter: '.'
-    precision:
-      format:
-        delimiter: '.'
-    human:
-      format:
-        precision: 3
-        delimiter: '.'
-      storage_units:
-        format: "%n %u"
-        units:
-          byte:
-            one: "Byte"
-            other: "Bytes"
-          kb: "KB"
-          mb: "MB"
-          gb: "GB"
-          tb: "TB"
-  support:
-    array:
-      sentence_connector: "e"
-      skip_last_comma: true
-
-  # Active Record
-  activerecord:
-    errors:
-      template:
-        header:
-          one: "modelo não pode ser salvo: 1 erro"
-          other: "modelo não pode ser salvo: %{count} erros."
-        body: "Por favor, verifique os seguintes campos:"
-      messages:
-        inclusion: "não está incluso na lista"
-        exclusion: "não está disponível"
-        invalid: "não é válido"
-        confirmation: "não está de acordo com a confirmação"
-        accepted: "precisa ser aceito"
-        empty: "não pode ficar vazio"
-        blank: "não pode ficar vazio"
-        too_long: "é muito longo (máximo: %{count} caracteres)"
-        too_short: "é muito curto (mínimo: %{count} caracteres)"
-        wrong_length: "deve ter %{count} caracteres"
-        taken: "não está disponível"
-        not_a_number: "não é um número"
-        greater_than: "precisa ser maior do que %{count}"
-        greater_than_or_equal_to: "precisa ser maior ou igual a %{count}"
-        equal_to: "precisa ser igual a %{count}"
-        less_than: "precisa ser menor do que %{count}"
-        less_than_or_equal_to: "precisa ser menor ou igual a %{count}"
-        odd: "precisa ser ímpar"
-        even: "precisa ser par"
-        greater_than_start_date: "deve ser maior que a data inicial"
-        not_same_project: "não pertence ao mesmo projeto"
-        circular_dependency: "Esta relação geraria uma dependência circular"
-        cant_link_an_issue_with_a_descendant: "Uma tarefa não pode ser relaciona a uma de suas subtarefas"
-        earlier_than_minimum_start_date: "cannot be earlier than %{date} because of preceding issues"
-
-  actionview_instancetag_blank_option: Selecione
-
-  general_text_No: 'Não'
-  general_text_Yes: 'Sim'
-  general_text_no: 'não'
-  general_text_yes: 'sim'
-  general_lang_name: 'Português(Brasil)'
-  general_csv_separator: ';'
-  general_csv_decimal_separator: ','
-  general_csv_encoding: ISO-8859-1
-  general_pdf_encoding: UTF-8
-  general_first_day_of_week: '1'
-
-  notice_account_updated: Conta atualizada com sucesso.
-  notice_account_invalid_creditentials: Usuário ou senha inválido.
-  notice_account_password_updated: Senha alterada com sucesso.
-  notice_account_wrong_password: Senha inválida.
-  notice_account_register_done: Conta criada com sucesso. Para ativar sua conta, clique no link que lhe foi enviado por e-mail.
-  notice_account_unknown_email: Usuário desconhecido.
-  notice_can_t_change_password: Esta conta utiliza autenticação externa. Não é possível alterar a senha.
-  notice_account_lost_email_sent: Um e-mail com instruções para escolher uma nova senha foi enviado para você.
-  notice_account_activated: Sua conta foi ativada. Você pode acessá-la agora.
-  notice_successful_create: Criado com sucesso.
-  notice_successful_update: Alterado com sucesso.
-  notice_successful_delete: Excluído com sucesso.
-  notice_successful_connection: Conectado com sucesso.
-  notice_file_not_found: A página que você está tentando acessar não existe ou foi excluída.
-  notice_locking_conflict: Os dados foram atualizados por outro usuário.
-  notice_not_authorized: Você não está autorizado a acessar esta página.
-  notice_email_sent: "Um e-mail foi enviado para %{value}"
-  notice_email_error: "Ocorreu um erro ao enviar o e-mail (%{value})"
-  notice_feeds_access_key_reseted: Sua chave Atom foi reconfigurada.
-  notice_failed_to_save_issues: "Problema ao salvar %{count} tarefa(s) de %{total} selecionadas: %{ids}."
-  notice_no_issue_selected: "Nenhuma tarefa selecionada! Por favor, marque as tarefas que você deseja editar."
-  notice_account_pending: "Sua conta foi criada e está aguardando aprovação do administrador."
-  notice_default_data_loaded: Configuração padrão carregada com sucesso.
-
-  error_can_t_load_default_data: "A configuração padrão não pode ser carregada: %{value}"
-  error_scm_not_found: "A entrada e/ou a revisão não existe no repositório."
-  error_scm_command_failed: "Ocorreu um erro ao tentar acessar o repositório: %{value}"
-  error_scm_annotate: "Esta entrada não existe ou não pode ser anotada."
-  error_issue_not_found_in_project: 'A tarefa não foi encontrada ou não pertence a este projeto'
-  error_no_tracker_in_project: 'Não há um tipo de tarefa associado a este projeto. Favor verificar as configurações do projeto.'
-  error_no_default_issue_status: 'A situação padrão para tarefa não está definida. Favor verificar sua configuração (Vá em "Administração -> Situação da tarefa").'
-
-  mail_subject_lost_password: "Sua senha do %{value}."
-  mail_body_lost_password: 'Para mudar sua senha, clique no link abaixo:'
-  mail_subject_register: "Ativação de conta do %{value}."
-  mail_body_register: 'Para ativar sua conta, clique no link abaixo:'
-  mail_body_account_information_external: "Você pode usar sua conta do %{value} para entrar."
-  mail_body_account_information: Informações sobre sua conta
-  mail_subject_account_activation_request: "%{value} - Requisição de ativação de conta"
-  mail_body_account_activation_request: "Um novo usuário (%{value}) se registrou. A conta está aguardando sua aprovação:"
-  mail_subject_reminder: "%{count} tarefa(s) com data prevista para os próximos %{days} dias"
-  mail_body_reminder: "%{count} tarefa(s) para você com data prevista para os próximos %{days} dias:"
-
-
-  field_name: Nome
-  field_description: Descrição
-  field_summary: Resumo
-  field_is_required: Obrigatório
-  field_firstname: Nome
-  field_lastname: Sobrenome
-  field_mail: E-mail
-  field_filename: Arquivo
-  field_filesize: Tamanho
-  field_downloads: Downloads
-  field_author: Autor
-  field_created_on: Criado em
-  field_updated_on: Alterado em
-  field_field_format: Formato
-  field_is_for_all: Para todos os projetos
-  field_possible_values: Possíveis valores
-  field_regexp: Expressão regular
-  field_min_length: Tamanho mínimo
-  field_max_length: Tamanho máximo
-  field_value: Valor
-  field_category: Categoria
-  field_title: Título
-  field_project: Projeto
-  field_issue: Tarefa
-  field_status: Situação
-  field_notes: Notas
-  field_is_closed: Tarefa fechada
-  field_is_default: Situação padrão
-  field_tracker: Tipo
-  field_subject: Título
-  field_due_date: Data prevista
-  field_assigned_to: Atribuído para
-  field_priority: Prioridade
-  field_fixed_version: Versão
-  field_user: Usuário
-  field_role: Cargo
-  field_homepage: Página do projeto
-  field_is_public: Público
-  field_parent: Sub-projeto de
-  field_is_in_roadmap: Exibir no planejamento
-  field_login: Usuário
-  field_mail_notification: Notificações por e-mail
-  field_admin: Administrador
-  field_last_login_on: Última conexão
-  field_language: Idioma
-  field_effective_date: Data
-  field_password: Senha
-  field_new_password: Nova senha
-  field_password_confirmation: Confirmação
-  field_version: Versão
-  field_type: Tipo
-  field_host: Servidor
-  field_port: Porta
-  field_account: Conta
-  field_base_dn: DN Base
-  field_attr_login: Atributo para nome de usuário
-  field_attr_firstname: Atributo para nome
-  field_attr_lastname: Atributo para sobrenome
-  field_attr_mail: Atributo para e-mail
-  field_onthefly: Criar usuários dinamicamente ("on-the-fly")
-  field_start_date: Início
-  field_done_ratio: "% Terminado"
-  field_auth_source: Modo de autenticação
-  field_hide_mail: Ocultar meu e-mail
-  field_comments: Comentário
-  field_url: URL
-  field_start_page: Página inicial
-  field_subproject: Subprojeto
-  field_hours: Horas
-  field_activity: Atividade
-  field_spent_on: Data
-  field_identifier: Identificador
-  field_is_filter: É um filtro
-  field_issue_to: Tarefa relacionada
-  field_delay: Atraso
-  field_assignable: Tarefas podem ser atribuídas a este papel
-  field_redirect_existing_links: Redirecionar links existentes
-  field_estimated_hours: Tempo estimado
-  field_column_names: Colunas
-  field_time_zone: Fuso-horário
-  field_searchable: Pesquisável
-  field_default_value: Padrão
-  field_comments_sorting: Visualizar comentários
-  field_parent_title: Página pai
-
-  setting_app_title: Título da aplicação
-  setting_app_subtitle: Subtítulo da aplicação
-  setting_welcome_text: Texto de boas-vindas
-  setting_default_language: Idioma padrão
-  setting_login_required: Exigir autenticação
-  setting_self_registration: Permitido Auto-registro
-  setting_attachment_max_size: Tamanho máximo do anexo
-  setting_issues_export_limit: Limite de exportação das tarefas
-  setting_mail_from: E-mail enviado de
-  setting_bcc_recipients: Enviar com cópia oculta (cco)
-  setting_host_name: Nome do Servidor e subdomínio
-  setting_text_formatting: Formatação do texto
-  setting_wiki_compression: Compactação de histórico do Wiki
-  setting_feeds_limit: Número de registros por Feed
-  setting_default_projects_public: Novos projetos são públicos por padrão
-  setting_autofetch_changesets: Obter commits automaticamente
-  setting_sys_api_enabled: Ativa WS para gerenciamento do repositório (SVN)
-  setting_commit_ref_keywords: Palavras-chave de referência
-  setting_commit_fix_keywords: Definição de palavras-chave
-  setting_autologin: Auto-login
-  setting_date_format: Formato da data
-  setting_time_format: Formato de hora
-  setting_cross_project_issue_relations: Permitir relacionar tarefas entre projetos
-  setting_issue_list_default_columns: Colunas padrão visíveis na lista de tarefas
-  setting_emails_footer: Rodapé do e-mail
-  setting_protocol: Protocolo
-  setting_per_page_options: Número de itens exibidos por página
-  setting_user_format: Formato de exibição de nome de usuário
-  setting_activity_days_default: Dias visualizados na atividade do projeto
-  setting_display_subprojects_issues: Visualizar tarefas dos subprojetos nos projetos principais por padrão
-  setting_enabled_scm: SCM habilitados
-  setting_mail_handler_api_enabled: Habilitar WS para e-mails de entrada
-  setting_mail_handler_api_key: Chave de API
-  setting_sequential_project_identifiers: Gerar identificadores sequenciais de projeto
-
-  project_module_issue_tracking: Gerenciamento de Tarefas
-  project_module_time_tracking: Gerenciamento de tempo
-  project_module_news: Notícias
-  project_module_documents: Documentos
-  project_module_files: Arquivos
-  project_module_wiki: Wiki
-  project_module_repository: Repositório
-  project_module_boards: Fóruns
-
-  label_user: Usuário
-  label_user_plural: Usuários
-  label_user_new: Novo usuário
-  label_project: Projeto
-  label_project_new: Novo projeto
-  label_project_plural: Projetos
-  label_x_projects:
-    zero:  nenhum projeto
-    one:   1 projeto
-    other: "%{count} projetos"
-  label_project_all: Todos os projetos
-  label_project_latest: Últimos projetos
-  label_issue: Tarefa
-  label_issue_new: Nova tarefa
-  label_issue_plural: Tarefas
-  label_issue_view_all: Ver todas as tarefas
-  label_issues_by: "Tarefas por %{value}"
-  label_issue_added: Tarefa adicionada
-  label_issue_updated: Tarefa atualizada
-  label_issue_note_added: Nota adicionada
-  label_issue_status_updated: Situação atualizada
-  label_issue_priority_updated: Prioridade atualizada
-  label_document: Documento
-  label_document_new: Novo documento
-  label_document_plural: Documentos
-  label_document_added: Documento adicionado
-  label_role: Papel
-  label_role_plural: Papéis
-  label_role_new: Novo papel
-  label_role_and_permissions: Papéis e permissões
-  label_member: Membro
-  label_member_new: Novo membro
-  label_member_plural: Membros
-  label_tracker: Tipo de tarefa
-  label_tracker_plural: Tipos de tarefas
-  label_tracker_new: Novo tipo
-  label_workflow: Fluxo de trabalho
-  label_issue_status: Situação da tarefa
-  label_issue_status_plural: Situação das tarefas
-  label_issue_status_new: Nova situação
-  label_issue_category: Categoria da tarefa
-  label_issue_category_plural: Categorias das tarefas
-  label_issue_category_new: Nova categoria
-  label_custom_field: Campo personalizado
-  label_custom_field_plural: Campos personalizados
-  label_custom_field_new: Novo campo personalizado
-  label_enumerations: 'Tipos & Categorias'
-  label_enumeration_new: Novo
-  label_information: Informação
-  label_information_plural: Informações
-  label_please_login: Efetue o login
-  label_register: Cadastre-se
-  label_password_lost: Perdi minha senha
-  label_home: Página inicial
-  label_my_page: Minha página
-  label_my_account: Minha conta
-  label_my_projects: Meus projetos
-  label_administration: Administração
-  label_login: Entrar
-  label_logout: Sair
-  label_help: Ajuda
-  label_reported_issues: Tarefas reportadas
-  label_assigned_to_me_issues: Minhas tarefas
-  label_last_login: Última conexão
-  label_registered_on: Registrado em
-  label_activity: Atividade
-  label_overall_activity: Atividades gerais
-  label_new: Novo
-  label_logged_as: "Acessando como:"
-  label_environment: Ambiente
-  label_authentication: Autenticação
-  label_auth_source: Modo de autenticação
-  label_auth_source_new: Novo modo de autenticação
-  label_auth_source_plural: Modos de autenticação
-  label_subproject_plural: Subprojetos
-  label_and_its_subprojects: "%{value} e seus subprojetos"
-  label_min_max_length: Tamanho mín-máx
-  label_list: Lista
-  label_date: Data
-  label_integer: Inteiro
-  label_float: Decimal
-  label_boolean: Boleano
-  label_string: Texto
-  label_text: Texto longo
-  label_attribute: Atributo
-  label_attribute_plural: Atributos
-  label_no_data: Nenhuma informação disponível
-  label_change_status: Alterar situação
-  label_history: Histórico
-  label_attachment: Arquivo
-  label_attachment_new: Novo arquivo
-  label_attachment_delete: Excluir arquivo
-  label_attachment_plural: Arquivos
-  label_file_added: Arquivo adicionado
-  label_report: Relatório
-  label_report_plural: Relatório
-  label_news: Notícia
-  label_news_new: Adicionar notícia
-  label_news_plural: Notícias
-  label_news_latest: Últimas notícias
-  label_news_view_all: Ver todas as notícias
-  label_news_added: Notícia adicionada
-  label_settings: Configurações
-  label_overview: Visão geral
-  label_version: Versão
-  label_version_new: Nova versão
-  label_version_plural: Versões
-  label_confirmation: Confirmação
-  label_export_to: Exportar para
-  label_read: Ler...
-  label_public_projects: Projetos públicos
-  label_open_issues: Aberta
-  label_open_issues_plural: Abertas
-  label_closed_issues: Fechada
-  label_closed_issues_plural: Fechadas
-  label_x_open_issues_abbr_on_total:
-    zero:  0 aberta / %{total}
-    one:   1 aberta / %{total}
-    other: "%{count} abertas / %{total}"
-  label_x_open_issues_abbr:
-    zero:  0 aberta
-    one:   1 aberta
-    other: "%{count} abertas"
-  label_x_closed_issues_abbr:
-    zero:  0 fechada
-    one:   1 fechada
-    other: "%{count} fechadas"
-  label_total: Total
-  label_permissions: Permissões
-  label_current_status: Situação atual
-  label_new_statuses_allowed: Nova situação permitida
-  label_all: todos
-  label_none: nenhum
-  label_nobody: ninguém
-  label_next: Próximo
-  label_previous: Anterior
-  label_used_by: Usado por
-  label_details: Detalhes
-  label_add_note: Adicionar nota
-  label_per_page: Por página
-  label_calendar: Calendário
-  label_months_from: meses a partir de
-  label_gantt: Gantt
-  label_internal: Interno
-  label_last_changes: "últimas %{count} alterações"
-  label_change_view_all: Mostrar todas as alterações
-  label_personalize_page: Personalizar esta página
-  label_comment: Comentário
-  label_comment_plural: Comentários
-  label_x_comments:
-    zero: nenhum comentário
-    one: 1 comentário
-    other: "%{count} comentários"
-  label_comment_add: Adicionar comentário
-  label_comment_added: Comentário adicionado
-  label_comment_delete: Excluir comentário
-  label_query: Consulta personalizada
-  label_query_plural: Consultas personalizadas
-  label_query_new: Nova consulta
-  label_filter_add: Adicionar filtro
-  label_filter_plural: Filtros
-  label_equals: igual a
-  label_not_equals: diferente de
-  label_in_less_than: maior que
-  label_in_more_than: menor que
-  label_in: em
-  label_today: hoje
-  label_all_time: tudo
-  label_yesterday: ontem
-  label_this_week: esta semana
-  label_last_week: última semana
-  label_last_n_days: "últimos %{count} dias"
-  label_this_month: este mês
-  label_last_month: último mês
-  label_this_year: este ano
-  label_date_range: Período
-  label_less_than_ago: menos de
-  label_more_than_ago: mais de
-  label_ago: dias atrás
-  label_contains: contém
-  label_not_contains: não contém
-  label_day_plural: dias
-  label_repository: Repositório
-  label_repository_plural: Repositórios
-  label_browse: Procurar
-  label_revision: Revisão
-  label_revision_plural: Revisões
-  label_associated_revisions: Revisões associadas
-  label_added: adicionada
-  label_modified: alterada
-  label_deleted: excluída
-  label_latest_revision: Última revisão
-  label_latest_revision_plural: Últimas revisões
-  label_view_revisions: Ver revisões
-  label_max_size: Tamanho máximo
-  label_sort_highest: Mover para o início
-  label_sort_higher: Mover para cima
-  label_sort_lower: Mover para baixo
-  label_sort_lowest: Mover para o fim
-  label_roadmap: Planejamento
-  label_roadmap_due_in: "Previsto para %{value}"
-  label_roadmap_overdue: "%{value} atrasado"
-  label_roadmap_no_issues: Sem tarefas para esta versão
-  label_search: Busca
-  label_result_plural: Resultados
-  label_all_words: Todas as palavras
-  label_wiki: Wiki
-  label_wiki_edit: Editar Wiki
-  label_wiki_edit_plural: Edições Wiki
-  label_wiki_page: Página Wiki
-  label_wiki_page_plural: páginas Wiki
-  label_index_by_title: Índice por título
-  label_index_by_date: Índice por data
-  label_current_version: Versão atual
-  label_preview: Pré-visualizar
-  label_feed_plural: Feeds
-  label_changes_details: Detalhes de todas as alterações
-  label_issue_tracking: Tarefas
-  label_spent_time: Tempo gasto
-  label_f_hour: "%{value} hora"
-  label_f_hour_plural: "%{value} horas"
-  label_time_tracking: Registro de horas
-  label_change_plural: Alterações
-  label_statistics: Estatísticas
-  label_commits_per_month: Commits por mês
-  label_commits_per_author: Commits por autor
-  label_view_diff: Ver diferenças
-  label_diff_inline: em linha
-  label_diff_side_by_side: lado a lado
-  label_options: Opções
-  label_copy_workflow_from: Copiar fluxo de trabalho de
-  label_permissions_report: Relatório de permissões
-  label_watched_issues: Tarefas observadas
-  label_related_issues: Tarefas relacionadas
-  label_applied_status: Situação alterada
-  label_loading: Carregando...
-  label_relation_new: Nova relação
-  label_relation_delete: Excluir relação
-  label_relates_to: relacionado a
-  label_duplicates: duplica
-  label_duplicated_by: duplicado por
-  label_blocks: bloqueia
-  label_blocked_by: bloqueado por
-  label_precedes: precede
-  label_follows: segue
-  label_end_to_start: fim para o início
-  label_end_to_end: fim para fim
-  label_start_to_start: início para início
-  label_start_to_end: início para fim
-  label_stay_logged_in: Permanecer logado
-  label_disabled: desabilitado
-  label_show_completed_versions: Exibir versões completas
-  label_me: mim
-  label_board: Fórum
-  label_board_new: Novo fórum
-  label_board_plural: Fóruns
-  label_topic_plural: Tópicos
-  label_message_plural: Mensagens
-  label_message_last: Última mensagem
-  label_message_new: Nova mensagem
-  label_message_posted: Mensagem enviada
-  label_reply_plural: Respostas
-  label_send_information: Enviar informação da nova conta para o usuário
-  label_year: Ano
-  label_month: Mês
-  label_week: Semana
-  label_date_from: De
-  label_date_to: Para
-  label_language_based: Com base no idioma do usuário
-  label_sort_by: "Ordenar por %{value}"
-  label_send_test_email: Enviar um e-mail de teste
-  label_feeds_access_key_created_on: "chave de acesso Atom criada %{value} atrás"
-  label_module_plural: Módulos
-  label_added_time_by: "Adicionado por %{author} %{age} atrás"
-  label_updated_time: "Atualizado %{value} atrás"
-  label_jump_to_a_project: Ir para o projeto...
-  label_file_plural: Arquivos
-  label_changeset_plural: Conjunto de alterações
-  label_default_columns: Colunas padrão
-  label_no_change_option: (Sem alteração)
-  label_bulk_edit_selected_issues: Edição em massa das tarefas selecionadas.
-  label_theme: Tema
-  label_default: Padrão
-  label_search_titles_only: Pesquisar somente títulos
-  label_user_mail_option_all: "Para qualquer evento em todos os meus projetos"
-  label_user_mail_option_selected: "Para qualquer evento somente no(s) projeto(s) selecionado(s)..."
-  label_user_mail_no_self_notified: "Eu não quero ser notificado de minhas próprias modificações"
-  label_registration_activation_by_email: ativação de conta por e-mail
-  label_registration_manual_activation: ativação manual de conta
-  label_registration_automatic_activation: ativação automática de conta
-  label_display_per_page: "Por página: %{value}"
-  label_age: Idade
-  label_change_properties: Alterar propriedades
-  label_general: Geral
-  label_more: Mais
-  label_scm: 'Controle de versão:'
-  label_plugins: Plugins
-  label_ldap_authentication: Autenticação LDAP
-  label_downloads_abbr: D/L
-  label_optional_description: Descrição opcional
-  label_add_another_file: Adicionar outro arquivo
-  label_preferences: Preferências
-  label_chronological_order: Em ordem cronológica
-  label_reverse_chronological_order: Em ordem cronológica inversa
-  label_planning: Planejamento
-  label_incoming_emails: E-mails recebidos
-  label_generate_key: Gerar uma chave
-  label_issue_watchers: Observadores
-
-  button_login: Entrar
-  button_submit: Enviar
-  button_save: Salvar
-  button_check_all: Marcar todos
-  button_uncheck_all: Desmarcar todos
-  button_delete: Excluir
-  button_create: Criar
-  button_test: Testar
-  button_edit: Editar
-  button_add: Adicionar
-  button_change: Alterar
-  button_apply: Aplicar
-  button_clear: Limpar
-  button_lock: Bloquear
-  button_unlock: Desbloquear
-  button_download: Baixar
-  button_list: Listar
-  button_view: Ver
-  button_move: Mover
-  button_back: Voltar
-  button_cancel: Cancelar
-  button_activate: Ativar
-  button_sort: Ordenar
-  button_log_time: Tempo de trabalho
-  button_rollback: Voltar para esta versão
-  button_watch: Observar
-  button_unwatch: Parar de observar
-  button_reply: Responder
-  button_archive: Arquivar
-  button_unarchive: Desarquivar
-  button_reset: Redefinir
-  button_rename: Renomear
-  button_change_password: Alterar senha
-  button_copy: Copiar
-  button_annotate: Anotar
-  button_update: Atualizar
-  button_configure: Configurar
-  button_quote: Responder
-
-  status_active: ativo
-  status_registered: registrado
-  status_locked: bloqueado
-
-  text_select_mail_notifications: Ações a serem notificadas por e-mail
-  text_regexp_info: ex. ^[A-Z0-9]+$
-  text_min_max_length_info: 0 = sem restrição
-  text_project_destroy_confirmation: Você tem certeza que deseja excluir este projeto e todos os dados relacionados?
-  text_subprojects_destroy_warning: "Seu(s) subprojeto(s): %{value} também serão excluídos."
-  text_workflow_edit: Selecione um papel e um tipo de tarefa para editar o fluxo de trabalho
-  text_are_you_sure: Você tem certeza?
-  text_tip_issue_begin_day: tarefa inicia neste dia
-  text_tip_issue_end_day: tarefa termina neste dia
-  text_tip_issue_begin_end_day: tarefa inicia e termina neste dia
-  text_caracters_maximum: "máximo %{count} caracteres"
-  text_caracters_minimum: "deve ter ao menos %{count} caracteres."
-  text_length_between: "deve ter entre %{min} e %{max} caracteres."
-  text_tracker_no_workflow: Sem fluxo de trabalho definido para este tipo.
-  text_unallowed_characters: Caracteres não permitidos
-  text_comma_separated: Múltiplos valores são permitidos (separados por vírgula).
-  text_issues_ref_in_commit_messages: Referenciando tarefas nas mensagens de commit
-  text_issue_added: "Tarefa %{id} incluída (por %{author})."
-  text_issue_updated: "Tarefa %{id} alterada (por %{author})."
-  text_wiki_destroy_confirmation: Você tem certeza que deseja excluir este wiki e TODO o seu conteúdo?
-  text_issue_category_destroy_question: "Algumas tarefas (%{count}) estão atribuídas a esta categoria. O que você deseja fazer?"
-  text_issue_category_destroy_assignments: Remover atribuições da categoria
-  text_issue_category_reassign_to: Redefinir tarefas para esta categoria
-  text_user_mail_option: "Para projetos (não selecionados), você somente receberá notificações sobre o que você está observando ou está envolvido (ex. tarefas das quais você é o autor ou que estão atribuídas a você)"
-  text_no_configuration_data: "Os Papéis, tipos de tarefas, situação de tarefas e fluxos de trabalho não foram configurados ainda.\nÉ altamente recomendado carregar as configurações padrão. Você poderá modificar estas configurações assim que carregadas."
-  text_load_default_configuration: Carregar a configuração padrão
-  text_status_changed_by_changeset: "Aplicado no conjunto de alterações %{value}."
-  text_issues_destroy_confirmation: 'Você tem certeza que deseja excluir a(s) tarefa(s) selecionada(s)?'
-  text_select_project_modules: 'Selecione módulos para habilitar para este projeto:'
-  text_default_administrator_account_changed: Conta padrão do administrador alterada
-  text_file_repository_writable: Repositório com permissão de escrita
-  text_rmagick_available: RMagick disponível (opcional)
-  text_destroy_time_entries_question: "%{hours} horas de trabalho foram registradas nas tarefas que você está excluindo. O que você deseja fazer?"
-  text_destroy_time_entries: Excluir horas de trabalho
-  text_assign_time_entries_to_project: Atribuir estas horas de trabalho para outro projeto
-  text_reassign_time_entries: 'Atribuir horas reportadas para esta tarefa:'
-  text_user_wrote: "%{value} escreveu:"
-  text_enumeration_destroy_question: "%{count} objetos estão atribuídos a este valor."
-  text_enumeration_category_reassign_to: 'Reatribuí-los ao valor:'
-  text_email_delivery_not_configured: "O envio de e-mail não está configurado, e as notificações estão inativas.\nConfigure seu servidor SMTP no arquivo config/configuration.yml e reinicie a aplicação para ativá-las."
-
-  default_role_manager: Gerente
-  default_role_developer: Desenvolvedor
-  default_role_reporter: Informante
-  default_tracker_bug: Defeito
-  default_tracker_feature: Funcionalidade
-  default_tracker_support: Suporte
-  default_issue_status_new: Nova
-  default_issue_status_in_progress: Em andamento
-  default_issue_status_resolved: Resolvida
-  default_issue_status_feedback: Feedback
-  default_issue_status_closed: Fechada
-  default_issue_status_rejected: Rejeitada
-  default_doc_category_user: Documentação do usuário
-  default_doc_category_tech: Documentação técnica
-  default_priority_low: Baixa
-  default_priority_normal: Normal
-  default_priority_high: Alta
-  default_priority_urgent: Urgente
-  default_priority_immediate: Imediata
-  default_activity_design: Design
-  default_activity_development: Desenvolvimento
-
-  enumeration_issue_priorities: Prioridade das tarefas
-  enumeration_doc_categories: Categorias de documento
-  enumeration_activities: Atividades (registro de horas)
-  notice_unable_delete_version: Não foi possível excluir a versão
-  label_renamed: renomeado
-  label_copied: copiado
-  setting_plain_text_mail: Usar mensagem sem formatação HTML
-  permission_view_files: Ver arquivos
-  permission_edit_issues: Editar tarefas
-  permission_edit_own_time_entries: Editar o próprio tempo de trabalho
-  permission_manage_public_queries: Gerenciar consultas públicas
-  permission_add_issues: Adicionar tarefas
-  permission_log_time: Adicionar tempo gasto
-  permission_view_changesets: Ver conjunto de alterações
-  permission_view_time_entries: Ver tempo gasto
-  permission_manage_versions: Gerenciar versões
-  permission_manage_wiki: Gerenciar wiki
-  permission_manage_categories: Gerenciar categorias de tarefas
-  permission_protect_wiki_pages: Proteger páginas wiki
-  permission_comment_news: Comentar notícias
-  permission_delete_messages: Excluir mensagens
-  permission_select_project_modules: Selecionar módulos de projeto
-  permission_edit_wiki_pages: Editar páginas wiki
-  permission_add_issue_watchers: Adicionar observadores
-  permission_view_gantt: Ver gráfico gantt
-  permission_move_issues: Mover tarefas
-  permission_manage_issue_relations: Gerenciar relacionamentos de tarefas
-  permission_delete_wiki_pages: Excluir páginas wiki
-  permission_manage_boards: Gerenciar fóruns
-  permission_delete_wiki_pages_attachments: Excluir anexos
-  permission_view_wiki_edits: Ver histórico do wiki
-  permission_add_messages: Postar mensagens
-  permission_view_messages: Ver mensagens
-  permission_manage_files: Gerenciar arquivos
-  permission_edit_issue_notes: Editar notas
-  permission_manage_news: Gerenciar notícias
-  permission_view_calendar: Ver calendário
-  permission_manage_members: Gerenciar membros
-  permission_edit_messages: Editar mensagens
-  permission_delete_issues: Excluir tarefas
-  permission_view_issue_watchers: Ver lista de observadores
-  permission_manage_repository: Gerenciar repositório
-  permission_commit_access: Acesso do commit
-  permission_browse_repository: Pesquisar repositório
-  permission_view_documents: Ver documentos
-  permission_edit_project: Editar projeto
-  permission_add_issue_notes: Adicionar notas
-  permission_save_queries: Salvar consultas
-  permission_view_wiki_pages: Ver wiki
-  permission_rename_wiki_pages: Renomear páginas wiki
-  permission_edit_time_entries: Editar tempo gasto
-  permission_edit_own_issue_notes: Editar suas próprias notas
-  setting_gravatar_enabled: Usar ícones do Gravatar
-  label_example: Exemplo
-  text_repository_usernames_mapping: "Seleciona ou atualiza os usuários do Redmine mapeando para cada usuário encontrado no log do repositório.\nUsuários com o mesmo login ou e-mail no Redmine e no repositório serão mapeados automaticamente."
-  permission_edit_own_messages: Editar próprias mensagens
-  permission_delete_own_messages: Excluir próprias mensagens
-  label_user_activity: "Atividade de %{value}"
-  label_updated_time_by: "Atualizado por %{author} há %{age}"
-  text_diff_truncated: '... Este diff foi truncado porque excede o tamanho máximo que pode ser exibido.'
-  setting_diff_max_lines_displayed: Número máximo de linhas exibidas no diff
-  text_plugin_assets_writable: Diretório de plugins gravável
-  warning_attachments_not_saved: "%{count} arquivo(s) não puderam ser salvo(s)."
-  button_create_and_continue: Criar e continuar
-  text_custom_field_possible_values_info: 'Uma linha para cada valor'
-  label_display: Exibição
-  field_editable: Editável
-  setting_repository_log_display_limit: Número máximo de revisões exibidas no arquivo de log
-  setting_file_max_size_displayed: Tamanho máximo dos arquivos textos exibidos em linha
-  field_identity_urler: Observador
-  setting_openid: Permitir Login e Registro via OpenID
-  field_identity_url: OpenID URL
-  label_login_with_open_id_option: ou use o OpenID
-  field_content: Conteúdo
-  label_descending: Descendente
-  label_sort: Ordenar
-  label_ascending: Ascendente
-  label_date_from_to: De %{start} até %{end}
-  label_greater_or_equal: ">="
-  label_less_or_equal: <=
-  text_wiki_page_destroy_question: Esta página tem %{descendants} página(s) filha(s) e descendente(s). O que você quer fazer?
-  text_wiki_page_reassign_children: Reatribuir páginas filhas para esta página pai
-  text_wiki_page_nullify_children: Manter as páginas filhas como páginas raízes
-  text_wiki_page_destroy_children: Excluir páginas filhas e todas suas descendentes
-  setting_password_min_length: Comprimento mínimo para senhas
-  field_group_by: Agrupar por
-  mail_subject_wiki_content_updated: "A página wiki '%{id}' foi atualizada"
-  label_wiki_content_added: Página wiki adicionada
-  mail_subject_wiki_content_added: "A página wiki '%{id}' foi adicionada"
-  mail_body_wiki_content_added: A página wiki '%{id}' foi adicionada por %{author}.
-  label_wiki_content_updated: Página wiki atualizada
-  mail_body_wiki_content_updated: A página wiki '%{id}' foi atualizada por %{author}.
-  permission_add_project: Criar projeto
-  setting_new_project_user_role_id: Papel atribuído a um usuário não-administrador que cria um projeto
-  label_view_all_revisions: Ver todas as revisões
-  label_tag: Tag
-  label_branch: Branch
-  text_journal_changed: "%{label} alterado de %{old} para %{new}"
-  text_journal_set_to: "%{label} ajustado para %{value}"
-  text_journal_deleted: "%{label} excluído (%{old})"
-  label_group_plural: Grupos
-  label_group: Grupo
-  label_group_new: Novo grupo
-  label_time_entry_plural: Tempos gastos
-  text_journal_added: "%{label} %{value} adicionado"
-  field_active: Ativo
-  enumeration_system_activity: Atividade do sistema
-  permission_delete_issue_watchers: Excluir observadores
-  version_status_closed: fechado
-  version_status_locked: bloqueado
-  version_status_open: aberto
-  error_can_not_reopen_issue_on_closed_version: Uma tarefa atribuída a uma versão fechada não pode ser reaberta
-  label_user_anonymous: Anônimo
-  button_move_and_follow: Mover e seguir
-  setting_default_projects_modules: Módulos habilitados por padrão para novos projetos
-  setting_gravatar_default: Imagem-padrão do Gravatar
-  field_sharing: Compartilhamento
-  label_version_sharing_hierarchy: Com a hierarquia do projeto
-  label_version_sharing_system: Com todos os projetos
-  label_version_sharing_descendants: Com sub-projetos
-  label_version_sharing_tree: Com a árvore do projeto
-  label_version_sharing_none: Sem compartilhamento
-  error_can_not_archive_project: Este projeto não pode ser arquivado
-  button_duplicate: Duplicar
-  button_copy_and_follow: Copiar e seguir
-  label_copy_source: Origem
-  setting_issue_done_ratio: Calcular o percentual de conclusão da tarefa
-  setting_issue_done_ratio_issue_status: Usar a situação da tarefa
-  error_issue_done_ratios_not_updated: O percentual de conclusão das tarefas não foi atualizado.
-  error_workflow_copy_target: Por favor, selecione os tipos de tarefa e os papéis alvo
-  setting_issue_done_ratio_issue_field: Use o campo da tarefa
-  label_copy_same_as_target: Mesmo alvo
-  label_copy_target: Alvo
-  notice_issue_done_ratios_updated: Percentual de conclusão atualizados.
-  error_workflow_copy_source: Por favor, selecione um tipo de tarefa e papel de origem
-  label_update_issue_done_ratios: Atualizar percentual de conclusão das tarefas
-  setting_start_of_week: Início da semana
-  field_watcher: Observador
-  permission_view_issues: Ver tarefas
-  label_display_used_statuses_only: Somente exibir situações que são usadas por este tipo de tarefa
-  label_revision_id: Revisão %{value}
-  label_api_access_key: Chave de acesso a API
-  button_show: Exibir
-  label_api_access_key_created_on: Chave de acesso a API criado a %{value} atrás
-  label_feeds_access_key: Chave de acesso ao Atom
-  notice_api_access_key_reseted: Sua chave de acesso a API foi redefinida.
-  setting_rest_api_enabled: Habilitar a api REST
-  label_missing_api_access_key: Chave de acesso a API faltando
-  label_missing_feeds_access_key: Chave de acesso ao Atom faltando
-  text_line_separated: Múltiplos valores permitidos (uma linha para cada valor).
-  setting_mail_handler_body_delimiters: Truncar e-mails após uma destas linhas
-  permission_add_subprojects: Criar subprojetos
-  label_subproject_new: Novo subprojeto
-  text_own_membership_delete_confirmation: |-
-    Você irá excluir algumas de suas próprias permissões e não estará mais apto a editar este projeto após esta operação.
-    Você tem certeza que deseja continuar?
-  label_close_versions: Fechar versões concluídas
-  label_board_sticky: Marcado
-  label_board_locked: Bloqueado
-  permission_export_wiki_pages: Exportar páginas wiki
-  setting_cache_formatted_text: Realizar cache de texto formatado
-  permission_manage_project_activities: Gerenciar atividades do projeto
-  error_unable_delete_issue_status: Não foi possível excluir situação da tarefa
-  label_profile: Perfil
-  permission_manage_subtasks: Gerenciar subtarefas
-  field_parent_issue: Tarefa pai
-  label_subtask_plural: Subtarefas
-  label_project_copy_notifications: Enviar notificações por e-mail ao copiar projeto
-  error_can_not_delete_custom_field: Não foi possível excluir o campo personalizado
-  error_unable_to_connect: Não foi possível conectar (%{value})
-  error_can_not_remove_role: Este papel está em uso e não pode ser excluído.
-  error_can_not_delete_tracker: Este tipo de tarefa está atribuído a alguma(s) tarefa(s) e não pode ser excluído.
-  field_principal: Principal
-  label_my_page_block: Meu bloco de página
-  notice_failed_to_save_members: "Falha ao salvar membro(s): %{errors}."
-  text_zoom_out: Afastar zoom
-  text_zoom_in: Aproximar zoom
-  notice_unable_delete_time_entry: Não foi possível excluir a entrada no registro de horas trabalhadas.
-  label_overall_spent_time: Tempo gasto geral
-  field_time_entries: Registro de horas
-  project_module_gantt: Gantt
-  project_module_calendar: Calendário
-  button_edit_associated_wikipage: "Editar página wiki relacionada: %{page_title}"
-  field_text: Campo de texto
-  label_user_mail_option_only_owner: Somente para as coisas que eu criei
-  setting_default_notification_option: Opção padrão de notificação
-  label_user_mail_option_only_my_events: Somente para as coisas que eu esteja observando ou esteja envolvido
-  label_user_mail_option_only_assigned: Somente para as coisas que estejam atribuídas a mim
-  label_user_mail_option_none: Sem eventos
-  field_member_of_group: Responsável pelo grupo
-  field_assigned_to_role: Papel do responsável
-  notice_not_authorized_archived_project: O projeto que você está tentando acessar foi arquivado.
-  label_principal_search: "Pesquisar por usuários ou grupos:"
-  label_user_search: "Pesquisar por usuário:"
-  field_visible: Visível
-  setting_emails_header: Cabeçalho do e-mail
-  setting_commit_logtime_activity_id: Atividade para registrar horas
-  text_time_logged_by_changeset: Aplicado no conjunto de alterações %{value}.
-  setting_commit_logtime_enabled: Habilitar registro de horas
-  notice_gantt_chart_truncated: O gráfico foi cortado por exceder o tamanho máximo de linhas que podem ser exibidas (%{max})
-  setting_gantt_items_limit: Número máximo de itens exibidos no gráfico gantt
-  field_warn_on_leaving_unsaved: Alertar-me ao sair de uma página sem salvar o texto
-  text_warn_on_leaving_unsaved: A página atual contém texto que não foi salvo e será perdido se você sair desta página.
-  label_my_queries: Minhas consultas personalizadas
-  text_journal_changed_no_detail: "%{label} atualizado(a)"
-  label_news_comment_added: Notícia recebeu um comentário
-  button_expand_all: Expandir tudo
-  button_collapse_all: Recolher tudo
-  label_additional_workflow_transitions_for_assignee: Transições adicionais permitidas quando o usuário é o responsável pela tarefa
-  label_additional_workflow_transitions_for_author: Transições adicionais permitidas quando o usuário é o autor
-
-  label_bulk_edit_selected_time_entries: Alteração em massa do registro de horas
-  text_time_entries_destroy_confirmation: Tem certeza que quer excluir o(s) registro(s) de horas selecionado(s)?
-  label_role_anonymous: Anônimo
-  label_role_non_member: Não Membro
-  label_issues_visibility_own: Tarefas criadas ou atribuídas ao usuário
-  field_issues_visibility: Visibilidade das tarefas
-  label_issues_visibility_all: Todas as tarefas
-  permission_set_own_issues_private: Alterar as próprias tarefas para públicas ou privadas
-  field_is_private: Privado
-  permission_set_issues_private: Alterar tarefas para públicas ou privadas
-  label_issues_visibility_public: Todas as tarefas não privadas
-  text_issues_destroy_descendants_confirmation: Isto também irá excluir %{count} subtarefa(s).
-  field_commit_logs_encoding: Codificação das mensagens de commit
-  field_scm_path_encoding: Codificação do caminho
-  text_scm_path_encoding_note: "Padrão: UTF-8"
-  field_path_to_repository: Caminho para o repositório
-  field_root_directory: Diretório raiz
-  field_cvs_module: Módulo
-  field_cvsroot: CVSROOT
-  text_mercurial_repository_note: "Repositório local (ex.: /hgrepo, c:\\hgrepo)"
-  text_scm_command: Comando
-  text_scm_command_version: Versão
-  label_git_report_last_commit: Relatar última alteração para arquivos e diretórios
-  text_scm_config: Você pode configurar seus comandos de versionamento em config/configurations.yml. Por favor reinicie a aplicação após alterá-lo.
-  text_scm_command_not_available: Comando de versionamento não disponível. Por favor verifique as configurações no painel de administração.
-  notice_issue_successful_create: Tarefa %{id} criada.
-  label_between: entre
-  setting_issue_group_assignment: Permitir atribuições de tarefas a grupos
-  label_diff: diff
-  text_git_repository_note: "Repositório esta vazio e é local (ex: /gitrepo, c:\\gitrepo)"
-
-  description_query_sort_criteria_direction: Escolher ordenação
-  description_project_scope: Escopo da pesquisa
-  description_filter: Filtro
-  description_user_mail_notification: Configuração de notificações por e-mail
-  description_date_from: Digite a data inicial
-  description_message_content: Conteúdo da mensagem
-  description_available_columns: Colunas disponíveis
-  description_date_range_interval: Escolha um período selecionando a data de início e fim
-  description_issue_category_reassign: Escolha uma categoria de tarefas
-  description_search: Campo de busca
-  description_notes: Notas
-  description_date_range_list: Escolha um período a partir da lista
-  description_choose_project: Projetos
-  description_date_to: Digite a data final
-  description_query_sort_criteria_attribute: Atributo de ordenação
-  description_wiki_subpages_reassign: Escolha uma nova página pai
-  description_selected_columns: Colunas selecionadas
-
-  label_parent_revision: Pai
-  label_child_revision: Filho
-  error_scm_annotate_big_text_file: A entrada não pode ser anotada, pois excede o tamanho máximo do arquivo de texto.
-  setting_default_issue_start_date_to_creation_date: Usar data corrente como data inicial para novas tarefas
-  button_edit_section: Editar esta seção
-  setting_repositories_encodings: Codificação dos repositórios e anexos
-  description_all_columns: Todas as colunas
-  button_export: Exportar
-  label_export_options: "Opções de exportação %{export_format}"
-  error_attachment_too_big: Este arquivo não pode ser enviado porque excede o tamanho máximo permitido (%{max_size})
-  notice_failed_to_save_time_entries: "Falha ao salvar %{count} de %{total} horas trabalhadas: %{ids}."
-  label_x_issues:
-    zero:  0 tarefa
-    one:   1 tarefa
-    other: "%{count} tarefas"
-  label_repository_new: Novo repositório
-  field_repository_is_default: Repositório principal
-  label_copy_attachments: Copiar anexos
-  label_item_position: "%{position}/%{count}"
-  label_completed_versions: Versões concluídas
-  text_project_identifier_info: Somente letras minúsculas (a-z), números, traços e sublinhados são permitidos. <br /> Uma vez salvo, o identificador não pode ser alterado.
-  field_multiple: Múltiplos valores
-  setting_commit_cross_project_ref: Permitir que tarefas de todos os outros projetos sejam refenciadas e resolvidas
-  text_issue_conflict_resolution_add_notes: Adicionar minhas anotações e descartar minhas outras mudanças
-  text_issue_conflict_resolution_overwrite: Aplicar as minhas alterações de qualquer maneira (notas anteriores serão mantidas, mas algumas mudanças podem ser substituídas)
-  notice_issue_update_conflict: A tarefa foi atualizada por um outro usuário, enquanto você estava editando.
-  text_issue_conflict_resolution_cancel: Descartar todas as minhas mudanças e reexibir %{link}
-  permission_manage_related_issues: Gerenciar tarefas relacionadas
-  field_auth_source_ldap_filter: Filtro LDAP
-  label_search_for_watchers: Procurar por outros observadores para adiconar
-  notice_account_deleted: Sua conta foi excluída permanentemente.
-  setting_unsubscribe: Permitir aos usuários excluir sua própria conta
-  button_delete_my_account: Excluir minha conta
-  text_account_destroy_confirmation: |-
-    Tem certeza que quer continuar?
-    Sua conta será excluída permanentemente, sem qualquer forma de reativá-la.
-  error_session_expired: A sua sessão expirou. Por favor, faça login novamente.
-  text_session_expiration_settings: "Aviso: a alteração dessas configurações pode expirar as sessões atuais, incluindo a sua."
-  setting_session_lifetime: duração máxima da sessão
-  setting_session_timeout: tempo limite de inatividade da sessão
-  label_session_expiration: "Expiração da sessão"
-  permission_close_project: Fechar / reabrir o projeto
-  label_show_closed_projects: Visualizar projetos fechados
-  button_close: Fechar
-  button_reopen: Reabrir
-  project_status_active: ativo
-  project_status_closed: fechado
-  project_status_archived: arquivado
-  text_project_closed: Este projeto está fechado e somente leitura.
-  notice_user_successful_create: Usuário %{id} criado.
-  field_core_fields: campos padrão
-  field_timeout: Tempo de espera (em segundos)
-  setting_thumbnails_enabled: Exibir miniaturas de anexos
-  setting_thumbnails_size: Tamanho das miniaturas (em pixels)
-  label_status_transitions: Estados das transições
-  label_fields_permissions: Permissões de campos
-  label_readonly: somente leitura
-  label_required: Obrigatório
-  text_repository_identifier_info: Somente letras minúsculas (az), números, traços e sublinhados são permitidos <br/> Uma vez salvo, o identificador não pode ser alterado.
-  field_board_parent: Fórum Pai
-  label_attribute_of_project: "Projeto %{name}"
-  label_attribute_of_author: "autor %{name}"
-  label_attribute_of_assigned_to: "atribuído a %{name}"
-  label_attribute_of_fixed_version: "versão %{name}"
-  label_copy_subtasks: Copiar subtarefas
-  label_copied_to: copiada
-  label_copied_from: copiado
-  label_any_issues_in_project: qualquer tarefa do projeto
-  label_any_issues_not_in_project: qualquer tarefa que não está no projeto
-  field_private_notes: notas privadas
-  permission_view_private_notes: Ver notas privadas
-  permission_set_notes_private: Permitir alterar notas para privada
-  label_no_issues_in_project: sem tarefas no projeto
-  label_any: todos
-  label_last_n_weeks: "últimas %{count} semanas"
-  setting_cross_project_subtasks: Permitir subtarefas entre projetos
-  label_cross_project_descendants: com subprojetos
-  label_cross_project_tree: Com a árvore do Projeto
-  label_cross_project_hierarchy: Com uma hierarquia do Projeto
-  label_cross_project_system: Com todos os Projetos
-  button_hide: Omitir
-  setting_non_working_week_days: dias não úteis
-  label_in_the_next_days: nos próximos dias
-  label_in_the_past_days: nos dias anteriores
-  label_attribute_of_user: Usuário %{name}
-  text_turning_multiple_off: Se você desativar vários valores, eles serão removidos, a fim de preservar somente um valor por item.
-  label_attribute_of_issue: Tarefa %{name}
-  permission_add_documents: Adicionar documentos
-  permission_edit_documents: Editar documentos
-  permission_delete_documents: Excluir documentos
-  label_gantt_progress_line: Linha de progresso
-  setting_jsonp_enabled: Ativar suporte JSONP
-  field_inherit_members: Herdar membros
-  field_closed_on: Concluído
-  field_generate_password: Gerar senha
-  setting_default_projects_tracker_ids: Tipos padrões para novos projeto
-  label_total_time: Total
-  notice_account_not_activated_yet: You haven't activated your account yet. If you want
-    to receive a new activation email, please <a href="%{url}">click this link</a>.
-  notice_account_locked: Your account is locked.
-  label_hidden: Hidden
-  label_visibility_private: to me only
-  label_visibility_roles: to these roles only
-  label_visibility_public: to any users
-  field_must_change_passwd: Must change password at next logon
-  notice_new_password_must_be_different: The new password must be different from the
-    current password
-  setting_mail_handler_excluded_filenames: Exclude attachments by name
-  text_convert_available: ImageMagick convert available (optional)
--- a/.svn/pristine/39/391b1c790687d518fea17dcd03fc5883b7da327b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssuePriorityCustomField < CustomField
-  def type_name
-    :enumeration_issue_priorities
-  end
-end
-
--- a/.svn/pristine/39/3942548809d01a94e378f6a25d893f1c4053354a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,327 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base
-  fixtures :users, :members, :member_roles, :roles, :projects
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  should_allow_api_authentication(:get, "/users.xml")
-  should_allow_api_authentication(:get, "/users.json")
-  should_allow_api_authentication(:post,
-    '/users.xml',
-     {:user => {
-        :login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
-        :mail => 'foo@example.net', :password => 'secret123'
-      }},
-    {:success_code => :created})
-  should_allow_api_authentication(:post,
-    '/users.json',
-    {:user => {
-       :login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
-       :mail => 'foo@example.net'
-    }},
-    {:success_code => :created})
-  should_allow_api_authentication(:put,
-    '/users/2.xml',
-    {:user => {
-        :login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
-        :mail => 'jsmith@somenet.foo'
-    }},
-    {:success_code => :ok})
-  should_allow_api_authentication(:put,
-    '/users/2.json',
-    {:user => {
-        :login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
-        :mail => 'jsmith@somenet.foo'
-    }},
-    {:success_code => :ok})
-  should_allow_api_authentication(:delete,
-    '/users/2.xml',
-    {},
-    {:success_code => :ok})
-  should_allow_api_authentication(:delete,
-    '/users/2.xml',
-    {},
-    {:success_code => :ok})
-
-  test "GET /users/:id.xml should return the user" do
-    get '/users/2.xml'
-
-    assert_response :success
-    assert_tag :tag => 'user',
-      :child => {:tag => 'id', :content => '2'}
-  end
-
-  test "GET /users/:id.json should return the user" do
-    get '/users/2.json'
-
-    assert_response :success
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json
-    assert_kind_of Hash, json['user']
-    assert_equal 2, json['user']['id']
-  end
-
-  test "GET /users/:id.xml with include=memberships should include memberships" do
-    get '/users/2.xml?include=memberships'
-
-    assert_response :success
-    assert_tag :tag => 'memberships',
-      :parent => {:tag => 'user'},
-      :children => {:count => 1}
-  end
-
-  test "GET /users/:id.json with include=memberships should include memberships" do
-    get '/users/2.json?include=memberships'
-
-    assert_response :success
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Array, json['user']['memberships']
-    assert_equal [{
-      "id"=>1,
-      "project"=>{"name"=>"eCookbook", "id"=>1},
-      "roles"=>[{"name"=>"Manager", "id"=>1}]
-    }], json['user']['memberships']
-  end
-
-  test "GET /users/current.xml should require authentication" do
-    get '/users/current.xml'
-
-    assert_response 401
-  end
-
-  test "GET /users/current.xml should return current user" do
-    get '/users/current.xml', {}, credentials('jsmith')
-
-    assert_tag :tag => 'user',
-      :child => {:tag => 'id', :content => '2'}
-  end
-
-  test "GET /users/:id should not return login for other user" do
-    get '/users/3.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_no_tag 'user', :child => {:tag => 'login'}
-  end
-
-  test "GET /users/:id should return login for current user" do
-    get '/users/2.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_tag 'user', :child => {:tag => 'login', :content => 'jsmith'}
-  end
-
-  test "GET /users/:id should not return api_key for other user" do
-    get '/users/3.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_no_tag 'user', :child => {:tag => 'api_key'}
-  end
-
-  test "GET /users/:id should return api_key for current user" do
-    get '/users/2.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_tag 'user', :child => {:tag => 'api_key', :content => User.find(2).api_key}
-  end
-
-  test "GET /users/:id should not return status for standard user" do
-    get '/users/3.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_no_tag 'user', :child => {:tag => 'status'}
-  end
-
-  test "GET /users/:id should return status for administrators" do
-    get '/users/2.xml', {}, credentials('admin')
-    assert_response :success
-    assert_tag 'user', :child => {:tag => 'status', :content => User.find(1).status.to_s}
-  end
-
-  test "POST /users.xml with valid parameters should create the user" do
-    assert_difference('User.count') do
-      post '/users.xml', {
-        :user => {
-          :login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
-          :mail => 'foo@example.net', :password => 'secret123',
-          :mail_notification => 'only_assigned'}
-        },
-        credentials('admin')
-    end
-
-    user = User.first(:order => 'id DESC')
-    assert_equal 'foo', user.login
-    assert_equal 'Firstname', user.firstname
-    assert_equal 'Lastname', user.lastname
-    assert_equal 'foo@example.net', user.mail
-    assert_equal 'only_assigned', user.mail_notification
-    assert !user.admin?
-    assert user.check_password?('secret123')
-
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'user', :child => {:tag => 'id', :content => user.id.to_s}
-  end
-
-  test "POST /users.json with valid parameters should create the user" do
-    assert_difference('User.count') do
-      post '/users.json', {
-        :user => {
-          :login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
-          :mail => 'foo@example.net', :password => 'secret123',
-          :mail_notification => 'only_assigned'}
-        },
-        credentials('admin')
-    end
-
-    user = User.first(:order => 'id DESC')
-    assert_equal 'foo', user.login
-    assert_equal 'Firstname', user.firstname
-    assert_equal 'Lastname', user.lastname
-    assert_equal 'foo@example.net', user.mail
-    assert !user.admin?
-
-    assert_response :created
-    assert_equal 'application/json', @response.content_type
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json
-    assert_kind_of Hash, json['user']
-    assert_equal user.id, json['user']['id']
-  end
-
-  test "POST /users.xml with with invalid parameters should return errors" do
-    assert_no_difference('User.count') do
-      post '/users.xml', {:user => {:login => 'foo', :lastname => 'Lastname', :mail => 'foo'}}, credentials('admin')
-    end
-
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'errors', :child => {
-                           :tag => 'error',
-                           :content => "First name can't be blank"
-                         }
-  end
-
-  test "POST /users.json with with invalid parameters should return errors" do
-    assert_no_difference('User.count') do
-      post '/users.json', {:user => {:login => 'foo', :lastname => 'Lastname', :mail => 'foo'}}, credentials('admin')
-    end
-
-    assert_response :unprocessable_entity
-    assert_equal 'application/json', @response.content_type
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json
-    assert json.has_key?('errors')
-    assert_kind_of Array, json['errors']
-  end
-
-  test "PUT /users/:id.xml with valid parameters should update the user" do
-    assert_no_difference('User.count') do
-      put '/users/2.xml', {
-        :user => {
-          :login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
-          :mail => 'jsmith@somenet.foo'}
-        },
-        credentials('admin')
-    end
-
-    user = User.find(2)
-    assert_equal 'jsmith', user.login
-    assert_equal 'John', user.firstname
-    assert_equal 'Renamed', user.lastname
-    assert_equal 'jsmith@somenet.foo', user.mail
-    assert !user.admin?
-
-    assert_response :ok
-    assert_equal '', @response.body
-  end
-
-  test "PUT /users/:id.json with valid parameters should update the user" do
-    assert_no_difference('User.count') do
-      put '/users/2.json', {
-        :user => {
-          :login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
-          :mail => 'jsmith@somenet.foo'}
-        },
-        credentials('admin')
-    end
-
-    user = User.find(2)
-    assert_equal 'jsmith', user.login
-    assert_equal 'John', user.firstname
-    assert_equal 'Renamed', user.lastname
-    assert_equal 'jsmith@somenet.foo', user.mail
-    assert !user.admin?
-
-    assert_response :ok
-    assert_equal '', @response.body
-  end
-
-  test "PUT /users/:id.xml with invalid parameters" do
-    assert_no_difference('User.count') do
-      put '/users/2.xml', {
-        :user => {
-          :login => 'jsmith', :firstname => '', :lastname => 'Lastname',
-          :mail => 'foo'}
-        },
-        credentials('admin')
-    end
-
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'errors', :child => {
-                           :tag => 'error',
-                           :content => "First name can't be blank"
-                          }
-  end
-
-  test "PUT /users/:id.json with invalid parameters" do
-    assert_no_difference('User.count') do
-      put '/users/2.json', {
-        :user => {
-          :login => 'jsmith', :firstname => '', :lastname => 'Lastname',
-          :mail => 'foo'}
-        },
-        credentials('admin')
-    end
-
-    assert_response :unprocessable_entity
-    assert_equal 'application/json', @response.content_type
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json
-    assert json.has_key?('errors')
-    assert_kind_of Array, json['errors']
-  end
-
-  test "DELETE /users/:id.xml should delete the user" do
-    assert_difference('User.count', -1) do
-      delete '/users/2.xml', {}, credentials('admin')
-    end
-
-    assert_response :ok
-    assert_equal '', @response.body
-  end
-
-  test "DELETE /users/:id.json should delete the user" do
-    assert_difference('User.count', -1) do
-      delete '/users/2.json', {}, credentials('admin')
-    end
-
-    assert_response :ok
-    assert_equal '', @response.body
-  end
-end
--- a/.svn/pristine/39/399f2a5d4375067a1c2f5abc78f9f28143ca9321.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class ReportsController < ApplicationController
-  menu_item :issues
-  before_filter :find_project, :authorize, :find_issue_statuses
-
-  def issue_report
-    @trackers = @project.trackers
-    @versions = @project.shared_versions.sort
-    @priorities = IssuePriority.all.reverse
-    @categories = @project.issue_categories
-    @assignees = (Setting.issue_group_assignment? ? @project.principals : @project.users).sort
-    @authors = @project.users.sort
-    @subprojects = @project.descendants.visible
-
-    @issues_by_tracker = Issue.by_tracker(@project)
-    @issues_by_version = Issue.by_version(@project)
-    @issues_by_priority = Issue.by_priority(@project)
-    @issues_by_category = Issue.by_category(@project)
-    @issues_by_assigned_to = Issue.by_assigned_to(@project)
-    @issues_by_author = Issue.by_author(@project)
-    @issues_by_subproject = Issue.by_subproject(@project) || []
-
-    render :template => "reports/issue_report"
-  end
-
-  def issue_report_details
-    case params[:detail]
-    when "tracker"
-      @field = "tracker_id"
-      @rows = @project.trackers
-      @data = Issue.by_tracker(@project)
-      @report_title = l(:field_tracker)
-    when "version"
-      @field = "fixed_version_id"
-      @rows = @project.shared_versions.sort
-      @data = Issue.by_version(@project)
-      @report_title = l(:field_version)
-    when "priority"
-      @field = "priority_id"
-      @rows = IssuePriority.all.reverse
-      @data = Issue.by_priority(@project)
-      @report_title = l(:field_priority)
-    when "category"
-      @field = "category_id"
-      @rows = @project.issue_categories
-      @data = Issue.by_category(@project)
-      @report_title = l(:field_category)
-    when "assigned_to"
-      @field = "assigned_to_id"
-      @rows = (Setting.issue_group_assignment? ? @project.principals : @project.users).sort
-      @data = Issue.by_assigned_to(@project)
-      @report_title = l(:field_assigned_to)
-    when "author"
-      @field = "author_id"
-      @rows = @project.users.sort
-      @data = Issue.by_author(@project)
-      @report_title = l(:field_author)
-    when "subproject"
-      @field = "project_id"
-      @rows = @project.descendants.visible
-      @data = Issue.by_subproject(@project) || []
-      @report_title = l(:field_subproject)
-    end
-
-    respond_to do |format|
-      if @field
-        format.html {}
-      else
-        format.html { redirect_to :action => 'issue_report', :id => @project }
-      end
-    end
-  end
-
-  private
-
-  def find_issue_statuses
-    @statuses = IssueStatus.sorted.all
-  end
-end
--- a/.svn/pristine/39/39a608089a590c01af61f645951f37bfe827c689.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AdminTest < ActionController::IntegrationTest
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def test_add_user
-    log_user("admin", "admin")
-    get "/users/new"
-    assert_response :success
-    assert_template "users/new"
-    post "/users",
-         :user => { :login => "psmith", :firstname => "Paul",
-                    :lastname => "Smith", :mail => "psmith@somenet.foo",
-                    :language => "en", :password => "psmith09",
-                    :password_confirmation => "psmith09" }
-
-    user = User.find_by_login("psmith")
-    assert_kind_of User, user
-    assert_redirected_to "/users/#{ user.id }/edit"
-
-    logged_user = User.try_to_login("psmith", "psmith09")
-    assert_kind_of User, logged_user
-    assert_equal "Paul", logged_user.firstname
-
-    put "users/#{user.id}", :id => user.id, :user => { :status => User::STATUS_LOCKED }
-    assert_redirected_to "/users/#{ user.id }/edit"
-    locked_user = User.try_to_login("psmith", "psmith09")
-    assert_equal nil, locked_user
-  end
-
-  test "Add a user as an anonymous user should fail" do
-    post '/users',
-         :user => { :login => 'psmith', :firstname => 'Paul'},
-         :password => "psmith09", :password_confirmation => "psmith09"
-    assert_response :redirect
-    assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fusers"
-  end
-end
--- a/.svn/pristine/39/39e07ef2d5632f8e7ca245cda7735bd6e7674f6d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,341 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/abstract_adapter'
-
-module Redmine
-  module Scm
-    module Adapters
-      class BazaarAdapter < AbstractAdapter
-
-        # Bazaar executable name
-        BZR_BIN = Redmine::Configuration['scm_bazaar_command'] || "bzr"
-
-        class << self
-          def client_command
-            @@bin    ||= BZR_BIN
-          end
-
-          def sq_bin
-            @@sq_bin ||= shell_quote_command
-          end
-
-          def client_version
-            @@client_version ||= (scm_command_version || [])
-          end
-
-          def client_available
-            !client_version.empty?
-          end
-
-          def scm_command_version
-            scm_version = scm_version_from_command_line.dup
-            if scm_version.respond_to?(:force_encoding)
-              scm_version.force_encoding('ASCII-8BIT')
-            end
-            if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
-              m[2].scan(%r{\d+}).collect(&:to_i)
-            end
-          end
-
-          def scm_version_from_command_line
-            shellout("#{sq_bin} --version") { |io| io.read }.to_s
-          end
-        end
-
-        def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
-          @url = url
-          @root_url = url
-          @path_encoding = 'UTF-8'
-          # do not call *super* for non ASCII repository path
-        end
-
-        def bzr_path_encodig=(encoding)
-          @path_encoding = encoding
-        end
-
-        # Get info about the repository
-        def info
-          cmd_args = %w|revno|
-          cmd_args << bzr_target('')
-          info = nil
-          scm_cmd(*cmd_args) do |io|
-            if io.read =~ %r{^(\d+)\r?$}
-              info = Info.new({:root_url => url,
-                               :lastrev => Revision.new({
-                                 :identifier => $1
-                               })
-                             })
-            end
-          end
-          info
-        rescue ScmCommandAborted
-          return nil
-        end
-
-        # Returns an Entries collection
-        # or nil if the given path doesn't exist in the repository
-        def entries(path=nil, identifier=nil, options={})
-          path ||= ''
-          entries = Entries.new
-          identifier = -1 unless identifier && identifier.to_i > 0
-          cmd_args = %w|ls -v --show-ids|
-          cmd_args << "-r#{identifier.to_i}"
-          cmd_args << bzr_target(path)
-          scm_cmd(*cmd_args) do |io|
-            prefix_utf8 = "#{url}/#{path}".gsub('\\', '/')
-            logger.debug "PREFIX: #{prefix_utf8}"
-            prefix = scm_iconv(@path_encoding, 'UTF-8', prefix_utf8)
-            prefix.force_encoding('ASCII-8BIT') if prefix.respond_to?(:force_encoding)
-            re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$}
-            io.each_line do |line|
-              next unless line =~ re
-              name_locale, slash, revision = $3.strip, $4, $5.strip
-              name = scm_iconv('UTF-8', @path_encoding, name_locale)
-              entries << Entry.new({:name => name,
-                                    :path => ((path.empty? ? "" : "#{path}/") + name),
-                                    :kind => (slash.blank? ? 'file' : 'dir'),
-                                    :size => nil,
-                                    :lastrev => Revision.new(:revision => revision)
-                                  })
-            end
-          end
-          if logger && logger.debug?
-            logger.debug("Found #{entries.size} entries in the repository for #{target(path)}")
-          end
-          entries.sort_by_name
-        rescue ScmCommandAborted
-          return nil
-        end
-
-        def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
-          path ||= ''
-          identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : 'last:1'
-          identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : 1
-          revisions = Revisions.new
-          cmd_args = %w|log -v --show-ids|
-          cmd_args << "-r#{identifier_to}..#{identifier_from}"
-          cmd_args << bzr_target(path)
-          scm_cmd(*cmd_args) do |io|
-            revision = nil
-            parsing  = nil
-            io.each_line do |line|
-              if line =~ /^----/
-                revisions << revision if revision
-                revision = Revision.new(:paths => [], :message => '')
-                parsing = nil
-              else
-                next unless revision
-                if line =~ /^revno: (\d+)($|\s\[merge\]$)/
-                  revision.identifier = $1.to_i
-                elsif line =~ /^committer: (.+)$/
-                  revision.author = $1.strip
-                elsif line =~ /^revision-id:(.+)$/
-                  revision.scmid = $1.strip
-                elsif line =~ /^timestamp: (.+)$/
-                  revision.time = Time.parse($1).localtime
-                elsif line =~ /^    -----/
-                  # partial revisions
-                  parsing = nil unless parsing == 'message'
-                elsif line =~ /^(message|added|modified|removed|renamed):/
-                  parsing = $1
-                elsif line =~ /^  (.*)$/
-                  if parsing == 'message'
-                    revision.message << "#{$1}\n"
-                  else
-                    if $1 =~ /^(.*)\s+(\S+)$/
-                      path_locale = $1.strip
-                      path = scm_iconv('UTF-8', @path_encoding, path_locale)
-                      revid = $2
-                      case parsing
-                      when 'added'
-                        revision.paths << {:action => 'A', :path => "/#{path}", :revision => revid}
-                      when 'modified'
-                        revision.paths << {:action => 'M', :path => "/#{path}", :revision => revid}
-                      when 'removed'
-                        revision.paths << {:action => 'D', :path => "/#{path}", :revision => revid}
-                      when 'renamed'
-                        new_path = path.split('=>').last
-                        if new_path
-                          revision.paths << {:action => 'M', :path => "/#{new_path.strip}",
-                                             :revision => revid}
-                        end
-                      end
-                    end
-                  end
-                else
-                  parsing = nil
-                end
-              end
-            end
-            revisions << revision if revision
-          end
-          revisions
-        rescue ScmCommandAborted
-          return nil
-        end
-
-        def diff(path, identifier_from, identifier_to=nil)
-          path ||= ''
-          if identifier_to
-            identifier_to = identifier_to.to_i
-          else
-            identifier_to = identifier_from.to_i - 1
-          end
-          if identifier_from
-            identifier_from = identifier_from.to_i
-          end
-          diff = []
-          cmd_args = %w|diff|
-          cmd_args << "-r#{identifier_to}..#{identifier_from}"
-          cmd_args << bzr_target(path)
-          scm_cmd_no_raise(*cmd_args) do |io|
-            io.each_line do |line|
-              diff << line
-            end
-          end
-          diff
-        end
-
-        def cat(path, identifier=nil)
-          cat = nil
-          cmd_args = %w|cat|
-          cmd_args << "-r#{identifier.to_i}" if identifier && identifier.to_i > 0
-          cmd_args << bzr_target(path)
-          scm_cmd(*cmd_args) do |io|
-            io.binmode
-            cat = io.read
-          end
-          cat
-        rescue ScmCommandAborted
-          return nil
-        end
-
-        def annotate(path, identifier=nil)
-          blame = Annotate.new
-          cmd_args = %w|annotate -q --all|
-          cmd_args << "-r#{identifier.to_i}" if identifier && identifier.to_i > 0
-          cmd_args << bzr_target(path)
-          scm_cmd(*cmd_args) do |io|
-            author     = nil
-            identifier = nil
-            io.each_line do |line|
-              next unless line =~ %r{^(\d+) ([^|]+)\| (.*)$}
-              rev = $1
-              blame.add_line($3.rstrip,
-                 Revision.new(
-                  :identifier => rev,
-                  :revision   => rev,
-                  :author     => $2.strip
-                  ))
-            end
-          end
-          blame
-        rescue ScmCommandAborted
-          return nil
-        end
-
-        def self.branch_conf_path(path)
-          bcp = nil
-          m = path.match(%r{^(.*[/\\])\.bzr.*$})
-          if m
-            bcp = m[1]
-          else
-            bcp = path
-          end
-          bcp.gsub!(%r{[\/\\]$}, "")
-          if bcp
-            bcp = File.join(bcp, ".bzr", "branch", "branch.conf")
-          end
-          bcp
-        end
-
-        def append_revisions_only
-          return @aro if ! @aro.nil?
-          @aro = false
-          bcp = self.class.branch_conf_path(url)
-          if bcp && File.exist?(bcp)
-            begin
-              f = File::open(bcp, "r")
-              cnt = 0
-              f.each_line do |line|
-                l = line.chomp.to_s
-                if l =~ /^\s*append_revisions_only\s*=\s*(\w+)\s*$/
-                  str_aro = $1
-                  if str_aro.upcase == "TRUE"
-                    @aro = true
-                    cnt += 1
-                  elsif str_aro.upcase == "FALSE"
-                    @aro = false
-                    cnt += 1
-                  end
-                  if cnt > 1
-                    @aro = false
-                    break
-                  end
-                end
-              end
-            ensure
-              f.close
-            end
-          end
-          @aro
-        end
-
-        def scm_cmd(*args, &block)
-          full_args = []
-          full_args += args
-          full_args_locale = []
-          full_args.map do |e|
-            full_args_locale << scm_iconv(@path_encoding, 'UTF-8', e)
-          end
-          ret = shellout(
-                   self.class.sq_bin + ' ' + 
-                     full_args_locale.map { |e| shell_quote e.to_s }.join(' '),
-                   &block
-                   )
-          if $? && $?.exitstatus != 0
-            raise ScmCommandAborted, "bzr exited with non-zero status: #{$?.exitstatus}"
-          end
-          ret
-        end
-        private :scm_cmd
-
-        def scm_cmd_no_raise(*args, &block)
-          full_args = []
-          full_args += args
-          full_args_locale = []
-          full_args.map do |e|
-            full_args_locale << scm_iconv(@path_encoding, 'UTF-8', e)
-          end
-          ret = shellout(
-                   self.class.sq_bin + ' ' + 
-                     full_args_locale.map { |e| shell_quote e.to_s }.join(' '),
-                   &block
-                   )
-          ret
-        end
-        private :scm_cmd_no_raise
-
-        def bzr_target(path)
-          target(path, false)
-        end
-        private :bzr_target
-      end
-    end
-  end
-end
--- a/.svn/pristine/3b/3b77726a8efda3938653233bf84d8e02401c4bc3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class WelcomeController < ApplicationController
-  caches_action :robots
-
-  def index
-    @news = News.latest User.current
-    @projects = Project.latest User.current
-  end
-
-  def robots
-    @projects = Project.all_public.active
-    render :layout => false, :content_type => 'text/plain'
-  end
-end
--- a/.svn/pristine/3d/3d264827557eaf8b65d3068714787c51e68d02b2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class DocumentCategoryCustomField < CustomField
-  def type_name
-    :enumeration_doc_categories
-  end
-end
--- a/.svn/pristine/3d/3d6522340e1723225cb18ddbafc5c9dc0b5f8799.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssueCategory < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  belongs_to :project
-  belongs_to :assigned_to, :class_name => 'Principal', :foreign_key => 'assigned_to_id'
-  has_many :issues, :foreign_key => 'category_id', :dependent => :nullify
-
-  validates_presence_of :name
-  validates_uniqueness_of :name, :scope => [:project_id]
-  validates_length_of :name, :maximum => 30
-
-  safe_attributes 'name', 'assigned_to_id'
-
-  scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
-
-  alias :destroy_without_reassign :destroy
-
-  # Destroy the category
-  # If a category is specified, issues are reassigned to this category
-  def destroy(reassign_to = nil)
-    if reassign_to && reassign_to.is_a?(IssueCategory) && reassign_to.project == self.project
-      Issue.update_all({:category_id => reassign_to.id}, {:category_id => id})
-    end
-    destroy_without_reassign
-  end
-
-  def <=>(category)
-    name <=> category.name
-  end
-
-  def to_s; name end
-end
--- a/.svn/pristine/3d/3d7003238eceffbbaba3bf34003b59ea441ffc00.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Activity
-
-    mattr_accessor :available_event_types, :default_event_types, :providers
-
-    @@available_event_types = []
-    @@default_event_types = []
-    @@providers = Hash.new {|h,k| h[k]=[] }
-
-    class << self
-      def map(&block)
-        yield self
-      end
-
-      # Registers an activity provider
-      def register(event_type, options={})
-        options.assert_valid_keys(:class_name, :default)
-
-        event_type = event_type.to_s
-        providers = options[:class_name] || event_type.classify
-        providers = ([] << providers) unless providers.is_a?(Array)
-
-        @@available_event_types << event_type unless @@available_event_types.include?(event_type)
-        @@default_event_types << event_type unless options[:default] == false
-        @@providers[event_type] += providers
-      end
-    end
-  end
-end
--- a/.svn/pristine/3e/3e7a4b29a1b991aef04200318dd8a5df349fe39d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,351 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class AccountController < ApplicationController
-  helper :custom_fields
-  include CustomFieldsHelper
-
-  # prevents login action to be filtered by check_if_login_required application scope filter
-  skip_before_filter :check_if_login_required, :check_password_change
-
-  # Overrides ApplicationController#verify_authenticity_token to disable
-  # token verification on openid callbacks
-  def verify_authenticity_token
-    unless using_open_id?
-      super
-    end
-  end
-
-  # Login request and validation
-  def login
-    if request.get?
-      if User.current.logged?
-        redirect_to home_url
-      end
-    else
-      authenticate_user
-    end
-  rescue AuthSourceException => e
-    logger.error "An error occured when authenticating #{params[:username]}: #{e.message}"
-    render_error :message => e.message
-  end
-
-  # Log out current user and redirect to welcome page
-  def logout
-    if User.current.anonymous?
-      redirect_to home_url
-    elsif request.post?
-      logout_user
-      redirect_to home_url
-    end
-    # display the logout form
-  end
-
-  # Lets user choose a new password
-  def lost_password
-    (redirect_to(home_url); return) unless Setting.lost_password?
-    if params[:token]
-      @token = Token.find_token("recovery", params[:token].to_s)
-      if @token.nil? || @token.expired?
-        redirect_to home_url
-        return
-      end
-      @user = @token.user
-      unless @user && @user.active?
-        redirect_to home_url
-        return
-      end
-      if request.post?
-        @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
-        if @user.save
-          @token.destroy
-          flash[:notice] = l(:notice_account_password_updated)
-          redirect_to signin_path
-          return
-        end
-      end
-      render :template => "account/password_recovery"
-      return
-    else
-      if request.post?
-        user = User.find_by_mail(params[:mail].to_s)
-        # user not found
-        unless user
-          flash.now[:error] = l(:notice_account_unknown_email)
-          return
-        end
-        unless user.active?
-          handle_inactive_user(user, lost_password_path)
-          return
-        end
-        # user cannot change its password
-        unless user.change_password_allowed?
-          flash.now[:error] = l(:notice_can_t_change_password)
-          return
-        end
-        # create a new token for password recovery
-        token = Token.new(:user => user, :action => "recovery")
-        if token.save
-          Mailer.lost_password(token).deliver
-          flash[:notice] = l(:notice_account_lost_email_sent)
-          redirect_to signin_path
-          return
-        end
-      end
-    end
-  end
-
-  # User self-registration
-  def register
-    (redirect_to(home_url); return) unless Setting.self_registration? || session[:auth_source_registration]
-    if request.get?
-      session[:auth_source_registration] = nil
-      @user = User.new(:language => current_language.to_s)
-    else
-      user_params = params[:user] || {}
-      @user = User.new
-      @user.safe_attributes = user_params
-      @user.admin = false
-      @user.register
-      if session[:auth_source_registration]
-        @user.activate
-        @user.login = session[:auth_source_registration][:login]
-        @user.auth_source_id = session[:auth_source_registration][:auth_source_id]
-        if @user.save
-          session[:auth_source_registration] = nil
-          self.logged_user = @user
-          flash[:notice] = l(:notice_account_activated)
-          redirect_to my_account_path
-        end
-      else
-        @user.login = params[:user][:login]
-        unless user_params[:identity_url].present? && user_params[:password].blank? && user_params[:password_confirmation].blank?
-          @user.password, @user.password_confirmation = user_params[:password], user_params[:password_confirmation]
-        end
-
-        case Setting.self_registration
-        when '1'
-          register_by_email_activation(@user)
-        when '3'
-          register_automatically(@user)
-        else
-          register_manually_by_administrator(@user)
-        end
-      end
-    end
-  end
-
-  # Token based account activation
-  def activate
-    (redirect_to(home_url); return) unless Setting.self_registration? && params[:token].present?
-    token = Token.find_token('register', params[:token].to_s)
-    (redirect_to(home_url); return) unless token and !token.expired?
-    user = token.user
-    (redirect_to(home_url); return) unless user.registered?
-    user.activate
-    if user.save
-      token.destroy
-      flash[:notice] = l(:notice_account_activated)
-    end
-    redirect_to signin_path
-  end
-
-  # Sends a new account activation email
-  def activation_email
-    if session[:registered_user_id] && Setting.self_registration == '1'
-      user_id = session.delete(:registered_user_id).to_i
-      user = User.find_by_id(user_id)
-      if user && user.registered?
-        register_by_email_activation(user)
-        return
-      end
-    end
-    redirect_to(home_url)
-  end
-
-  private
-
-  def authenticate_user
-    if Setting.openid? && using_open_id?
-      open_id_authenticate(params[:openid_url])
-    else
-      password_authentication
-    end
-  end
-
-  def password_authentication
-    user = User.try_to_login(params[:username], params[:password], false)
-
-    if user.nil?
-      invalid_credentials
-    elsif user.new_record?
-      onthefly_creation_failed(user, {:login => user.login, :auth_source_id => user.auth_source_id })
-    else
-      # Valid user
-      if user.active?
-        successful_authentication(user)
-      else
-        handle_inactive_user(user)
-      end
-    end
-  end
-
-  def open_id_authenticate(openid_url)
-    back_url = signin_url(:autologin => params[:autologin])
-    authenticate_with_open_id(
-          openid_url, :required => [:nickname, :fullname, :email],
-          :return_to => back_url, :method => :post
-    ) do |result, identity_url, registration|
-      if result.successful?
-        user = User.find_or_initialize_by_identity_url(identity_url)
-        if user.new_record?
-          # Self-registration off
-          (redirect_to(home_url); return) unless Setting.self_registration?
-          # Create on the fly
-          user.login = registration['nickname'] unless registration['nickname'].nil?
-          user.mail = registration['email'] unless registration['email'].nil?
-          user.firstname, user.lastname = registration['fullname'].split(' ') unless registration['fullname'].nil?
-          user.random_password
-          user.register
-          case Setting.self_registration
-          when '1'
-            register_by_email_activation(user) do
-              onthefly_creation_failed(user)
-            end
-          when '3'
-            register_automatically(user) do
-              onthefly_creation_failed(user)
-            end
-          else
-            register_manually_by_administrator(user) do
-              onthefly_creation_failed(user)
-            end
-          end
-        else
-          # Existing record
-          if user.active?
-            successful_authentication(user)
-          else
-            handle_inactive_user(user)
-          end
-        end
-      end
-    end
-  end
-
-  def successful_authentication(user)
-    logger.info "Successful authentication for '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}"
-    # Valid user
-    self.logged_user = user
-    # generate a key and set cookie if autologin
-    if params[:autologin] && Setting.autologin?
-      set_autologin_cookie(user)
-    end
-    call_hook(:controller_account_success_authentication_after, {:user => user })
-    redirect_back_or_default my_page_path
-  end
-
-  def set_autologin_cookie(user)
-    token = Token.create(:user => user, :action => 'autologin')
-    cookie_options = {
-      :value => token.value,
-      :expires => 1.year.from_now,
-      :path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
-      :secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
-      :httponly => true
-    }
-    cookies[autologin_cookie_name] = cookie_options
-  end
-
-  # Onthefly creation failed, display the registration form to fill/fix attributes
-  def onthefly_creation_failed(user, auth_source_options = { })
-    @user = user
-    session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
-    render :action => 'register'
-  end
-
-  def invalid_credentials
-    logger.warn "Failed login for '#{params[:username]}' from #{request.remote_ip} at #{Time.now.utc}"
-    flash.now[:error] = l(:notice_account_invalid_creditentials)
-  end
-
-  # Register a user for email activation.
-  #
-  # Pass a block for behavior when a user fails to save
-  def register_by_email_activation(user, &block)
-    token = Token.new(:user => user, :action => "register")
-    if user.save and token.save
-      Mailer.register(token).deliver
-      flash[:notice] = l(:notice_account_register_done, :email => user.mail)
-      redirect_to signin_path
-    else
-      yield if block_given?
-    end
-  end
-
-  # Automatically register a user
-  #
-  # Pass a block for behavior when a user fails to save
-  def register_automatically(user, &block)
-    # Automatic activation
-    user.activate
-    user.last_login_on = Time.now
-    if user.save
-      self.logged_user = user
-      flash[:notice] = l(:notice_account_activated)
-      redirect_to my_account_path
-    else
-      yield if block_given?
-    end
-  end
-
-  # Manual activation by the administrator
-  #
-  # Pass a block for behavior when a user fails to save
-  def register_manually_by_administrator(user, &block)
-    if user.save
-      # Sends an email to the administrators
-      Mailer.account_activation_request(user).deliver
-      account_pending(user)
-    else
-      yield if block_given?
-    end
-  end
-
-  def handle_inactive_user(user, redirect_path=signin_path)
-    if user.registered?
-      account_pending(user, redirect_path)
-    else
-      account_locked(user, redirect_path)
-    end
-  end
-
-  def account_pending(user, redirect_path=signin_path)
-    if Setting.self_registration == '1'
-      flash[:error] = l(:notice_account_not_activated_yet, :url => activation_email_path)
-      session[:registered_user_id] = user.id
-    else
-      flash[:error] = l(:notice_account_pending)
-    end
-    redirect_to redirect_path
-  end
-
-  def account_locked(user, redirect_path=signin_path)
-    flash[:error] = l(:notice_account_locked)
-    redirect_to redirect_path
-  end
-end
--- a/.svn/pristine/3f/3f7e33eb719b73cf1721b389cca78ecdef336acd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module JournalsHelper
-  def render_notes(issue, journal, options={})
-    content = ''
-    editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
-    links = []
-    if !journal.notes.blank?
-      links << link_to(image_tag('comment.png'),
-                       {:controller => 'journals', :action => 'new', :id => issue, :journal_id => journal},
-                       :remote => true,
-                       :method => 'post',
-                       :title => l(:button_quote)) if options[:reply_links]
-      links << link_to_in_place_notes_editor(image_tag('edit.png'), "journal-#{journal.id}-notes",
-                                             { :controller => 'journals', :action => 'edit', :id => journal, :format => 'js' },
-                                                :title => l(:button_edit)) if editable
-    end
-    content << content_tag('div', links.join(' ').html_safe, :class => 'contextual') unless links.empty?
-    content << textilizable(journal, :notes)
-    css_classes = "wiki"
-    css_classes << " editable" if editable
-    content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes)
-  end
-
-  def link_to_in_place_notes_editor(text, field_id, url, options={})
-    onclick = "$.ajax({url: '#{url_for(url)}', type: 'get'}); return false;"
-    link_to text, '#', options.merge(:onclick => onclick)
-  end
-end
--- a/.svn/pristine/3f/3f94297661bca0411e24d438a57b40f9f718ed59.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,438 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'SVG/Graph/Bar'
-require 'SVG/Graph/BarHorizontal'
-require 'digest/sha1'
-require 'redmine/scm/adapters'
-
-class ChangesetNotFound < Exception; end
-class InvalidRevisionParam < Exception; end
-
-class RepositoriesController < ApplicationController
-  menu_item :repository
-  menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers]
-  default_search_scope :changesets
-
-  before_filter :find_project_by_project_id, :only => [:new, :create]
-  before_filter :find_repository, :only => [:edit, :update, :destroy, :committers]
-  before_filter :find_project_repository, :except => [:new, :create, :edit, :update, :destroy, :committers]
-  before_filter :find_changeset, :only => [:revision, :add_related_issue, :remove_related_issue]
-  before_filter :authorize
-  accept_rss_auth :revisions
-
-  rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed
-
-  def new
-    scm = params[:repository_scm] || (Redmine::Scm::Base.all & Setting.enabled_scm).first
-    @repository = Repository.factory(scm)
-    @repository.is_default = @project.repository.nil?
-    @repository.project = @project
-  end
-
-  def create
-    attrs = pickup_extra_info
-    @repository = Repository.factory(params[:repository_scm])
-    @repository.safe_attributes = params[:repository]
-    if attrs[:attrs_extra].keys.any?
-      @repository.merge_extra_info(attrs[:attrs_extra])
-    end
-    @repository.project = @project
-    if request.post? && @repository.save
-      redirect_to settings_project_path(@project, :tab => 'repositories')
-    else
-      render :action => 'new'
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    attrs = pickup_extra_info
-    @repository.safe_attributes = attrs[:attrs]
-    if attrs[:attrs_extra].keys.any?
-      @repository.merge_extra_info(attrs[:attrs_extra])
-    end
-    @repository.project = @project
-    if request.put? && @repository.save
-      redirect_to settings_project_path(@project, :tab => 'repositories')
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def pickup_extra_info
-    p       = {}
-    p_extra = {}
-    params[:repository].each do |k, v|
-      if k =~ /^extra_/
-        p_extra[k] = v
-      else
-        p[k] = v
-      end
-    end
-    {:attrs => p, :attrs_extra => p_extra}
-  end
-  private :pickup_extra_info
-
-  def committers
-    @committers = @repository.committers
-    @users = @project.users
-    additional_user_ids = @committers.collect(&:last).collect(&:to_i) - @users.collect(&:id)
-    @users += User.find_all_by_id(additional_user_ids) unless additional_user_ids.empty?
-    @users.compact!
-    @users.sort!
-    if request.post? && params[:committers].is_a?(Hash)
-      # Build a hash with repository usernames as keys and corresponding user ids as values
-      @repository.committer_ids = params[:committers].values.inject({}) {|h, c| h[c.first] = c.last; h}
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to settings_project_path(@project, :tab => 'repositories')
-    end
-  end
-
-  def destroy
-    @repository.destroy if request.delete?
-    redirect_to settings_project_path(@project, :tab => 'repositories')
-  end
-
-  def show
-    @repository.fetch_changesets if @project.active? && Setting.autofetch_changesets? && @path.empty?
-
-    @entries = @repository.entries(@path, @rev)
-    @changeset = @repository.find_changeset_by_name(@rev)
-    if request.xhr?
-      @entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
-    else
-      (show_error_not_found; return) unless @entries
-      @changesets = @repository.latest_changesets(@path, @rev)
-      @properties = @repository.properties(@path, @rev)
-      @repositories = @project.repositories
-      render :action => 'show'
-    end
-  end
-
-  alias_method :browse, :show
-
-  def changes
-    @entry = @repository.entry(@path, @rev)
-    (show_error_not_found; return) unless @entry
-    @changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i)
-    @properties = @repository.properties(@path, @rev)
-    @changeset = @repository.find_changeset_by_name(@rev)
-  end
-
-  def revisions
-    @changeset_count = @repository.changesets.count
-    @changeset_pages = Paginator.new @changeset_count,
-                                     per_page_option,
-                                     params['page']
-    @changesets = @repository.changesets.
-      limit(@changeset_pages.per_page).
-      offset(@changeset_pages.offset).
-      includes(:user, :repository, :parents).
-      all
-
-    respond_to do |format|
-      format.html { render :layout => false if request.xhr? }
-      format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
-    end
-  end
-
-  def raw
-    entry_and_raw(true)
-  end
-
-  def entry
-    entry_and_raw(false)
-  end
-
-  def entry_and_raw(is_raw)
-    @entry = @repository.entry(@path, @rev)
-    (show_error_not_found; return) unless @entry
-
-    # If the entry is a dir, show the browser
-    (show; return) if @entry.is_dir?
-
-    @content = @repository.cat(@path, @rev)
-    (show_error_not_found; return) unless @content
-    if is_raw ||
-         (@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) ||
-         ! is_entry_text_data?(@content, @path)
-      # Force the download
-      send_opt = { :filename => filename_for_content_disposition(@path.split('/').last) }
-      send_type = Redmine::MimeType.of(@path)
-      send_opt[:type] = send_type.to_s if send_type
-      send_opt[:disposition] = (Redmine::MimeType.is_type?('image', @path) && !is_raw ? 'inline' : 'attachment')
-      send_data @content, send_opt
-    else
-      # Prevent empty lines when displaying a file with Windows style eol
-      # TODO: UTF-16
-      # Is this needs? AttachmentsController reads file simply.
-      @content.gsub!("\r\n", "\n")
-      @changeset = @repository.find_changeset_by_name(@rev)
-    end
-  end
-  private :entry_and_raw
-
-  def is_entry_text_data?(ent, path)
-    # UTF-16 contains "\x00".
-    # It is very strict that file contains less than 30% of ascii symbols
-    # in non Western Europe.
-    return true if Redmine::MimeType.is_type?('text', path)
-    # Ruby 1.8.6 has a bug of integer divisions.
-    # http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
-    return false if ent.is_binary_data?
-    true
-  end
-  private :is_entry_text_data?
-
-  def annotate
-    @entry = @repository.entry(@path, @rev)
-    (show_error_not_found; return) unless @entry
-
-    @annotate = @repository.scm.annotate(@path, @rev)
-    if @annotate.nil? || @annotate.empty?
-      (render_error l(:error_scm_annotate); return)
-    end
-    ann_buf_size = 0
-    @annotate.lines.each do |buf|
-      ann_buf_size += buf.size
-    end
-    if ann_buf_size > Setting.file_max_size_displayed.to_i.kilobyte
-      (render_error l(:error_scm_annotate_big_text_file); return)
-    end
-    @changeset = @repository.find_changeset_by_name(@rev)
-  end
-
-  def revision
-    respond_to do |format|
-      format.html
-      format.js {render :layout => false}
-    end
-  end
-
-  # Adds a related issue to a changeset
-  # POST /projects/:project_id/repository/(:repository_id/)revisions/:rev/issues
-  def add_related_issue
-    issue_id = params[:issue_id].to_s.sub(/^#/,'')
-    @issue = @changeset.find_referenced_issue_by_id(issue_id)
-    if @issue && (!@issue.visible? || @changeset.issues.include?(@issue))
-      @issue = nil
-    end
-
-    if @issue
-      @changeset.issues << @issue
-    end
-  end
-
-  # Removes a related issue from a changeset
-  # DELETE /projects/:project_id/repository/(:repository_id/)revisions/:rev/issues/:issue_id
-  def remove_related_issue
-    @issue = Issue.visible.find_by_id(params[:issue_id])
-    if @issue
-      @changeset.issues.delete(@issue)
-    end
-  end
-
-  def diff
-    if params[:format] == 'diff'
-      @diff = @repository.diff(@path, @rev, @rev_to)
-      (show_error_not_found; return) unless @diff
-      filename = "changeset_r#{@rev}"
-      filename << "_r#{@rev_to}" if @rev_to
-      send_data @diff.join, :filename => "#{filename}.diff",
-                            :type => 'text/x-patch',
-                            :disposition => 'attachment'
-    else
-      @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
-      @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
-
-      # Save diff type as user preference
-      if User.current.logged? && @diff_type != User.current.pref[:diff_type]
-        User.current.pref[:diff_type] = @diff_type
-        User.current.preference.save
-      end
-      @cache_key = "repositories/diff/#{@repository.id}/" +
-                      Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}")
-      unless read_fragment(@cache_key)
-        @diff = @repository.diff(@path, @rev, @rev_to)
-        show_error_not_found unless @diff
-      end
-
-      @changeset = @repository.find_changeset_by_name(@rev)
-      @changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil
-      @diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to)
-    end
-  end
-
-  def stats
-  end
-
-  def graph
-    data = nil
-    case params[:graph]
-    when "commits_per_month"
-      data = graph_commits_per_month(@repository)
-    when "commits_per_author"
-      data = graph_commits_per_author(@repository)
-    end
-    if data
-      headers["Content-Type"] = "image/svg+xml"
-      send_data(data, :type => "image/svg+xml", :disposition => "inline")
-    else
-      render_404
-    end
-  end
-
-  private
-
-  def find_repository
-    @repository = Repository.find(params[:id])
-    @project = @repository.project
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
-
-  def find_project_repository
-    @project = Project.find(params[:id])
-    if params[:repository_id].present?
-      @repository = @project.repositories.find_by_identifier_param(params[:repository_id])
-    else
-      @repository = @project.repository
-    end
-    (render_404; return false) unless @repository
-    @path = params[:path].is_a?(Array) ? params[:path].join('/') : params[:path].to_s
-    @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip
-    @rev_to = params[:rev_to]
-
-    unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
-      if @repository.branches.blank?
-        raise InvalidRevisionParam
-      end
-    end
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  rescue InvalidRevisionParam
-    show_error_not_found
-  end
-
-  def find_changeset
-    if @rev.present?
-      @changeset = @repository.find_changeset_by_name(@rev)
-    end
-    show_error_not_found unless @changeset
-  end
-
-  def show_error_not_found
-    render_error :message => l(:error_scm_not_found), :status => 404
-  end
-
-  # Handler for Redmine::Scm::Adapters::CommandFailed exception
-  def show_error_command_failed(exception)
-    render_error l(:error_scm_command_failed, exception.message)
-  end
-
-  def graph_commits_per_month(repository)
-    @date_to = Date.today
-    @date_from = @date_to << 11
-    @date_from = Date.civil(@date_from.year, @date_from.month, 1)
-    commits_by_day = Changeset.
-      where("repository_id = ? AND commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to).
-      group(:commit_date).
-      count
-    commits_by_month = [0] * 12
-    commits_by_day.each {|c| commits_by_month[(@date_to.month - c.first.to_date.month) % 12] += c.last }
-
-    changes_by_day = Change.
-      joins(:changeset).
-      where("#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to).
-      group(:commit_date).
-      count
-    changes_by_month = [0] * 12
-    changes_by_day.each {|c| changes_by_month[(@date_to.month - c.first.to_date.month) % 12] += c.last }
-
-    fields = []
-    12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)}
-
-    graph = SVG::Graph::Bar.new(
-      :height => 300,
-      :width => 800,
-      :fields => fields.reverse,
-      :stack => :side,
-      :scale_integers => true,
-      :step_x_labels => 2,
-      :show_data_values => false,
-      :graph_title => l(:label_commits_per_month),
-      :show_graph_title => true
-    )
-
-    graph.add_data(
-      :data => commits_by_month[0..11].reverse,
-      :title => l(:label_revision_plural)
-    )
-
-    graph.add_data(
-      :data => changes_by_month[0..11].reverse,
-      :title => l(:label_change_plural)
-    )
-
-    graph.burn
-  end
-
-  def graph_commits_per_author(repository)
-    commits_by_author = Changeset.where("repository_id = ?", repository.id).group(:committer).count
-    commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}
-
-    changes_by_author = Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", repository.id).group(:committer).count
-    h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
-
-    fields = commits_by_author.collect {|r| r.first}
-    commits_data = commits_by_author.collect {|r| r.last}
-    changes_data = commits_by_author.collect {|r| h[r.first] || 0}
-
-    fields = fields + [""]*(10 - fields.length) if fields.length<10
-    commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
-    changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
-
-    # Remove email adress in usernames
-    fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') }
-
-    graph = SVG::Graph::BarHorizontal.new(
-      :height => 30 * commits_data.length,
-      :width => 800,
-      :fields => fields,
-      :stack => :side,
-      :scale_integers => true,
-      :show_data_values => false,
-      :rotate_y_labels => false,
-      :graph_title => l(:label_commits_per_author),
-      :show_graph_title => true
-    )
-    graph.add_data(
-      :data => commits_data,
-      :title => l(:label_revision_plural)
-    )
-    graph.add_data(
-      :data => changes_data,
-      :title => l(:label_change_plural)
-    )
-    graph.burn
-  end
-end
--- a/.svn/pristine/40/40689c0c3542244c3df167e6c12a7f9af9376e9b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module DocumentsHelper
-end
--- a/.svn/pristine/40/407f7e2d4e08a32e78ca65cbc6b2ee007be59736.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class WorkflowRule < ActiveRecord::Base
-  self.table_name = "#{table_name_prefix}workflows#{table_name_suffix}"
-
-  belongs_to :role
-  belongs_to :tracker
-  belongs_to :old_status, :class_name => 'IssueStatus', :foreign_key => 'old_status_id'
-  belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id'
-
-  validates_presence_of :role, :tracker, :old_status
-
-  # Copies workflows from source to targets
-  def self.copy(source_tracker, source_role, target_trackers, target_roles)
-    unless source_tracker.is_a?(Tracker) || source_role.is_a?(Role)
-      raise ArgumentError.new("source_tracker or source_role must be specified")
-    end
-
-    target_trackers = [target_trackers].flatten.compact
-    target_roles = [target_roles].flatten.compact
-
-    target_trackers = Tracker.sorted.all if target_trackers.empty?
-    target_roles = Role.all if target_roles.empty?
-
-    target_trackers.each do |target_tracker|
-      target_roles.each do |target_role|
-        copy_one(source_tracker || target_tracker,
-                   source_role || target_role,
-                   target_tracker,
-                   target_role)
-      end
-    end
-  end
-
-  # Copies a single set of workflows from source to target
-  def self.copy_one(source_tracker, source_role, target_tracker, target_role)
-    unless source_tracker.is_a?(Tracker) && !source_tracker.new_record? &&
-      source_role.is_a?(Role) && !source_role.new_record? &&
-      target_tracker.is_a?(Tracker) && !target_tracker.new_record? &&
-      target_role.is_a?(Role) && !target_role.new_record?
-
-      raise ArgumentError.new("arguments can not be nil or unsaved objects")
-    end
-
-    if source_tracker == target_tracker && source_role == target_role
-      false
-    else
-      transaction do
-        delete_all :tracker_id => target_tracker.id, :role_id => target_role.id
-        connection.insert "INSERT INTO #{WorkflowRule.table_name} (tracker_id, role_id, old_status_id, new_status_id, author, assignee, field_name, #{connection.quote_column_name 'rule'}, type)" +
-                          " SELECT #{target_tracker.id}, #{target_role.id}, old_status_id, new_status_id, author, assignee, field_name, #{connection.quote_column_name 'rule'}, type" +
-                          " FROM #{WorkflowRule.table_name}" +
-                          " WHERE tracker_id = #{source_tracker.id} AND role_id = #{source_role.id}"
-      end
-      true
-    end
-  end
-end
--- a/.svn/pristine/40/40b857ca7c7de72d5c1758ba52344afd6a5847fd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class SearchCustomFieldsVisibilityTest < ActionController::TestCase
-  tests SearchController
-  fixtures :projects,
-           :users,
-           :roles,
-           :members,
-           :member_roles,
-           :issue_statuses,
-           :trackers,
-           :projects_trackers,
-           :enabled_modules,
-           :enumerations,
-           :workflows
-
-  def setup
-    field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :searchable => true, :trackers => Tracker.all}
-    @fields = []
-    @fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true)))
-    @fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2])))
-    @fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3])))
-    @issue = Issue.generate!(
-      :author_id => 1,
-      :project_id => 1,
-      :tracker_id => 1,
-      :custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'}
-    )
-
-    @user_with_role_on_other_project = User.generate!
-    User.add_to_project(@user_with_role_on_other_project, Project.find(2), Role.find(3))
-
-    @users_to_test = {
-      User.find(1) => [@field1, @field2, @field3],
-      User.find(3) => [@field1, @field2],
-      @user_with_role_on_other_project => [@field1], # should see field1 only on Project 1
-      User.generate! => [@field1],
-      User.anonymous => [@field1]
-    }
-
-    Member.where(:project_id => 1).each do |member|
-      member.destroy unless @users_to_test.keys.include?(member.principal)
-    end
-  end
-
-  def test_search_should_search_visible_custom_fields_only
-    @users_to_test.each do |user, fields|
-      @request.session[:user_id] = user.id
-      @fields.each_with_index do |field, i|
-        get :index, :q => "value#{i}"
-        assert_response :success
-        # we should get a result only if the custom field is visible
-        if fields.include?(field)
-          assert_equal 1, assigns(:results).size
-        else
-          assert_equal 0, assigns(:results).size
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/41/4113a8ca258eb3b9d10aacea8fe7152c8f9122c6.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,364 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::UnifiedDiffTest < ActiveSupport::TestCase
-  def test_subversion_diff
-    diff = Redmine::UnifiedDiff.new(read_diff_fixture('subversion.diff'))
-    # number of files
-    assert_equal 4, diff.size
-    assert diff.detect {|file| file.file_name =~ %r{^config/settings.yml}}
-  end
-
-  def test_truncate_diff
-    diff = Redmine::UnifiedDiff.new(read_diff_fixture('subversion.diff'), :max_lines => 20)
-    assert_equal 2, diff.size
-  end
-
-  def test_inline_partials
-    diff = Redmine::UnifiedDiff.new(read_diff_fixture('partials.diff'))
-    assert_equal 1, diff.size
-    diff = diff.first
-    assert_equal 43, diff.size
-
-    assert_equal [51, -1], diff[0].offsets
-    assert_equal [51, -1], diff[1].offsets
-    assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>elit</span>', diff[0].html_line
-    assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>xx</span>', diff[1].html_line
-
-    assert_nil diff[2].offsets
-    assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[2].html_line
-
-    assert_equal [0, -14], diff[3].offsets
-    assert_equal [0, -14], diff[4].offsets
-    assert_equal '<span>Ut sed</span> auctor justo', diff[3].html_line
-    assert_equal '<span>xxx</span> auctor justo', diff[4].html_line
-
-    assert_equal [13, -19], diff[6].offsets
-    assert_equal [13, -19], diff[7].offsets
-
-    assert_equal [24, -8], diff[9].offsets
-    assert_equal [24, -8], diff[10].offsets
-
-    assert_equal [37, -1], diff[12].offsets
-    assert_equal [37, -1], diff[13].offsets
-
-    assert_equal [0, -38], diff[15].offsets
-    assert_equal [0, -38], diff[16].offsets
-  end
-
-  def test_side_by_side_partials
-    diff = Redmine::UnifiedDiff.new(read_diff_fixture('partials.diff'), :type => 'sbs')
-    assert_equal 1, diff.size
-    diff = diff.first
-    assert_equal 32, diff.size
-
-    assert_equal [51, -1], diff[0].offsets
-    assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>elit</span>', diff[0].html_line_left
-    assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>xx</span>', diff[0].html_line_right
-
-    assert_nil diff[1].offsets
-    assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[1].html_line_left
-    assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[1].html_line_right
-
-    assert_equal [0, -14], diff[2].offsets
-    assert_equal '<span>Ut sed</span> auctor justo', diff[2].html_line_left
-    assert_equal '<span>xxx</span> auctor justo', diff[2].html_line_right
-
-    assert_equal [13, -19], diff[4].offsets
-    assert_equal [24, -8], diff[6].offsets
-    assert_equal [37, -1], diff[8].offsets
-    assert_equal [0, -38], diff[10].offsets
-
-  end
-
-  def test_partials_with_html_entities
-    raw = <<-DIFF
---- test.orig.txt Wed Feb 15 16:10:39 2012
-+++ test.new.txt  Wed Feb 15 16:11:25 2012
-@@ -1,5 +1,5 @@
- Semicolons were mysteriously appearing in code diffs in the repository
- 
--void DoSomething(std::auto_ptr<MyClass> myObj)
-+void DoSomething(const MyClass& myObj)
- 
-DIFF
-
-    diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
-    assert_equal 1, diff.size
-    assert_equal 'void DoSomething(<span>std::auto_ptr&lt;MyClass&gt;</span> myObj)', diff.first[2].html_line_left
-    assert_equal 'void DoSomething(<span>const MyClass&amp;</span> myObj)', diff.first[2].html_line_right
-
-    diff = Redmine::UnifiedDiff.new(raw, :type => 'inline')
-    assert_equal 1, diff.size
-    assert_equal 'void DoSomething(<span>std::auto_ptr&lt;MyClass&gt;</span> myObj)', diff.first[2].html_line
-    assert_equal 'void DoSomething(<span>const MyClass&amp;</span> myObj)', diff.first[3].html_line
-  end
-
-  def test_line_starting_with_dashes
-    diff = Redmine::UnifiedDiff.new(<<-DIFF
---- old.txt Wed Nov 11 14:24:58 2009
-+++ new.txt Wed Nov 11 14:25:02 2009
-@@ -1,8 +1,4 @@
--Lines that starts with dashes:
--
--------------------------
---- file.c
--------------------------
-+A line that starts with dashes:
- 
- and removed.
- 
-@@ -23,4 +19,4 @@
- 
- 
- 
--Another chunk of change
-+Another chunk of changes
-
-DIFF
-    )
-    assert_equal 1, diff.size
-  end
-
-  def test_one_line_new_files
-    diff = Redmine::UnifiedDiff.new(<<-DIFF
-diff -r 000000000000 -r ea98b14f75f0 README1
---- /dev/null
-+++ b/README1
-@@ -0,0 +1,1 @@
-+test1
-diff -r 000000000000 -r ea98b14f75f0 README2
---- /dev/null
-+++ b/README2
-@@ -0,0 +1,1 @@
-+test2
-diff -r 000000000000 -r ea98b14f75f0 README3
---- /dev/null
-+++ b/README3
-@@ -0,0 +1,3 @@
-+test4
-+test5
-+test6
-diff -r 000000000000 -r ea98b14f75f0 README4
---- /dev/null
-+++ b/README4
-@@ -0,0 +1,3 @@
-+test4
-+test5
-+test6
-DIFF
-    )
-    assert_equal 4, diff.size
-    assert_equal "README1", diff[0].file_name
-  end
-
-  def test_both_git_diff
-    diff = Redmine::UnifiedDiff.new(<<-DIFF
-# HG changeset patch
-# User test
-# Date 1348014182 -32400
-# Node ID d1c871b8ef113df7f1c56d41e6e3bfbaff976e1f
-# Parent  180b6605936cdc7909c5f08b59746ec1a7c99b3e
-modify test1.txt
-
-diff -r 180b6605936c -r d1c871b8ef11 test1.txt
---- a/test1.txt
-+++ b/test1.txt
-@@ -1,1 +1,1 @@
--test1
-+modify test1
-DIFF
-    )
-    assert_equal 1, diff.size
-    assert_equal "test1.txt", diff[0].file_name
-  end
-
-  def test_include_a_b_slash
-    diff = Redmine::UnifiedDiff.new(<<-DIFF
---- test1.txt
-+++ b/test02.txt
-@@ -1 +0,0 @@
--modify test1
-DIFF
-    )
-    assert_equal 1, diff.size
-    assert_equal "b/test02.txt", diff[0].file_name
-
-    diff = Redmine::UnifiedDiff.new(<<-DIFF
---- a/test1.txt
-+++ a/test02.txt
-@@ -1 +0,0 @@
--modify test1
-DIFF
-    )
-    assert_equal 1, diff.size
-    assert_equal "a/test02.txt", diff[0].file_name
-
-    diff = Redmine::UnifiedDiff.new(<<-DIFF
---- a/test1.txt
-+++ test02.txt
-@@ -1 +0,0 @@
--modify test1
-DIFF
-    )
-    assert_equal 1, diff.size
-    assert_equal "test02.txt", diff[0].file_name
-  end
-
-  def test_utf8_ja
-    ja = "  text_tip_issue_end_day: "
-    ja += "\xe3\x81\x93\xe3\x81\xae\xe6\x97\xa5\xe3\x81\xab\xe7\xb5\x82\xe4\xba\x86\xe3\x81\x99\xe3\x82\x8b<span>\xe3\x82\xbf\xe3\x82\xb9\xe3\x82\xaf</span>"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
-    with_settings :repositories_encodings => '' do
-      diff = Redmine::UnifiedDiff.new(read_diff_fixture('issue-12641-ja.diff'), :type => 'inline')
-      assert_equal 1, diff.size
-      assert_equal 12, diff.first.size
-      assert_equal ja, diff.first[4].html_line_left
-    end
-  end
-
-  def test_utf8_ru
-    ru = "        other: &quot;\xd0\xbe\xd0\xba\xd0\xbe\xd0\xbb\xd0\xbe %{count} \xd1\x87\xd0\xb0\xd1\x81<span>\xd0\xb0</span>&quot;"
-    ru.force_encoding('UTF-8') if ru.respond_to?(:force_encoding)
-    with_settings :repositories_encodings => '' do
-      diff = Redmine::UnifiedDiff.new(read_diff_fixture('issue-12641-ru.diff'), :type => 'inline')
-      assert_equal 1, diff.size
-      assert_equal 8, diff.first.size
-      assert_equal ru, diff.first[3].html_line_left
-    end
-  end
-
-  def test_offset_range_ascii_1
-    raw = <<-DIFF
---- a.txt	2013-04-05 14:19:39.000000000 +0900
-+++ b.txt	2013-04-05 14:19:51.000000000 +0900
-@@ -1,3 +1,3 @@
- aaaa
--abc
-+abcd
- bbbb
-DIFF
-    diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
-    assert_equal 1, diff.size
-    assert_equal 3, diff.first.size
-    assert_equal "abc<span></span>", diff.first[1].html_line_left
-    assert_equal "abc<span>d</span>", diff.first[1].html_line_right
-  end
-
-  def test_offset_range_ascii_2
-    raw = <<-DIFF
---- a.txt	2013-04-05 14:19:39.000000000 +0900
-+++ b.txt	2013-04-05 14:19:51.000000000 +0900
-@@ -1,3 +1,3 @@
- aaaa
--abc
-+zabc
- bbbb
-DIFF
-    diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
-    assert_equal 1, diff.size
-    assert_equal 3, diff.first.size
-    assert_equal "<span></span>abc", diff.first[1].html_line_left
-    assert_equal "<span>z</span>abc", diff.first[1].html_line_right
-  end
-
-  def test_offset_range_japanese_1
-    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span></span>"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x9e</span>"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
-    with_settings :repositories_encodings => '' do
-      diff = Redmine::UnifiedDiff.new(
-               read_diff_fixture('issue-13644-1.diff'), :type => 'sbs')
-      assert_equal 1, diff.size
-      assert_equal 3, diff.first.size
-      assert_equal ja1, diff.first[1].html_line_left
-      assert_equal ja2, diff.first[1].html_line_right
-    end
-  end
-
-  def test_offset_range_japanese_2
-    ja1 = "<span></span>\xe6\x97\xa5\xe6\x9c\xac"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "<span>\xe3\x81\xab\xe3\x81\xa3\xe3\x81\xbd\xe3\x82\x93</span>\xe6\x97\xa5\xe6\x9c\xac"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
-    with_settings :repositories_encodings => '' do
-      diff = Redmine::UnifiedDiff.new(
-               read_diff_fixture('issue-13644-2.diff'), :type => 'sbs')
-      assert_equal 1, diff.size
-      assert_equal 3, diff.first.size
-      assert_equal ja1, diff.first[1].html_line_left
-      assert_equal ja2, diff.first[1].html_line_right
-    end
-  end
-
-  def test_offset_range_japanese_3
-    # UTF-8 The 1st byte differs.
-    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe5\xa8\x98</span>"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
-    with_settings :repositories_encodings => '' do
-      diff = Redmine::UnifiedDiff.new(
-               read_diff_fixture('issue-13644-3.diff'), :type => 'sbs')
-      assert_equal 1, diff.size
-      assert_equal 3, diff.first.size
-      assert_equal ja1, diff.first[1].html_line_left
-      assert_equal ja2, diff.first[1].html_line_right
-    end
-  end
-
-  def test_offset_range_japanese_4
-    # UTF-8 The 2nd byte differs. 
-    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
-    with_settings :repositories_encodings => '' do
-      diff = Redmine::UnifiedDiff.new(
-               read_diff_fixture('issue-13644-4.diff'), :type => 'sbs')
-      assert_equal 1, diff.size
-      assert_equal 3, diff.first.size
-      assert_equal ja1, diff.first[1].html_line_left
-      assert_equal ja2, diff.first[1].html_line_right
-    end
-  end
-
-  def test_offset_range_japanese_5
-    # UTF-8 The 2nd byte differs. 
-    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>ok"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>ok"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
-    with_settings :repositories_encodings => '' do
-      diff = Redmine::UnifiedDiff.new(
-               read_diff_fixture('issue-13644-5.diff'), :type => 'sbs')
-      assert_equal 1, diff.size
-      assert_equal 3, diff.first.size
-      assert_equal ja1, diff.first[1].html_line_left
-      assert_equal ja2, diff.first[1].html_line_right
-    end
-  end
-
-  private
-
-  def read_diff_fixture(filename)
-    File.new(File.join(File.dirname(__FILE__), '/../../../fixtures/diffs', filename)).read
-  end
-end
--- a/.svn/pristine/41/414d847bcbb5d1b481c5b6e074d2d95ff30c291d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class UsersTest < ActionController::IntegrationTest
-  fixtures :users
-
-  def test_destroy_should_not_accept_get_requests
-    assert_no_difference 'User.count' do
-      get '/users/destroy/2', {}, credentials('admin')
-      assert_response 404
-    end
-  end
-end
--- a/.svn/pristine/41/41666c76b3a63b119e23476dd87dae257e309108.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class NewsController < ApplicationController
-  default_search_scope :news
-  model_object News
-  before_filter :find_model_object, :except => [:new, :create, :index]
-  before_filter :find_project_from_association, :except => [:new, :create, :index]
-  before_filter :find_project_by_project_id, :only => [:new, :create]
-  before_filter :authorize, :except => [:index]
-  before_filter :find_optional_project, :only => :index
-  accept_rss_auth :index
-  accept_api_auth :index
-
-  helper :watchers
-  helper :attachments
-
-  def index
-    case params[:format]
-    when 'xml', 'json'
-      @offset, @limit = api_offset_and_limit
-    else
-      @limit =  10
-    end
-
-    scope = @project ? @project.news.visible : News.visible
-
-    @news_count = scope.count
-    @news_pages = Paginator.new @news_count, @limit, params['page']
-    @offset ||= @news_pages.offset
-    @newss = scope.all(:include => [:author, :project],
-                                       :order => "#{News.table_name}.created_on DESC",
-                                       :offset => @offset,
-                                       :limit => @limit)
-
-    respond_to do |format|
-      format.html {
-        @news = News.new # for adding news inline
-        render :layout => false if request.xhr?
-      }
-      format.api
-      format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
-    end
-  end
-
-  def show
-    @comments = @news.comments
-    @comments.reverse! if User.current.wants_comments_in_reverse_order?
-  end
-
-  def new
-    @news = News.new(:project => @project, :author => User.current)
-  end
-
-  def create
-    @news = News.new(:project => @project, :author => User.current)
-    @news.safe_attributes = params[:news]
-    @news.save_attachments(params[:attachments])
-    if @news.save
-      render_attachment_warning_if_needed(@news)
-      flash[:notice] = l(:notice_successful_create)
-      redirect_to project_news_index_path(@project)
-    else
-      render :action => 'new'
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    @news.safe_attributes = params[:news]
-    @news.save_attachments(params[:attachments])
-    if @news.save
-      render_attachment_warning_if_needed(@news)
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to news_path(@news)
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def destroy
-    @news.destroy
-    redirect_to project_news_index_path(@project)
-  end
-
-  private
-
-  def find_optional_project
-    return true unless params[:project_id]
-    @project = Project.find(params[:project_id])
-    authorize
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/42/42095fdeb59e4c54c780a1fd8312c01640c1df4f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueRelationsControllerTest < ActionController::TestCase
-  fixtures :projects,
-           :users,
-           :roles,
-           :members,
-           :member_roles,
-           :issues,
-           :issue_statuses,
-           :issue_relations,
-           :enabled_modules,
-           :enumerations,
-           :trackers,
-           :projects_trackers
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 3
-  end
-
-  def test_create
-    assert_difference 'IssueRelation.count' do
-      post :create, :issue_id => 1,
-                 :relation => {:issue_to_id => '2', :relation_type => 'relates', :delay => ''}
-    end
-    relation = IssueRelation.first(:order => 'id DESC')
-    assert_equal 1, relation.issue_from_id
-    assert_equal 2, relation.issue_to_id
-    assert_equal 'relates', relation.relation_type
-  end
-
-  def test_create_xhr
-    assert_difference 'IssueRelation.count' do
-      xhr :post, :create, :issue_id => 3, :relation => {:issue_to_id => '1', :relation_type => 'relates', :delay => ''}
-      assert_response :success
-      assert_template 'create'
-      assert_equal 'text/javascript', response.content_type
-    end
-    relation = IssueRelation.first(:order => 'id DESC')
-    assert_equal 3, relation.issue_from_id
-    assert_equal 1, relation.issue_to_id
-
-    assert_match /Bug #1/, response.body
-  end
-
-  def test_create_should_accept_id_with_hash
-    assert_difference 'IssueRelation.count' do
-      post :create, :issue_id => 1,
-                 :relation => {:issue_to_id => '#2', :relation_type => 'relates', :delay => ''}
-    end
-    relation = IssueRelation.first(:order => 'id DESC')
-    assert_equal 2, relation.issue_to_id
-  end
-
-  def test_create_should_strip_id
-    assert_difference 'IssueRelation.count' do
-      post :create, :issue_id => 1,
-                 :relation => {:issue_to_id => ' 2  ', :relation_type => 'relates', :delay => ''}
-    end
-    relation = IssueRelation.first(:order => 'id DESC')
-    assert_equal 2, relation.issue_to_id
-  end
-
-  def test_create_should_not_break_with_non_numerical_id
-    assert_no_difference 'IssueRelation.count' do
-      assert_nothing_raised do
-        post :create, :issue_id => 1,
-                   :relation => {:issue_to_id => 'foo', :relation_type => 'relates', :delay => ''}
-      end
-    end
-  end
-
-  def test_create_follows_relation_should_update_relations_list
-    issue1 = Issue.generate!(:subject => 'Followed issue', :start_date => Date.yesterday, :due_date => Date.today)
-    issue2 = Issue.generate!
-
-    assert_difference 'IssueRelation.count' do
-      xhr :post, :create, :issue_id => issue2.id,
-                 :relation => {:issue_to_id => issue1.id, :relation_type => 'follows', :delay => ''}
-    end
-    assert_match /Followed issue/, response.body
-  end
-
-  def test_should_create_relations_with_visible_issues_only
-    Setting.cross_project_issue_relations = '1'
-    assert_nil Issue.visible(User.find(3)).find_by_id(4)
-
-    assert_no_difference 'IssueRelation.count' do
-      post :create, :issue_id => 1,
-                 :relation => {:issue_to_id => '4', :relation_type => 'relates', :delay => ''}
-    end
-  end
-
-  def test_create_xhr_with_failure
-    assert_no_difference 'IssueRelation.count' do
-      xhr :post, :create, :issue_id => 3, :relation => {:issue_to_id => '999', :relation_type => 'relates', :delay => ''}
-
-      assert_response :success
-      assert_template 'create'
-      assert_equal 'text/javascript', response.content_type
-    end
-
-    assert_match /errorExplanation/, response.body
-  end
-
-  def test_destroy
-    assert_difference 'IssueRelation.count', -1 do
-      delete :destroy, :id => '2'
-    end
-  end
-
-  def test_destroy_xhr
-    IssueRelation.create!(:relation_type => IssueRelation::TYPE_RELATES) do |r|
-      r.issue_from_id = 3
-      r.issue_to_id = 1
-    end
-
-    assert_difference 'IssueRelation.count', -1 do
-      xhr :delete, :destroy, :id => '2'
-
-      assert_response :success
-      assert_template 'destroy'
-      assert_equal 'text/javascript', response.content_type
-      assert_match /relation-2/, response.body
-    end
-  end
-end
--- a/.svn/pristine/42/42f2467cb688a2f7bda7722fe0d6a10336e81f57.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
-
-  class CvsAdapterTest < ActiveSupport::TestCase
-    REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s
-    REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
-    MODULE_NAME = 'test'
-
-    if File.directory?(REPOSITORY_PATH)
-      def setup
-        @adapter = Redmine::Scm::Adapters::CvsAdapter.new(MODULE_NAME, REPOSITORY_PATH)
-      end
-
-      def test_scm_version
-        to_test = { "\nConcurrent Versions System (CVS) 1.12.13 (client/server)\n"  => [1,12,13],
-                    "\r\n1.12.12\r\n1.12.11"                   => [1,12,12],
-                    "1.12.11\r\n1.12.10\r\n"                   => [1,12,11]}
-        to_test.each do |s, v|
-          test_scm_version_for(s, v)
-        end
-      end
-
-      def test_revisions_all
-        cnt = 0
-        @adapter.revisions('', nil, nil, :log_encoding => 'UTF-8') do |revision|
-          cnt += 1
-        end
-        assert_equal 16, cnt
-      end
-
-      def test_revisions_from_rev3
-        rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22)
-        cnt = 0
-        @adapter.revisions('', rev3_committed_on, nil, :log_encoding => 'UTF-8') do |revision|
-          cnt += 1
-        end
-        assert_equal 4, cnt
-      end
-
-      def test_entries_rev3
-        rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22)
-        entries = @adapter.entries('sources', rev3_committed_on)
-        assert_equal 2, entries.size
-        assert_equal entries[0].name, "watchers_controller.rb"
-        assert_equal entries[0].lastrev.time, Time.gm(2007, 12, 13, 16, 27, 22)
-      end
-
-      def test_path_encoding_default_utf8
-        adpt1 = Redmine::Scm::Adapters::CvsAdapter.new(
-                                  MODULE_NAME,
-                                  REPOSITORY_PATH
-                                )
-        assert_equal "UTF-8", adpt1.path_encoding
-        adpt2 = Redmine::Scm::Adapters::CvsAdapter.new(
-                                  MODULE_NAME,
-                                  REPOSITORY_PATH,
-                                  nil,
-                                  nil,
-                                  ""
-                                )
-        assert_equal "UTF-8", adpt2.path_encoding
-      end
-
-      def test_root_url_path
-        to_test = {
-          ':pserver:cvs_user:cvs_password@123.456.789.123:9876/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password@123.456.789.123/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password@cvs_server:/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password@cvs_server:9876/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password@cvs_server/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password@cvs_server/path/repo' => '/path/repo',
-          ':ext:cvsservername:/path' => '/path'
-        }
-
-        to_test.each do |string, expected|
-          assert_equal expected, Redmine::Scm::Adapters::CvsAdapter.new('foo', string).send(:root_url_path), "#{string} failed"
-        end
-      end
-
-      private
-
-      def test_scm_version_for(scm_command_version, version)
-        @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
-        assert_equal version, @adapter.class.scm_command_version
-      end
-    else
-      puts "Cvs test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
-    end
-  end
-
-rescue LoadError
-  class CvsMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
-  end
-end
-
--- a/.svn/pristine/43/4333e2faed9865820292b92a3a8ebf203749d50e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module WikiHelper
-
-  def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0)
-    pages = pages.group_by(&:parent) unless pages.is_a?(Hash)
-    s = ''.html_safe
-    if pages.has_key?(parent)
-      pages[parent].each do |page|
-        attrs = "value='#{page.id}'"
-        attrs << " selected='selected'" if selected == page
-        indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : ''
-
-        s << content_tag('option', (indent + h(page.pretty_title)).html_safe, :value => page.id.to_s, :selected => selected == page) +
-               wiki_page_options_for_select(pages, selected, page, level + 1)
-      end
-    end
-    s
-  end
-
-  def wiki_page_breadcrumb(page)
-    breadcrumb(page.ancestors.reverse.collect {|parent|
-      link_to(h(parent.pretty_title), {:controller => 'wiki', :action => 'show', :id => parent.title, :project_id => parent.project, :version => nil})
-    })
-  end
-end
--- a/.svn/pristine/44/4427f53bdbb62ef1eca701cca69cda8b76215c5d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module MessagesHelper
-end
--- a/.svn/pristine/44/442810adc553727c9efe816480daa7fe72b8c040.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,337 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ProjectCopyTest < ActiveSupport::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :journals, :journal_details,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :custom_fields,
-           :custom_fields_projects,
-           :custom_fields_trackers,
-           :custom_values,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :versions,
-           :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
-           :groups_users,
-           :boards, :messages,
-           :repositories,
-           :news, :comments,
-           :documents
-
-  def setup
-    ProjectCustomField.destroy_all
-    @source_project = Project.find(2)
-    @project = Project.new(:name => 'Copy Test', :identifier => 'copy-test')
-    @project.trackers = @source_project.trackers
-    @project.enabled_module_names = @source_project.enabled_modules.collect(&:name)
-  end
-
-  test "#copy should copy issues" do
-    @source_project.issues << Issue.generate!(:status => IssueStatus.find_by_name('Closed'),
-                                              :subject => "copy issue status",
-                                              :tracker_id => 1,
-                                              :assigned_to_id => 2,
-                                              :project_id => @source_project.id)
-    assert @project.valid?
-    assert @project.issues.empty?
-    assert @project.copy(@source_project)
-
-    assert_equal @source_project.issues.size, @project.issues.size
-    @project.issues.each do |issue|
-      assert issue.valid?
-      assert ! issue.assigned_to.blank?
-      assert_equal @project, issue.project
-    end
-
-    copied_issue = @project.issues.where(:subject => "copy issue status").first
-    assert copied_issue
-    assert copied_issue.status
-    assert_equal "Closed", copied_issue.status.name
-  end
-
-  test "#copy should copy issues custom values" do
-    field = IssueCustomField.generate!(:is_for_all => true, :trackers => Tracker.all)
-    issue = Issue.generate!(:project => @source_project, :subject => 'Custom field copy')
-    issue.custom_field_values = {field.id => 'custom'}
-    issue.save!
-    assert_equal 'custom', issue.reload.custom_field_value(field)
-
-    assert @project.copy(@source_project)
-    copy = @project.issues.find_by_subject('Custom field copy')
-    assert copy
-    assert_equal 'custom', copy.reload.custom_field_value(field)
-  end
-
-  test "#copy should copy issues assigned to a locked version" do
-    User.current = User.find(1)
-    assigned_version = Version.generate!(:name => "Assigned Issues")
-    @source_project.versions << assigned_version
-    Issue.generate!(:project => @source_project,
-                    :fixed_version_id => assigned_version.id,
-                    :subject => "copy issues assigned to a locked version")
-    assigned_version.update_attribute :status, 'locked'
-
-    assert @project.copy(@source_project)
-    @project.reload
-    copied_issue = @project.issues.where(:subject => "copy issues assigned to a locked version").first
-
-    assert copied_issue
-    assert copied_issue.fixed_version
-    assert_equal "Assigned Issues", copied_issue.fixed_version.name # Same name
-    assert_equal 'locked', copied_issue.fixed_version.status
-  end
-
-  test "#copy should change the new issues to use the copied version" do
-    User.current = User.find(1)
-    assigned_version = Version.generate!(:name => "Assigned Issues", :status => 'open')
-    @source_project.versions << assigned_version
-    assert_equal 3, @source_project.versions.size
-    Issue.generate!(:project => @source_project,
-                    :fixed_version_id => assigned_version.id,
-                    :subject => "change the new issues to use the copied version")
-
-    assert @project.copy(@source_project)
-    @project.reload
-    copied_issue = @project.issues.where(:subject => "change the new issues to use the copied version").first
-
-    assert copied_issue
-    assert copied_issue.fixed_version
-    assert_equal "Assigned Issues", copied_issue.fixed_version.name # Same name
-    assert_not_equal assigned_version.id, copied_issue.fixed_version.id # Different record
-  end
-
-  test "#copy should keep target shared versions from other project" do
-    assigned_version = Version.generate!(:name => "Assigned Issues", :status => 'open', :project_id => 1, :sharing => 'system')
-    issue = Issue.generate!(:project => @source_project,
-                            :fixed_version => assigned_version,
-                            :subject => "keep target shared versions")
-
-    assert @project.copy(@source_project)
-    @project.reload
-    copied_issue = @project.issues.where(:subject => "keep target shared versions").first
-
-    assert copied_issue
-    assert_equal assigned_version, copied_issue.fixed_version
-  end
-
-  test "#copy should copy issue relations" do
-    Setting.cross_project_issue_relations = '1'
-
-    second_issue = Issue.generate!(:status_id => 5,
-                                   :subject => "copy issue relation",
-                                   :tracker_id => 1,
-                                   :assigned_to_id => 2,
-                                   :project_id => @source_project.id)
-    source_relation = IssueRelation.create!(:issue_from => Issue.find(4),
-                                              :issue_to => second_issue,
-                                              :relation_type => "relates")
-    source_relation_cross_project = IssueRelation.create!(:issue_from => Issue.find(1),
-                                                            :issue_to => second_issue,
-                                                            :relation_type => "duplicates")
-
-    assert @project.copy(@source_project)
-    assert_equal @source_project.issues.count, @project.issues.count
-    copied_issue = @project.issues.find_by_subject("Issue on project 2") # Was #4
-    copied_second_issue = @project.issues.find_by_subject("copy issue relation")
-
-    # First issue with a relation on project
-    assert_equal 1, copied_issue.relations.size, "Relation not copied"
-    copied_relation = copied_issue.relations.first
-    assert_equal "relates", copied_relation.relation_type
-    assert_equal copied_second_issue.id, copied_relation.issue_to_id
-    assert_not_equal source_relation.id, copied_relation.id
-
-    # Second issue with a cross project relation
-    assert_equal 2, copied_second_issue.relations.size, "Relation not copied"
-    copied_relation = copied_second_issue.relations.select {|r| r.relation_type == 'duplicates'}.first
-    assert_equal "duplicates", copied_relation.relation_type
-    assert_equal 1, copied_relation.issue_from_id, "Cross project relation not kept"
-    assert_not_equal source_relation_cross_project.id, copied_relation.id
-  end
-
-  test "#copy should copy issue attachments" do
-    issue = Issue.generate!(:subject => "copy with attachment", :tracker_id => 1, :project_id => @source_project.id)
-    Attachment.create!(:container => issue, :file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 1)
-    @source_project.issues << issue
-    assert @project.copy(@source_project)
-
-    copied_issue = @project.issues.where(:subject => "copy with attachment").first
-    assert_not_nil copied_issue
-    assert_equal 1, copied_issue.attachments.count, "Attachment not copied"
-    assert_equal "testfile.txt", copied_issue.attachments.first.filename
-  end
-
-  test "#copy should copy memberships" do
-    assert @project.valid?
-    assert @project.members.empty?
-    assert @project.copy(@source_project)
-
-    assert_equal @source_project.memberships.size, @project.memberships.size
-    @project.memberships.each do |membership|
-      assert membership
-      assert_equal @project, membership.project
-    end
-  end
-
-  test "#copy should copy memberships with groups and additional roles" do
-    group = Group.create!(:lastname => "Copy group")
-    user = User.find(7)
-    group.users << user
-    # group role
-    Member.create!(:project_id => @source_project.id, :principal => group, :role_ids => [2])
-    member = Member.find_by_user_id_and_project_id(user.id, @source_project.id)
-    # additional role
-    member.role_ids = [1]
-
-    assert @project.copy(@source_project)
-    member = Member.find_by_user_id_and_project_id(user.id, @project.id)
-    assert_not_nil member
-    assert_equal [1, 2], member.role_ids.sort
-  end
-
-  test "#copy should copy project specific queries" do
-    assert @project.valid?
-    assert @project.queries.empty?
-    assert @project.copy(@source_project)
-
-    assert_equal @source_project.queries.size, @project.queries.size
-    @project.queries.each do |query|
-      assert query
-      assert_equal @project, query.project
-    end
-    assert_equal @source_project.queries.map(&:user_id).sort, @project.queries.map(&:user_id).sort
-  end
-
-  test "#copy should copy versions" do
-    @source_project.versions << Version.generate!
-    @source_project.versions << Version.generate!
-
-    assert @project.versions.empty?
-    assert @project.copy(@source_project)
-
-    assert_equal @source_project.versions.size, @project.versions.size
-    @project.versions.each do |version|
-      assert version
-      assert_equal @project, version.project
-    end
-  end
-
-  test "#copy should copy wiki" do
-    assert_difference 'Wiki.count' do
-      assert @project.copy(@source_project)
-    end
-
-    assert @project.wiki
-    assert_not_equal @source_project.wiki, @project.wiki
-    assert_equal "Start page", @project.wiki.start_page
-  end
-
-  test "#copy should copy wiki without wiki module" do
-    project = Project.new(:name => 'Copy Test', :identifier => 'copy-test', :enabled_module_names => [])
-    assert_difference 'Wiki.count' do
-      assert project.copy(@source_project)
-    end
-
-    assert project.wiki
-  end
-
-  test "#copy should copy wiki pages and content with hierarchy" do
-    assert_difference 'WikiPage.count', @source_project.wiki.pages.size do
-      assert @project.copy(@source_project)
-    end
-
-    assert @project.wiki
-    assert_equal @source_project.wiki.pages.size, @project.wiki.pages.size
-
-    @project.wiki.pages.each do |wiki_page|
-      assert wiki_page.content
-      assert !@source_project.wiki.pages.include?(wiki_page)
-    end
-
-    parent = @project.wiki.find_page('Parent_page')
-    child1 = @project.wiki.find_page('Child_page_1')
-    child2 = @project.wiki.find_page('Child_page_2')
-    assert_equal parent, child1.parent
-    assert_equal parent, child2.parent
-  end
-
-  test "#copy should copy issue categories" do
-    assert @project.copy(@source_project)
-
-    assert_equal 2, @project.issue_categories.size
-    @project.issue_categories.each do |issue_category|
-      assert !@source_project.issue_categories.include?(issue_category)
-    end
-  end
-
-  test "#copy should copy boards" do
-    assert @project.copy(@source_project)
-
-    assert_equal 1, @project.boards.size
-    @project.boards.each do |board|
-      assert !@source_project.boards.include?(board)
-    end
-  end
-
-  test "#copy should change the new issues to use the copied issue categories" do
-    issue = Issue.find(4)
-    issue.update_attribute(:category_id, 3)
-
-    assert @project.copy(@source_project)
-
-    @project.issues.each do |issue|
-      assert issue.category
-      assert_equal "Stock management", issue.category.name # Same name
-      assert_not_equal IssueCategory.find(3), issue.category # Different record
-    end
-  end
-
-  test "#copy should limit copy with :only option" do
-    assert @project.members.empty?
-    assert @project.issue_categories.empty?
-    assert @source_project.issues.any?
-
-    assert @project.copy(@source_project, :only => ['members', 'issue_categories'])
-
-    assert @project.members.any?
-    assert @project.issue_categories.any?
-    assert @project.issues.empty?
-  end
-
-  test "#copy should copy subtasks" do
-    source = Project.generate!(:tracker_ids => [1])
-    issue = Issue.generate_with_descendants!(:project => source)
-    project = Project.new(:name => 'Copy', :identifier => 'copy', :tracker_ids => [1])
-
-    assert_difference 'Project.count' do
-      assert_difference 'Issue.count', 1+issue.descendants.count do
-        assert project.copy(source.reload)
-      end
-    end
-    copy = Issue.where(:parent_id => nil).order("id DESC").first
-    assert_equal project, copy.project
-    assert_equal issue.descendants.count, copy.descendants.count
-    child_copy = copy.children.detect {|c| c.subject == 'Child1'}
-    assert child_copy.descendants.any?
-  end
-end
--- a/.svn/pristine/45/4537efe545b75bf585f6f1b2f82d7cbf9d1195c2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Hook
-    @@listener_classes = []
-    @@listeners = nil
-    @@hook_listeners = {}
-
-    class << self
-      # Adds a listener class.
-      # Automatically called when a class inherits from Redmine::Hook::Listener.
-      def add_listener(klass)
-        raise "Hooks must include Singleton module." unless klass.included_modules.include?(Singleton)
-        @@listener_classes << klass
-        clear_listeners_instances
-      end
-
-      # Returns all the listerners instances.
-      def listeners
-        @@listeners ||= @@listener_classes.collect {|listener| listener.instance}
-      end
-
-      # Returns the listeners instances for the given hook.
-      def hook_listeners(hook)
-        @@hook_listeners[hook] ||= listeners.select {|listener| listener.respond_to?(hook)}
-      end
-
-      # Clears all the listeners.
-      def clear_listeners
-        @@listener_classes = []
-        clear_listeners_instances
-      end
-
-      # Clears all the listeners instances.
-      def clear_listeners_instances
-        @@listeners = nil
-        @@hook_listeners = {}
-      end
-
-      # Calls a hook.
-      # Returns the listeners response.
-      def call_hook(hook, context={})
-        [].tap do |response|
-          hls = hook_listeners(hook)
-          if hls.any?
-            hls.each {|listener| response << listener.send(hook, context)}
-          end
-        end
-      end
-    end
-
-    # Base class for hook listeners.
-    class Listener
-      include Singleton
-      include Redmine::I18n
-
-      # Registers the listener
-      def self.inherited(child)
-        Redmine::Hook.add_listener(child)
-        super
-      end
-
-    end
-
-    # Listener class used for views hooks.
-    # Listeners that inherit this class will include various helpers by default.
-    class ViewListener < Listener
-      include ERB::Util
-      include ActionView::Helpers::TagHelper
-      include ActionView::Helpers::FormHelper
-      include ActionView::Helpers::FormTagHelper
-      include ActionView::Helpers::FormOptionsHelper
-      include ActionView::Helpers::JavaScriptHelper
-      include ActionView::Helpers::NumberHelper
-      include ActionView::Helpers::UrlHelper
-      include ActionView::Helpers::AssetTagHelper
-      include ActionView::Helpers::TextHelper
-      include Rails.application.routes.url_helpers
-      include ApplicationHelper
-
-      # Default to creating links using only the path.  Subclasses can
-      # change this default as needed
-      def self.default_url_options
-        {:only_path => true }
-      end
-
-      # Helper method to directly render a partial using the context:
-      #
-      #   class MyHook < Redmine::Hook::ViewListener
-      #     render_on :view_issues_show_details_bottom, :partial => "show_more_data"
-      #   end
-      #
-      def self.render_on(hook, options={})
-        define_method hook do |context|
-          if context[:hook_caller].respond_to?(:render)
-            context[:hook_caller].send(:render, {:locals => context}.merge(options))
-          elsif context[:controller].is_a?(ActionController::Base)
-            context[:controller].send(:render_to_string, {:locals => context}.merge(options))
-          else
-            raise "Cannot render #{self.name} hook from #{context[:hook_caller].class.name}"
-          end
-        end
-      end
-      
-      def controller
-        nil
-      end
-      
-      def config
-        ActionController::Base.config
-      end
-    end
-
-    # Helper module included in ApplicationHelper and ActionController so that
-    # hooks can be called in views like this:
-    #
-    #   <%= call_hook(:some_hook) %>
-    #   <%= call_hook(:another_hook, :foo => 'bar') %>
-    #
-    # Or in controllers like:
-    #   call_hook(:some_hook)
-    #   call_hook(:another_hook, :foo => 'bar')
-    #
-    # Hooks added to views will be concatenated into a string. Hooks added to
-    # controllers will return an array of results.
-    #
-    # Several objects are automatically added to the call context:
-    #
-    # * project => current project
-    # * request => Request instance
-    # * controller => current Controller instance
-    # * hook_caller => object that called the hook
-    #
-    module Helper
-      def call_hook(hook, context={})
-        if is_a?(ActionController::Base)
-          default_context = {:controller => self, :project => @project, :request => request, :hook_caller => self}
-          Redmine::Hook.call_hook(hook, default_context.merge(context))
-        else
-          default_context = { :project => @project, :hook_caller => self }
-          default_context[:controller] = controller if respond_to?(:controller)
-          default_context[:request] = request if respond_to?(:request)
-          Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ').html_safe
-        end
-      end
-    end
-  end
-end
-
-ApplicationHelper.send(:include, Redmine::Hook::Helper)
-ActionController::Base.send(:include, Redmine::Hook::Helper)
--- a/.svn/pristine/45/45b8269cf1731acb2f145d6ea43cdd52da6f4d4a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class TrackersController < ApplicationController
-  layout 'admin'
-
-  before_filter :require_admin, :except => :index
-  before_filter :require_admin_or_api_request, :only => :index
-  accept_api_auth :index
-
-  def index
-    respond_to do |format|
-      format.html {
-        @tracker_pages, @trackers = paginate Tracker.sorted, :per_page => 25
-        render :action => "index", :layout => false if request.xhr?
-      }
-      format.api {
-        @trackers = Tracker.sorted.all
-      }
-    end
-  end
-
-  def new
-    @tracker ||= Tracker.new(params[:tracker])
-    @trackers = Tracker.sorted.all
-    @projects = Project.all
-  end
-
-  def create
-    @tracker = Tracker.new(params[:tracker])
-    if @tracker.save
-      # workflow copy
-      if !params[:copy_workflow_from].blank? && (copy_from = Tracker.find_by_id(params[:copy_workflow_from]))
-        @tracker.workflow_rules.copy(copy_from)
-      end
-      flash[:notice] = l(:notice_successful_create)
-      redirect_to trackers_path
-      return
-    end
-    new
-    render :action => 'new'
-  end
-
-  def edit
-    @tracker ||= Tracker.find(params[:id])
-    @projects = Project.all
-  end
-
-  def update
-    @tracker = Tracker.find(params[:id])
-    if @tracker.update_attributes(params[:tracker])
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to trackers_path
-      return
-    end
-    edit
-    render :action => 'edit'
-  end
-
-  def destroy
-    @tracker = Tracker.find(params[:id])
-    unless @tracker.issues.empty?
-      flash[:error] = l(:error_can_not_delete_tracker)
-    else
-      @tracker.destroy
-    end
-    redirect_to trackers_path
-  end
-
-  def fields
-    if request.post? && params[:trackers]
-      params[:trackers].each do |tracker_id, tracker_params|
-        tracker = Tracker.find_by_id(tracker_id)
-        if tracker
-          tracker.core_fields = tracker_params[:core_fields]
-          tracker.custom_field_ids = tracker_params[:custom_field_ids]
-          tracker.save
-        end
-      end
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to fields_trackers_path
-      return
-    end
-    @trackers = Tracker.sorted.all
-    @custom_fields = IssueCustomField.all.sort
-  end
-end
--- a/.svn/pristine/45/45d6a4c7517a59a47326ffe4aae5abf9f33149fd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class MessagesController < ApplicationController
-  menu_item :boards
-  default_search_scope :messages
-  before_filter :find_board, :only => [:new, :preview]
-  before_filter :find_attachments, :only => [:preview]
-  before_filter :find_message, :except => [:new, :preview]
-  before_filter :authorize, :except => [:preview, :edit, :destroy]
-
-  helper :boards
-  helper :watchers
-  helper :attachments
-  include AttachmentsHelper
-
-  REPLIES_PER_PAGE = 25 unless const_defined?(:REPLIES_PER_PAGE)
-
-  # Show a topic and its replies
-  def show
-    page = params[:page]
-    # Find the page of the requested reply
-    if params[:r] && page.nil?
-      offset = @topic.children.where("#{Message.table_name}.id < ?", params[:r].to_i).count
-      page = 1 + offset / REPLIES_PER_PAGE
-    end
-
-    @reply_count = @topic.children.count
-    @reply_pages = Paginator.new @reply_count, REPLIES_PER_PAGE, page
-    @replies =  @topic.children.
-      includes(:author, :attachments, {:board => :project}).
-      reorder("#{Message.table_name}.created_on ASC").
-      limit(@reply_pages.per_page).
-      offset(@reply_pages.offset).
-      all
-
-    @reply = Message.new(:subject => "RE: #{@message.subject}")
-    render :action => "show", :layout => false if request.xhr?
-  end
-
-  # Create a new topic
-  def new
-    @message = Message.new
-    @message.author = User.current
-    @message.board = @board
-    @message.safe_attributes = params[:message]
-    if request.post?
-      @message.save_attachments(params[:attachments])
-      if @message.save
-        call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
-        render_attachment_warning_if_needed(@message)
-        redirect_to board_message_path(@board, @message)
-      end
-    end
-  end
-
-  # Reply to a topic
-  def reply
-    @reply = Message.new
-    @reply.author = User.current
-    @reply.board = @board
-    @reply.safe_attributes = params[:reply]
-    @topic.children << @reply
-    if !@reply.new_record?
-      call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply})
-      attachments = Attachment.attach_files(@reply, params[:attachments])
-      render_attachment_warning_if_needed(@reply)
-    end
-    redirect_to board_message_path(@board, @topic, :r => @reply)
-  end
-
-  # Edit a message
-  def edit
-    (render_403; return false) unless @message.editable_by?(User.current)
-    @message.safe_attributes = params[:message]
-    if request.post? && @message.save
-      attachments = Attachment.attach_files(@message, params[:attachments])
-      render_attachment_warning_if_needed(@message)
-      flash[:notice] = l(:notice_successful_update)
-      @message.reload
-      redirect_to board_message_path(@message.board, @message.root, :r => (@message.parent_id && @message.id))
-    end
-  end
-
-  # Delete a messages
-  def destroy
-    (render_403; return false) unless @message.destroyable_by?(User.current)
-    r = @message.to_param
-    @message.destroy
-    if @message.parent
-      redirect_to board_message_path(@board, @message.parent, :r => r)
-    else
-      redirect_to project_board_path(@project, @board)
-    end
-  end
-
-  def quote
-    @subject = @message.subject
-    @subject = "RE: #{@subject}" unless @subject.starts_with?('RE:')
-
-    @content = "#{ll(Setting.default_language, :text_user_wrote, @message.author)}\n> "
-    @content << @message.content.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
-  end
-
-  def preview
-    message = @board.messages.find_by_id(params[:id])
-    @text = (params[:message] || params[:reply])[:content]
-    @previewed = message
-    render :partial => 'common/preview'
-  end
-
-private
-  def find_message
-    return unless find_board
-    @message = @board.messages.find(params[:id], :include => :parent)
-    @topic = @message.root
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def find_board
-    @board = Board.find(params[:board_id], :include => :project)
-    @project = @board.project
-  rescue ActiveRecord::RecordNotFound
-    render_404
-    nil
-  end
-end
--- a/.svn/pristine/45/45fedacb83fa4bf0b530842cc4c9e44d1242cd73.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module AttachmentsHelper
-  # Displays view/delete links to the attachments of the given object
-  # Options:
-  #   :author -- author names are not displayed if set to false
-  #   :thumbails -- display thumbnails if enabled in settings
-  def link_to_attachments(container, options = {})
-    options.assert_valid_keys(:author, :thumbnails)
-
-    if container.attachments.any?
-      options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
-      render :partial => 'attachments/links',
-        :locals => {:attachments => container.attachments, :options => options, :thumbnails => (options[:thumbnails] && Setting.thumbnails_enabled?)}
-    end
-  end
-
-  def render_api_attachment(attachment, api)
-    api.attachment do
-      api.id attachment.id
-      api.filename attachment.filename
-      api.filesize attachment.filesize
-      api.content_type attachment.content_type
-      api.description attachment.description
-      api.content_url url_for(:controller => 'attachments', :action => 'download', :id => attachment, :filename => attachment.filename, :only_path => false)
-      api.author(:id => attachment.author.id, :name => attachment.author.name) if attachment.author
-      api.created_on attachment.created_on
-    end
-  end
-end
--- a/.svn/pristine/46/460823ad942a6dbaf3986f763002fe9ab659fb36.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class WorkflowPermission < WorkflowRule
-  validates_inclusion_of :rule, :in => %w(readonly required)
-  validate :validate_field_name
-
-  # Replaces the workflow permissions for the given tracker and role
-  #
-  # Example:
-  #   WorkflowPermission.replace_permissions role, tracker, {'due_date' => {'1' => 'readonly', '2' => 'required'}}
-  def self.replace_permissions(tracker, role, permissions)
-    destroy_all(:tracker_id => tracker.id, :role_id => role.id)
-
-    permissions.each { |field, rule_by_status_id|
-      rule_by_status_id.each { |status_id, rule|
-        if rule.present?
-          WorkflowPermission.create(:role_id => role.id, :tracker_id => tracker.id, :old_status_id => status_id, :field_name => field, :rule => rule)
-        end
-      }
-    }
-  end
-
-  protected
-
-  def validate_field_name
-    unless Tracker::CORE_FIELDS_ALL.include?(field_name) || field_name.to_s.match(/^\d+$/)
-      errors.add :field_name, :invalid
-    end
-  end
-end
--- a/.svn/pristine/46/46c80cd596249868cd44c8d7343c86bdddc1eb3f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssueCustomField < CustomField
-  has_and_belongs_to_many :projects, :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :foreign_key => "custom_field_id"
-  has_and_belongs_to_many :trackers, :join_table => "#{table_name_prefix}custom_fields_trackers#{table_name_suffix}", :foreign_key => "custom_field_id"
-  has_many :issues, :through => :issue_custom_values
-
-  def type_name
-    :label_issue_plural
-  end
-
-  def visible_by?(project, user=User.current)
-    super || (roles & user.roles_for_project(project)).present?
-  end
-
-  def visibility_by_project_condition(*args)
-    sql = super
-    additional_sql = "#{Issue.table_name}.tracker_id IN (SELECT tracker_id FROM #{table_name_prefix}custom_fields_trackers#{table_name_suffix} WHERE custom_field_id = #{id})"
-    unless is_for_all?
-      additional_sql << " AND #{Issue.table_name}.project_id IN (SELECT project_id FROM #{table_name_prefix}custom_fields_projects#{table_name_suffix} WHERE custom_field_id = #{id})"
-    end
-    "((#{sql}) AND (#{additional_sql}))"
-  end
-
-  def validate_custom_field
-    super
-    errors.add(:base, l(:label_role_plural) + ' ' + l('activerecord.errors.messages.blank')) unless visible? || roles.present?
-  end
-end
--- a/.svn/pristine/47/4753e6da278a7ff7f4570acb7cd3a1cfc5512fc7.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module ProjectsHelper
-  def link_to_version(version, options = {})
-    return '' unless version && version.is_a?(Version)
-    link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, options
-  end
-
-  def project_settings_tabs
-    tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural},
-            {:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
-            {:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural},
-            {:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural},
-            {:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural},
-            {:name => 'wiki', :action => :manage_wiki, :partial => 'projects/settings/wiki', :label => :label_wiki},
-            {:name => 'repositories', :action => :manage_repository, :partial => 'projects/settings/repositories', :label => :label_repository_plural},
-            {:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural},
-            {:name => 'activities', :action => :manage_project_activities, :partial => 'projects/settings/activities', :label => :enumeration_activities}
-            ]
-    tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)}
-  end
-
-  def parent_project_select_tag(project)
-    selected = project.parent
-    # retrieve the requested parent project
-    parent_id = (params[:project] && params[:project][:parent_id]) || params[:parent_id]
-    if parent_id
-      selected = (parent_id.blank? ? nil : Project.find(parent_id))
-    end
-
-    options = ''
-    options << "<option value=''>&nbsp;</option>" if project.allowed_parents.include?(nil)
-    options << project_tree_options_for_select(project.allowed_parents.compact, :selected => selected)
-    content_tag('select', options.html_safe, :name => 'project[parent_id]', :id => 'project_parent_id')
-  end
-
-  # Renders the projects index
-  def render_project_hierarchy(projects)
-    render_project_nested_lists(projects) do |project|
-      s = link_to_project(project, {}, :class => "#{project.css_classes} #{User.current.member_of?(project) ? 'my-project' : nil}")
-      if project.description.present?
-        s << content_tag('div', textilizable(project.short_description, :project => project), :class => 'wiki description')
-      end
-      s
-    end
-  end
-
-  # Returns a set of options for a select field, grouped by project.
-  def version_options_for_select(versions, selected=nil)
-    grouped = Hash.new {|h,k| h[k] = []}
-    versions.each do |version|
-      grouped[version.project.name] << [version.name, version.id]
-    end
-
-    selected = selected.is_a?(Version) ? selected.id : selected
-    if grouped.keys.size > 1
-      grouped_options_for_select(grouped, selected)
-    else
-      options_for_select((grouped.values.first || []), selected)
-    end
-  end
-
-  def format_version_sharing(sharing)
-    sharing = 'none' unless Version::VERSION_SHARINGS.include?(sharing)
-    l("label_version_sharing_#{sharing}")
-  end
-end
--- a/.svn/pristine/47/476f7092547a421c5cdba23a45c9f5c323dff122.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::PluginTest < ActiveSupport::TestCase
-  def setup
-    @klass = Redmine::Plugin
-    # In case some real plugins are installed
-    @klass.clear
-  end
-
-  def teardown
-    @klass.clear
-  end
-
-  def test_register
-    @klass.register :foo do
-      name 'Foo plugin'
-      url 'http://example.net/plugins/foo'
-      author 'John Smith'
-      author_url 'http://example.net/jsmith'
-      description 'This is a test plugin'
-      version '0.0.1'
-      settings :default => {'sample_setting' => 'value', 'foo'=>'bar'}, :partial => 'foo/settings'
-    end
-
-    assert_equal 1, @klass.all.size
-
-    plugin = @klass.find('foo')
-    assert plugin.is_a?(Redmine::Plugin)
-    assert_equal :foo, plugin.id
-    assert_equal 'Foo plugin', plugin.name
-    assert_equal 'http://example.net/plugins/foo', plugin.url
-    assert_equal 'John Smith', plugin.author
-    assert_equal 'http://example.net/jsmith', plugin.author_url
-    assert_equal 'This is a test plugin', plugin.description
-    assert_equal '0.0.1', plugin.version
-  end
-
-  def test_installed
-    @klass.register(:foo) {}
-    assert_equal true, @klass.installed?(:foo)
-    assert_equal false, @klass.installed?(:bar)
-  end
-
-  def test_menu
-    assert_difference 'Redmine::MenuManager.items(:project_menu).size' do
-      @klass.register :foo do
-        menu :project_menu, :foo_menu_item, '/foo', :caption => 'Foo'
-      end
-    end
-    menu_item = Redmine::MenuManager.items(:project_menu).detect {|i| i.name == :foo_menu_item}
-    assert_not_nil menu_item
-    assert_equal 'Foo', menu_item.caption
-    assert_equal '/foo', menu_item.url
-  end
-
-  def test_delete_menu_item
-    Redmine::MenuManager.map(:project_menu).push(:foo_menu_item, '/foo', :caption => 'Foo')
-    assert_difference 'Redmine::MenuManager.items(:project_menu).size', -1 do
-      @klass.register :foo do
-        delete_menu_item :project_menu, :foo_menu_item
-      end
-    end
-    assert_nil Redmine::MenuManager.items(:project_menu).detect {|i| i.name == :foo_menu_item}
-  end
-
-  def test_directory_with_override
-    @klass.register(:foo) do
-      directory '/path/to/foo'
-    end
-    assert_equal '/path/to/foo', @klass.find('foo').directory
-  end
-
-  def test_directory_without_override
-    @klass.register(:foo) {}
-    assert_equal File.join(@klass.directory, 'foo'), @klass.find('foo').directory
-  end
-
-  def test_requires_redmine
-    plugin = Redmine::Plugin.register(:foo) {}
-    Redmine::VERSION.stubs(:to_a).returns([2, 1, 3, "stable", 10817])
-    # Specific version without hash
-    assert plugin.requires_redmine('2.1.3')
-    assert plugin.requires_redmine('2.1')
-    assert_raise Redmine::PluginRequirementError do
-      plugin.requires_redmine('2.1.4')
-    end
-    assert_raise Redmine::PluginRequirementError do
-      plugin.requires_redmine('2.2')
-    end
-    # Specific version
-    assert plugin.requires_redmine(:version => '2.1.3')
-    assert plugin.requires_redmine(:version => ['2.1.3', '2.2.0'])
-    assert plugin.requires_redmine(:version => '2.1')
-    assert_raise Redmine::PluginRequirementError do
-      plugin.requires_redmine(:version => '2.2.0')
-    end
-    assert_raise Redmine::PluginRequirementError do
-      plugin.requires_redmine(:version => ['2.1.4', '2.2.0'])
-    end
-    assert_raise Redmine::PluginRequirementError do
-      plugin.requires_redmine(:version => '2.2')
-    end
-    # Version range
-    assert plugin.requires_redmine(:version => '2.0.0'..'2.2.4')
-    assert plugin.requires_redmine(:version => '2.1.3'..'2.2.4')
-    assert plugin.requires_redmine(:version => '2.0.0'..'2.1.3')
-    assert plugin.requires_redmine(:version => '2.0'..'2.2')
-    assert plugin.requires_redmine(:version => '2.1'..'2.2')
-    assert plugin.requires_redmine(:version => '2.0'..'2.1')
-    assert_raise Redmine::PluginRequirementError do
-      plugin.requires_redmine(:version => '2.1.4'..'2.2.4')
-    end
-    # Version or higher
-    assert plugin.requires_redmine(:version_or_higher => '0.1.0')
-    assert plugin.requires_redmine(:version_or_higher => '2.1.3')
-    assert plugin.requires_redmine(:version_or_higher => '2.1')
-    assert_raise Redmine::PluginRequirementError do
-      plugin.requires_redmine(:version_or_higher => '2.2.0')
-    end
-    assert_raise Redmine::PluginRequirementError do
-      plugin.requires_redmine(:version_or_higher => '2.2')
-    end
-  end
-
-  def test_requires_redmine_plugin
-    test = self
-    other_version = '0.5.0'
-    @klass.register :other do
-      name 'Other'
-      version other_version
-    end
-    @klass.register :foo do
-      test.assert requires_redmine_plugin(:other, :version_or_higher => '0.1.0')
-      test.assert requires_redmine_plugin(:other, :version_or_higher => other_version)
-      test.assert requires_redmine_plugin(:other, other_version)
-      test.assert_raise Redmine::PluginRequirementError do
-        requires_redmine_plugin(:other, :version_or_higher => '99.0.0')
-      end
-      test.assert requires_redmine_plugin(:other, :version => other_version)
-      test.assert requires_redmine_plugin(:other, :version => [other_version, '99.0.0'])
-      test.assert_raise Redmine::PluginRequirementError do
-        requires_redmine_plugin(:other, :version => '99.0.0')
-      end
-      test.assert_raise Redmine::PluginRequirementError do
-        requires_redmine_plugin(:other, :version => ['98.0.0', '99.0.0'])
-      end
-      # Missing plugin
-      test.assert_raise Redmine::PluginNotFound do
-        requires_redmine_plugin(:missing, :version_or_higher => '0.1.0')
-      end
-      test.assert_raise Redmine::PluginNotFound do
-        requires_redmine_plugin(:missing, '0.1.0')
-      end
-      test.assert_raise Redmine::PluginNotFound do
-        requires_redmine_plugin(:missing, :version => '0.1.0')
-      end
-    end
-  end
-end
--- a/.svn/pristine/47/47a7b4898fe505591d4572ccd817f96b3fd4d27d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,356 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-RedmineApp::Application.routes.draw do
-  root :to => 'welcome#index', :as => 'home'
-
-  match 'login', :to => 'account#login', :as => 'signin', :via => [:get, :post]
-  match 'logout', :to => 'account#logout', :as => 'signout', :via => [:get, :post]
-  match 'account/register', :to => 'account#register', :via => [:get, :post], :as => 'register'
-  match 'account/lost_password', :to => 'account#lost_password', :via => [:get, :post], :as => 'lost_password'
-  match 'account/activate', :to => 'account#activate', :via => :get
-  get 'account/activation_email', :to => 'account#activation_email', :as => 'activation_email'
-
-  match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put]
-  match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put]
-  match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put]
-  match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put]
-
-  match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post
-  match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post]
-
-  match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post], :as => 'new_board_message'
-  get 'boards/:board_id/topics/:id', :to => 'messages#show', :as => 'board_message'
-  match 'boards/:board_id/topics/quote/:id', :to => 'messages#quote', :via => [:get, :post]
-  get 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
-
-  post 'boards/:board_id/topics/preview', :to => 'messages#preview', :as => 'preview_board_message'
-  post 'boards/:board_id/topics/:id/replies', :to => 'messages#reply'
-  post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
-  post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy'
-
-  # Misc issue routes. TODO: move into resources
-  match '/issues/auto_complete', :to => 'auto_completes#issues', :via => :get, :as => 'auto_complete_issues'
-  match '/issues/context_menu', :to => 'context_menus#issues', :as => 'issues_context_menu', :via => [:get, :post]
-  match '/issues/changes', :to => 'journals#index', :as => 'issue_changes', :via => :get
-  match '/issues/:id/quoted', :to => 'journals#new', :id => /\d+/, :via => :post, :as => 'quoted_issue'
-
-  match '/journals/diff/:id', :to => 'journals#diff', :id => /\d+/, :via => :get
-  match '/journals/edit/:id', :to => 'journals#edit', :id => /\d+/, :via => [:get, :post]
-
-  get '/projects/:project_id/issues/gantt', :to => 'gantts#show', :as => 'project_gantt'
-  get '/issues/gantt', :to => 'gantts#show'
-
-  get '/projects/:project_id/issues/calendar', :to => 'calendars#show', :as => 'project_calendar'
-  get '/issues/calendar', :to => 'calendars#show'
-
-  get 'projects/:id/issues/report', :to => 'reports#issue_report', :as => 'project_issues_report'
-  get 'projects/:id/issues/report/:detail', :to => 'reports#issue_report_details', :as => 'project_issues_report_details'
-
-  match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
-  match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
-  match 'my/page', :controller => 'my', :action => 'page', :via => :get
-  match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
-  match 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key', :via => :post
-  match 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key', :via => :post
-  match 'my/password', :controller => 'my', :action => 'password', :via => [:get, :post]
-  match 'my/page_layout', :controller => 'my', :action => 'page_layout', :via => :get
-  match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post
-  match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post
-  match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
-
-  resources :users
-  match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership'
-  match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete
-  match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships'
-
-  post 'watchers/watch', :to => 'watchers#watch', :as => 'watch'
-  delete 'watchers/watch', :to => 'watchers#unwatch'
-  get 'watchers/new', :to => 'watchers#new'
-  post 'watchers', :to => 'watchers#create'
-  post 'watchers/append', :to => 'watchers#append'
-  delete 'watchers', :to => 'watchers#destroy'
-  get 'watchers/autocomplete_for_user', :to => 'watchers#autocomplete_for_user'
-  # Specific routes for issue watchers API
-  post 'issues/:object_id/watchers', :to => 'watchers#create', :object_type => 'issue'
-  delete 'issues/:object_id/watchers/:user_id' => 'watchers#destroy', :object_type => 'issue'
-
-  resources :projects do
-    member do
-      get 'settings(/:tab)', :action => 'settings', :as => 'settings'
-      post 'modules'
-      post 'archive'
-      post 'unarchive'
-      post 'close'
-      post 'reopen'
-      match 'copy', :via => [:get, :post]
-    end
-
-    shallow do
-      resources :memberships, :controller => 'members', :only => [:index, :show, :new, :create, :update, :destroy] do
-        collection do
-          get 'autocomplete'
-        end
-      end
-    end
-
-    resource :enumerations, :controller => 'project_enumerations', :only => [:update, :destroy]
-
-    get 'issues/:copy_from/copy', :to => 'issues#new', :as => 'copy_issue'
-    resources :issues, :only => [:index, :new, :create] do
-      resources :time_entries, :controller => 'timelog' do
-        collection do
-          get 'report'
-        end
-      end
-    end
-    # issue form update
-    match 'issues/update_form', :controller => 'issues', :action => 'update_form', :via => [:put, :post], :as => 'issue_form'
-
-    resources :files, :only => [:index, :new, :create]
-
-    resources :versions, :except => [:index, :show, :edit, :update, :destroy] do
-      collection do
-        put 'close_completed'
-      end
-    end
-    get 'versions.:format', :to => 'versions#index'
-    get 'roadmap', :to => 'versions#index', :format => false
-    get 'versions', :to => 'versions#index'
-
-    resources :news, :except => [:show, :edit, :update, :destroy]
-    resources :time_entries, :controller => 'timelog' do
-      get 'report', :on => :collection
-    end
-    resources :queries, :only => [:new, :create]
-    shallow do
-      resources :issue_categories
-    end
-    resources :documents, :except => [:show, :edit, :update, :destroy]
-    resources :boards
-    shallow do
-      resources :repositories, :except => [:index, :show] do
-        member do
-          match 'committers', :via => [:get, :post]
-        end
-      end
-    end
-  
-    match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
-    resources :wiki, :except => [:index, :new, :create], :as => 'wiki_page' do
-      member do
-        get 'rename'
-        post 'rename'
-        get 'history'
-        get 'diff'
-        match 'preview', :via => [:post, :put]
-        post 'protect'
-        post 'add_attachment'
-      end
-      collection do
-        get 'export'
-        get 'date_index'
-      end
-    end
-    match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
-    get 'wiki/:id/:version', :to => 'wiki#show', :constraints => {:version => /\d+/}
-    delete 'wiki/:id/:version', :to => 'wiki#destroy_version'
-    get 'wiki/:id/:version/annotate', :to => 'wiki#annotate'
-    get 'wiki/:id/:version/diff', :to => 'wiki#diff'
-  end
-
-  resources :issues do
-    collection do
-      match 'bulk_edit', :via => [:get, :post]
-      post 'bulk_update'
-    end
-    resources :time_entries, :controller => 'timelog' do
-      collection do
-        get 'report'
-      end
-    end
-    shallow do
-      resources :relations, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
-    end
-  end
-  match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete
-
-  resources :queries, :except => [:show]
-
-  resources :news, :only => [:index, :show, :edit, :update, :destroy]
-  match '/news/:id/comments', :to => 'comments#create', :via => :post
-  match '/news/:id/comments/:comment_id', :to => 'comments#destroy', :via => :delete
-
-  resources :versions, :only => [:show, :edit, :update, :destroy] do
-    post 'status_by', :on => :member
-  end
-
-  resources :documents, :only => [:show, :edit, :update, :destroy] do
-    post 'add_attachment', :on => :member
-  end
-
-  match '/time_entries/context_menu', :to => 'context_menus#time_entries', :as => :time_entries_context_menu, :via => [:get, :post]
-
-  resources :time_entries, :controller => 'timelog', :except => :destroy do
-    collection do
-      get 'report'
-      get 'bulk_edit'
-      post 'bulk_update'
-    end
-  end
-  match '/time_entries/:id', :to => 'timelog#destroy', :via => :delete, :id => /\d+/
-  # TODO: delete /time_entries for bulk deletion
-  match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete
-
-  get 'projects/:id/activity', :to => 'activities#index'
-  get 'projects/:id/activity.:format', :to => 'activities#index'
-  get 'activity', :to => 'activities#index'
-
-  # repositories routes
-  get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats'
-  get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph'
-
-  get 'projects/:id/repository/:repository_id/changes(/*path(.:ext))',
-      :to => 'repositories#changes'
-
-  get 'projects/:id/repository/:repository_id/revisions/:rev', :to => 'repositories#revision'
-  get 'projects/:id/repository/:repository_id/revision', :to => 'repositories#revision'
-  post   'projects/:id/repository/:repository_id/revisions/:rev/issues', :to => 'repositories#add_related_issue'
-  delete 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
-  get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions'
-  get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))',
-      :controller => 'repositories',
-      :format => false,
-      :constraints => {
-            :action => /(browse|show|entry|raw|annotate|diff)/,
-            :rev    => /[a-z0-9\.\-_]+/
-          }
-
-  get 'projects/:id/repository/statistics', :to => 'repositories#stats'
-  get 'projects/:id/repository/graph', :to => 'repositories#graph'
-
-  get 'projects/:id/repository/changes(/*path(.:ext))',
-      :to => 'repositories#changes'
-
-  get 'projects/:id/repository/revisions', :to => 'repositories#revisions'
-  get 'projects/:id/repository/revisions/:rev', :to => 'repositories#revision'
-  get 'projects/:id/repository/revision', :to => 'repositories#revision'
-  post   'projects/:id/repository/revisions/:rev/issues', :to => 'repositories#add_related_issue'
-  delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
-  get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))',
-      :controller => 'repositories',
-      :format => false,
-      :constraints => {
-            :action => /(browse|show|entry|raw|annotate|diff)/,
-            :rev    => /[a-z0-9\.\-_]+/
-          }
-  get 'projects/:id/repository/:repository_id/:action(/*path(.:ext))',
-      :controller => 'repositories',
-      :action => /(browse|show|entry|raw|changes|annotate|diff)/
-  get 'projects/:id/repository/:action(/*path(.:ext))',
-      :controller => 'repositories',
-      :action => /(browse|show|entry|raw|changes|annotate|diff)/
-
-  get 'projects/:id/repository/:repository_id', :to => 'repositories#show', :path => nil
-  get 'projects/:id/repository', :to => 'repositories#show', :path => nil
-
-  # additional routes for having the file name at the end of url
-  get 'attachments/:id/:filename', :to => 'attachments#show', :id => /\d+/, :filename => /.*/, :as => 'named_attachment'
-  get 'attachments/download/:id/:filename', :to => 'attachments#download', :id => /\d+/, :filename => /.*/, :as => 'download_named_attachment'
-  get 'attachments/download/:id', :to => 'attachments#download', :id => /\d+/
-  get 'attachments/thumbnail/:id(/:size)', :to => 'attachments#thumbnail', :id => /\d+/, :size => /\d+/, :as => 'thumbnail'
-  resources :attachments, :only => [:show, :destroy]
-
-  resources :groups do
-    member do
-      get 'autocomplete_for_user'
-    end
-  end
-
-  match 'groups/:id/users', :controller => 'groups', :action => 'add_users', :id => /\d+/, :via => :post, :as => 'group_users'
-  match 'groups/:id/users/:user_id', :controller => 'groups', :action => 'remove_user', :id => /\d+/, :via => :delete, :as => 'group_user'
-  match 'groups/destroy_membership/:id', :controller => 'groups', :action => 'destroy_membership', :id => /\d+/, :via => :post
-  match 'groups/edit_membership/:id', :controller => 'groups', :action => 'edit_membership', :id => /\d+/, :via => :post
-
-  resources :trackers, :except => :show do
-    collection do
-      match 'fields', :via => [:get, :post]
-    end
-  end
-  resources :issue_statuses, :except => :show do
-    collection do
-      post 'update_issue_done_ratio'
-    end
-  end
-  resources :custom_fields, :except => :show
-  resources :roles do
-    collection do
-      match 'permissions', :via => [:get, :post]
-    end
-  end
-  resources :enumerations, :except => :show
-  match 'enumerations/:type', :to => 'enumerations#index', :via => :get
-
-  get 'projects/:id/search', :controller => 'search', :action => 'index'
-  get 'search', :controller => 'search', :action => 'index'
-
-  match 'mail_handler', :controller => 'mail_handler', :action => 'index', :via => :post
-
-  match 'admin', :controller => 'admin', :action => 'index', :via => :get
-  match 'admin/projects', :controller => 'admin', :action => 'projects', :via => :get
-  match 'admin/plugins', :controller => 'admin', :action => 'plugins', :via => :get
-  match 'admin/info', :controller => 'admin', :action => 'info', :via => :get
-  match 'admin/test_email', :controller => 'admin', :action => 'test_email', :via => :get
-  match 'admin/default_configuration', :controller => 'admin', :action => 'default_configuration', :via => :post
-
-  resources :auth_sources do
-    member do
-      get 'test_connection', :as => 'try_connection'
-    end
-    collection do
-      get 'autocomplete_for_new_user'
-    end
-  end
-
-  match 'workflows', :controller => 'workflows', :action => 'index', :via => :get
-  match 'workflows/edit', :controller => 'workflows', :action => 'edit', :via => [:get, :post]
-  match 'workflows/permissions', :controller => 'workflows', :action => 'permissions', :via => [:get, :post]
-  match 'workflows/copy', :controller => 'workflows', :action => 'copy', :via => [:get, :post]
-  match 'settings', :controller => 'settings', :action => 'index', :via => :get
-  match 'settings/edit', :controller => 'settings', :action => 'edit', :via => [:get, :post]
-  match 'settings/plugin/:id', :controller => 'settings', :action => 'plugin', :via => [:get, :post], :as => 'plugin_settings'
-
-  match 'sys/projects', :to => 'sys#projects', :via => :get
-  match 'sys/projects/:id/repository', :to => 'sys#create_project_repository', :via => :post
-  match 'sys/fetch_changesets', :to => 'sys#fetch_changesets', :via => :get
-
-  match 'uploads', :to => 'attachments#upload', :via => :post
-
-  get 'robots.txt', :to => 'welcome#robots'
-
-  Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir|
-    file = File.join(plugin_dir, "config/routes.rb")
-    if File.exists?(file)
-      begin
-        instance_eval File.read(file)
-      rescue Exception => e
-        puts "An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}."
-        exit 1
-      end
-    end
-  end
-end
--- a/.svn/pristine/47/47fe92274420b778273849bcd6f771fbd1ac083b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::TokenAuthenticationTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def setup
-    Setting.rest_api_enabled = '1'
-    Setting.login_required = '1'
-  end
-
-  def teardown
-    Setting.rest_api_enabled = '0'
-    Setting.login_required = '0'
-  end
-
-  # Using the NewsController because it's a simple API.
-  should_allow_key_based_auth(:get, "/news.xml")
-  should_allow_key_based_auth(:get, "/news.json")
-end
--- a/.svn/pristine/48/4829d2fe162c5f9c318c8ff9b05ff5fc25513144.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module WelcomeHelper
-end
--- a/.svn/pristine/48/482dc54fc612e4f812361911050f6c949928488f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class CustomFieldValue
-  attr_accessor :custom_field, :customized, :value
-
-  def custom_field_id
-    custom_field.id
-  end
-
-  def true?
-    self.value == '1'
-  end
-
-  def editable?
-    custom_field.editable?
-  end
-
-  def visible?
-    custom_field.visible?
-  end
-
-  def required?
-    custom_field.is_required?
-  end
-
-  def to_s
-    value.to_s
-  end
-
-  def validate_value
-    custom_field.validate_field_value(value).each do |message|
-      customized.errors.add(:base, custom_field.name + ' ' + message)
-    end
-  end
-end
--- a/.svn/pristine/48/485c22af8fcad2b07fb5864c22ee67cc2bfd6c6f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class SearchTest < ActiveSupport::TestCase
-  fixtures :users,
-           :members,
-           :member_roles,
-           :projects,
-           :roles,
-           :enabled_modules,
-           :issues,
-           :trackers,
-           :journals,
-           :journal_details,
-           :repositories,
-           :changesets
-
-  def setup
-    @project = Project.find(1)
-    @issue_keyword = '%unable to print recipes%'
-    @issue = Issue.find(1)
-    @changeset_keyword = '%very first commit%'
-    @changeset = Changeset.find(100)
-  end
-
-  def test_search_by_anonymous
-    User.current = nil
-
-    r = Issue.search(@issue_keyword).first
-    assert r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert r.include?(@changeset)
-
-    # Removes the :view_changesets permission from Anonymous role
-    remove_permission Role.anonymous, :view_changesets
-    User.current = nil
-
-    r = Issue.search(@issue_keyword).first
-    assert r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert !r.include?(@changeset)
-
-    # Make the project private
-    @project.update_attribute :is_public, false
-    r = Issue.search(@issue_keyword).first
-    assert !r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert !r.include?(@changeset)
-  end
-
-  def test_search_by_user
-    User.current = User.find_by_login('rhill')
-    assert User.current.memberships.empty?
-
-    r = Issue.search(@issue_keyword).first
-    assert r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert r.include?(@changeset)
-
-    # Removes the :view_changesets permission from Non member role
-    remove_permission Role.non_member, :view_changesets
-    User.current = User.find_by_login('rhill')
-
-    r = Issue.search(@issue_keyword).first
-    assert r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert !r.include?(@changeset)
-
-    # Make the project private
-    @project.update_attribute :is_public, false
-    r = Issue.search(@issue_keyword).first
-    assert !r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert !r.include?(@changeset)
-  end
-
-  def test_search_by_allowed_member
-    User.current = User.find_by_login('jsmith')
-    assert User.current.projects.include?(@project)
-
-    r = Issue.search(@issue_keyword).first
-    assert r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert r.include?(@changeset)
-
-    # Make the project private
-    @project.update_attribute :is_public, false
-    r = Issue.search(@issue_keyword).first
-    assert r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert r.include?(@changeset)
-  end
-
-  def test_search_by_unallowed_member
-    # Removes the :view_changesets permission from user's and non member role
-    remove_permission Role.find(1), :view_changesets
-    remove_permission Role.non_member, :view_changesets
-
-    User.current = User.find_by_login('jsmith')
-    assert User.current.projects.include?(@project)
-
-    r = Issue.search(@issue_keyword).first
-    assert r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert !r.include?(@changeset)
-
-    # Make the project private
-    @project.update_attribute :is_public, false
-    r = Issue.search(@issue_keyword).first
-    assert r.include?(@issue)
-    r = Changeset.search(@changeset_keyword).first
-    assert !r.include?(@changeset)
-  end
-
-  def test_search_issue_with_multiple_hits_in_journals
-    i = Issue.find(1)
-    assert_equal 2, i.journals.where("notes LIKE '%notes%'").count
-
-    r = Issue.search('%notes%').first
-    assert_equal 1, r.size
-    assert_equal i, r.first
-  end
-
-  private
-
-  def remove_permission(role, permission)
-    role.permissions = role.permissions - [ permission ]
-    role.save
-  end
-end
--- a/.svn/pristine/48/4881b5ad6e4efa4165188246776dbe492c56e6df.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Principal < ActiveRecord::Base
-  self.table_name = "#{table_name_prefix}users#{table_name_suffix}"
-
-  # Account statuses
-  STATUS_ANONYMOUS  = 0
-  STATUS_ACTIVE     = 1
-  STATUS_REGISTERED = 2
-  STATUS_LOCKED     = 3
-
-  has_many :members, :foreign_key => 'user_id', :dependent => :destroy
-  has_many :memberships, :class_name => 'Member', :foreign_key => 'user_id', :include => [ :project, :roles ], :conditions => "#{Project.table_name}.status<>#{Project::STATUS_ARCHIVED}", :order => "#{Project.table_name}.name"
-  has_many :projects, :through => :memberships
-  has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify
-
-  # Groups and active users
-  scope :active, lambda { where(:status => STATUS_ACTIVE) }
-
-  scope :like, lambda {|q|
-    q = q.to_s
-    if q.blank?
-      where({})
-    else
-      pattern = "%#{q}%"
-      sql = %w(login firstname lastname mail).map {|column| "LOWER(#{table_name}.#{column}) LIKE LOWER(:p)"}.join(" OR ")
-      params = {:p => pattern}
-      if q =~ /^(.+)\s+(.+)$/
-        a, b = "#{$1}%", "#{$2}%"
-        sql << " OR (LOWER(#{table_name}.firstname) LIKE LOWER(:a) AND LOWER(#{table_name}.lastname) LIKE LOWER(:b))"
-        sql << " OR (LOWER(#{table_name}.firstname) LIKE LOWER(:b) AND LOWER(#{table_name}.lastname) LIKE LOWER(:a))"
-        params.merge!(:a => a, :b => b)
-      end
-      where(sql, params)
-    end
-  }
-
-  # Principals that are members of a collection of projects
-  scope :member_of, lambda {|projects|
-    projects = [projects] unless projects.is_a?(Array)
-    if projects.empty?
-      where("1=0")
-    else
-      ids = projects.map(&:id)
-      active.uniq.joins(:members).where("#{Member.table_name}.project_id IN (?)", ids)
-    end
-  }
-  # Principals that are not members of projects
-  scope :not_member_of, lambda {|projects|
-    projects = [projects] unless projects.is_a?(Array)
-    if projects.empty?
-      where("1=0")
-    else
-      ids = projects.map(&:id)
-      where("#{Principal.table_name}.id NOT IN (SELECT DISTINCT user_id FROM #{Member.table_name} WHERE project_id IN (?))", ids)
-    end
-  }
-  scope :sorted, lambda { order(*Principal.fields_for_order_statement)}
-
-  before_create :set_default_empty_values
-
-  def name(formatter = nil)
-    to_s
-  end
-
-  def <=>(principal)
-    if principal.nil?
-      -1
-    elsif self.class.name == principal.class.name
-      self.to_s.downcase <=> principal.to_s.downcase
-    else
-      # groups after users
-      principal.class.name <=> self.class.name
-    end
-  end
-
-  # Returns an array of fields names than can be used to make an order statement for principals.
-  # Users are sorted before Groups.
-  # Examples:
-  def self.fields_for_order_statement(table=nil)
-    table ||= table_name
-    columns = ['type DESC'] + (User.name_formatter[:order] - ['id']) + ['lastname', 'id']
-    columns.uniq.map {|field| "#{table}.#{field}"}
-  end
-
-  protected
-
-  # Make sure we don't try to insert NULL values (see #4632)
-  def set_default_empty_values
-    self.login ||= ''
-    self.hashed_password ||= ''
-    self.firstname ||= ''
-    self.lastname ||= ''
-    self.mail ||= ''
-    true
-  end
-end
--- a/.svn/pristine/48/48978cef54e6b0d716c9ba5b5c6c5a3e24326336.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module TimelogHelper
-  include ApplicationHelper
-
-  def render_timelog_breadcrumb
-    links = []
-    links << link_to(l(:label_project_all), {:project_id => nil, :issue_id => nil})
-    links << link_to(h(@project), {:project_id => @project, :issue_id => nil}) if @project
-    if @issue
-      if @issue.visible?
-        links << link_to_issue(@issue, :subject => false)
-      else
-        links << "##{@issue.id}"
-      end
-    end
-    breadcrumb links
-  end
-
-  # Returns a collection of activities for a select field.  time_entry
-  # is optional and will be used to check if the selected TimeEntryActivity
-  # is active.
-  def activity_collection_for_select_options(time_entry=nil, project=nil)
-    project ||= @project
-    if project.nil?
-      activities = TimeEntryActivity.shared.active
-    else
-      activities = project.activities
-    end
-
-    collection = []
-    if time_entry && time_entry.activity && !time_entry.activity.active?
-      collection << [ "--- #{l(:actionview_instancetag_blank_option)} ---", '' ]
-    else
-      collection << [ "--- #{l(:actionview_instancetag_blank_option)} ---", '' ] unless activities.detect(&:is_default)
-    end
-    activities.each { |a| collection << [a.name, a.id] }
-    collection
-  end
-
-  def select_hours(data, criteria, value)
-    if value.to_s.empty?
-      data.select {|row| row[criteria].blank? }
-    else
-      data.select {|row| row[criteria].to_s == value.to_s}
-    end
-  end
-
-  def sum_hours(data)
-    sum = 0
-    data.each do |row|
-      sum += row['hours'].to_f
-    end
-    sum
-  end
-
-  def options_for_period_select(value)
-    options_for_select([[l(:label_all_time), 'all'],
-                        [l(:label_today), 'today'],
-                        [l(:label_yesterday), 'yesterday'],
-                        [l(:label_this_week), 'current_week'],
-                        [l(:label_last_week), 'last_week'],
-                        [l(:label_last_n_weeks, 2), 'last_2_weeks'],
-                        [l(:label_last_n_days, 7), '7_days'],
-                        [l(:label_this_month), 'current_month'],
-                        [l(:label_last_month), 'last_month'],
-                        [l(:label_last_n_days, 30), '30_days'],
-                        [l(:label_this_year), 'current_year']],
-                        value)
-  end
-
-  def format_criteria_value(criteria_options, value)
-    if value.blank?
-      "[#{l(:label_none)}]"
-    elsif k = criteria_options[:klass]
-      obj = k.find_by_id(value.to_i)
-      if obj.is_a?(Issue)
-        obj.visible? ? "#{obj.tracker} ##{obj.id}: #{obj.subject}" : "##{obj.id}"
-      else
-        obj
-      end
-    else
-      format_value(value, criteria_options[:format])
-    end
-  end
-
-  def report_to_csv(report)
-    decimal_separator = l(:general_csv_decimal_separator)
-    export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
-      # Column headers
-      headers = report.criteria.collect {|criteria| l(report.available_criteria[criteria][:label]) }
-      headers += report.periods
-      headers << l(:label_total_time)
-      csv << headers.collect {|c| Redmine::CodesetUtil.from_utf8(
-                                    c.to_s,
-                                    l(:general_csv_encoding) ) }
-      # Content
-      report_criteria_to_csv(csv, report.available_criteria, report.columns, report.criteria, report.periods, report.hours)
-      # Total row
-      str_total = Redmine::CodesetUtil.from_utf8(l(:label_total_time), l(:general_csv_encoding))
-      row = [ str_total ] + [''] * (report.criteria.size - 1)
-      total = 0
-      report.periods.each do |period|
-        sum = sum_hours(select_hours(report.hours, report.columns, period.to_s))
-        total += sum
-        row << (sum > 0 ? ("%.2f" % sum).gsub('.',decimal_separator) : '')
-      end
-      row << ("%.2f" % total).gsub('.',decimal_separator)
-      csv << row
-    end
-    export
-  end
-
-  def report_criteria_to_csv(csv, available_criteria, columns, criteria, periods, hours, level=0)
-    decimal_separator = l(:general_csv_decimal_separator)
-    hours.collect {|h| h[criteria[level]].to_s}.uniq.each do |value|
-      hours_for_value = select_hours(hours, criteria[level], value)
-      next if hours_for_value.empty?
-      row = [''] * level
-      row << Redmine::CodesetUtil.from_utf8(
-                        format_criteria_value(available_criteria[criteria[level]], value).to_s,
-                        l(:general_csv_encoding) )
-      row += [''] * (criteria.length - level - 1)
-      total = 0
-      periods.each do |period|
-        sum = sum_hours(select_hours(hours_for_value, columns, period.to_s))
-        total += sum
-        row << (sum > 0 ? ("%.2f" % sum).gsub('.',decimal_separator) : '')
-      end
-      row << ("%.2f" % total).gsub('.',decimal_separator)
-      csv << row
-      if criteria.length > level + 1
-        report_criteria_to_csv(csv, available_criteria, columns, criteria, periods, hours_for_value, level + 1)
-      end
-    end
-  end
-end
--- a/.svn/pristine/49/493a8cd26b7fa714fe78dd4274ecdc966ff8a00e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module SubclassFactory
-    def self.included(base) 
-      base.extend ClassMethods
-    end 
-
-    module ClassMethods
-      def get_subclass(class_name)
-        klass = nil
-        begin
-          klass = class_name.to_s.classify.constantize
-        rescue
-          # invalid class name
-        end
-        unless subclasses.include? klass
-          klass = nil
-        end
-        klass
-      end
-
-      # Returns an instance of the given subclass name
-      def new_subclass_instance(class_name, *args)
-        klass = get_subclass(class_name)
-        if klass
-          klass.new(*args)
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/4a/4a1058fec0661c02d0fe7d4f1388a59811624904.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,492 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-require 'digest/md5'
-
-class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
-
-  def setup
-    @formatter = Redmine::WikiFormatting::Textile::Formatter
-  end
-
-  MODIFIERS = {
-    "*" => 'strong', # bold
-    "_" => 'em',     # italic
-    "+" => 'ins',    # underline
-    "-" => 'del',    # deleted
-    "^" => 'sup',    # superscript
-    "~" => 'sub'     # subscript
-  }
-
-  def test_modifiers
-    assert_html_output(
-      '*bold*'                => '<strong>bold</strong>',
-      'before *bold*'         => 'before <strong>bold</strong>',
-      '*bold* after'          => '<strong>bold</strong> after',
-      '*two words*'           => '<strong>two words</strong>',
-      '*two*words*'           => '<strong>two*words</strong>',
-      '*two * words*'         => '<strong>two * words</strong>',
-      '*two* *words*'         => '<strong>two</strong> <strong>words</strong>',
-      '*(two)* *(words)*'     => '<strong>(two)</strong> <strong>(words)</strong>',
-      # with class
-      '*(foo)two words*'      => '<strong class="foo">two words</strong>'
-    )
-  end
-
-  def test_modifiers_combination
-    MODIFIERS.each do |m1, tag1|
-      MODIFIERS.each do |m2, tag2|
-        next if m1 == m2
-        text = "#{m2}#{m1}Phrase modifiers#{m1}#{m2}"
-        html = "<#{tag2}><#{tag1}>Phrase modifiers</#{tag1}></#{tag2}>"
-        assert_html_output text => html
-      end
-    end
-  end
-
-  def test_styles
-    # single style
-    assert_html_output({
-      'p{color:red}. text'           => '<p style="color:red;">text</p>',
-      'p{color:red;}. text'          => '<p style="color:red;">text</p>',
-      'p{color: red}. text'          => '<p style="color: red;">text</p>',
-      'p{color:#f00}. text'          => '<p style="color:#f00;">text</p>',
-      'p{color:#ff0000}. text'       => '<p style="color:#ff0000;">text</p>',
-      'p{border:10px}. text'         => '<p style="border:10px;">text</p>',
-      'p{border:10}. text'           => '<p style="border:10;">text</p>',
-      'p{border:10%}. text'          => '<p style="border:10%;">text</p>',
-      'p{border:10em}. text'         => '<p style="border:10em;">text</p>',
-      'p{border:1.5em}. text'        => '<p style="border:1.5em;">text</p>',
-      'p{border-left:1px}. text'     => '<p style="border-left:1px;">text</p>',
-      'p{border-right:1px}. text'    => '<p style="border-right:1px;">text</p>',
-      'p{border-top:1px}. text'      => '<p style="border-top:1px;">text</p>',
-      'p{border-bottom:1px}. text'   => '<p style="border-bottom:1px;">text</p>',
-      }, false)
-
-    # multiple styles
-    assert_html_output({
-      'p{color:red; border-top:1px}. text'   => '<p style="color:red;border-top:1px;">text</p>',
-      'p{color:red ; border-top:1px}. text'  => '<p style="color:red;border-top:1px;">text</p>',
-      'p{color:red;border-top:1px}. text'    => '<p style="color:red;border-top:1px;">text</p>',
-      }, false)
-
-    # styles with multiple values
-    assert_html_output({
-      'p{border:1px solid red;}. text'             => '<p style="border:1px solid red;">text</p>',
-      'p{border-top-left-radius: 10px 5px;}. text' => '<p style="border-top-left-radius: 10px 5px;">text</p>',
-      }, false)
-  end
-
-  def test_invalid_styles_should_be_filtered
-    assert_html_output({
-      'p{invalid}. text'                     => '<p>text</p>',
-      'p{invalid:red}. text'                 => '<p>text</p>',
-      'p{color:(red)}. text'                 => '<p>text</p>',
-      'p{color:red;invalid:blue}. text'      => '<p style="color:red;">text</p>',
-      'p{invalid:blue;color:red}. text'      => '<p style="color:red;">text</p>',
-      'p{color:"}. text'                     => '<p>p{color:"}. text</p>',
-      }, false)
-  end
-
-  def test_inline_code
-    assert_html_output(
-      'this is @some code@'      => 'this is <code>some code</code>',
-      '@<Location /redmine>@'    => '<code>&lt;Location /redmine&gt;</code>'
-    )
-  end
-
-  def test_nested_lists
-    raw = <<-RAW
-# Item 1
-# Item 2
-** Item 2a
-** Item 2b
-# Item 3
-** Item 3a
-RAW
-
-    expected = <<-EXPECTED
-<ol>
-  <li>Item 1</li>
-  <li>Item 2
-    <ul>
-      <li>Item 2a</li>
-      <li>Item 2b</li>
-    </ul>
-  </li>
-  <li>Item 3
-    <ul>
-      <li>Item 3a</li>
-    </ul>
-  </li>
-</ol>
-EXPECTED
-
-    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
-  end
-
-  def test_escaping
-    assert_html_output(
-      'this is a <script>'      => 'this is a &lt;script&gt;'
-    )
-  end
-
-  def test_use_of_backslashes_followed_by_numbers_in_headers
-    assert_html_output({
-      'h1. 2009\02\09'      => '<h1>2009\02\09</h1>'
-    }, false)
-  end
-
-  def test_double_dashes_should_not_strikethrough
-    assert_html_output(
-      'double -- dashes -- test'  => 'double -- dashes -- test',
-      'double -- *dashes* -- test'  => 'double -- <strong>dashes</strong> -- test'
-    )
-  end
-
-  def test_abbreviations
-    assert_html_output(
-      'this is an abbreviation: GPL(General Public License)' => 'this is an abbreviation: <abbr title="General Public License">GPL</abbr>',
-      '2 letters JP(Jean-Philippe) abbreviation' => '2 letters <abbr title="Jean-Philippe">JP</abbr> abbreviation',
-      'GPL(This is a double-quoted "title")' => '<abbr title="This is a double-quoted &quot;title&quot;">GPL</abbr>'
-    )
-  end
-
-  def test_blockquote
-    # orig raw text
-    raw = <<-RAW
-John said:
-> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
-> Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
-> * Donec odio lorem,
-> * sagittis ac,
-> * malesuada in,
-> * adipiscing eu, dolor.
->
-> >Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.
-> Proin a tellus. Nam vel neque.
-
-He's right.
-RAW
-
-    # expected html
-    expected = <<-EXPECTED
-<p>John said:</p>
-<blockquote>
-Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.<br />
-Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
-<ul>
-  <li>Donec odio lorem,</li>
-  <li>sagittis ac,</li>
-  <li>malesuada in,</li>
-  <li>adipiscing eu, dolor.</li>
-</ul>
-<blockquote>
-<p>Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.</p>
-</blockquote>
-<p>Proin a tellus. Nam vel neque.</p>
-</blockquote>
-<p>He's right.</p>
-EXPECTED
-
-    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
-  end
-
-  def test_table
-    raw = <<-RAW
-This is a table with empty cells:
-
-|cell11|cell12||
-|cell21||cell23|
-|cell31|cell32|cell33|
-RAW
-
-    expected = <<-EXPECTED
-<p>This is a table with empty cells:</p>
-
-<table>
-  <tr><td>cell11</td><td>cell12</td><td></td></tr>
-  <tr><td>cell21</td><td></td><td>cell23</td></tr>
-  <tr><td>cell31</td><td>cell32</td><td>cell33</td></tr>
-</table>
-EXPECTED
-
-    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
-  end
-
-  def test_table_with_line_breaks
-    raw = <<-RAW
-This is a table with line breaks:
-
-|cell11
-continued|cell12||
-|-cell21-||cell23
-cell23 line2
-cell23 *line3*|
-|cell31|cell32
-cell32 line2|cell33|
-
-RAW
-
-    expected = <<-EXPECTED
-<p>This is a table with line breaks:</p>
-
-<table>
-  <tr>
-    <td>cell11<br />continued</td>
-    <td>cell12</td>
-    <td></td>
-  </tr>
-  <tr>
-    <td><del>cell21</del></td>
-    <td></td>
-    <td>cell23<br/>cell23 line2<br/>cell23 <strong>line3</strong></td>
-  </tr>
-  <tr>
-    <td>cell31</td>
-    <td>cell32<br/>cell32 line2</td>
-    <td>cell33</td>
-  </tr>
-</table>
-EXPECTED
-
-    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
-  end
-
-  def test_tables_with_lists
-    raw = <<-RAW
-This is a table with lists:
-
-|cell11|cell12|
-|cell21|ordered list
-# item
-# item 2|
-|cell31|unordered list
-* item
-* item 2|
-
-RAW
-
-    expected = <<-EXPECTED
-<p>This is a table with lists:</p>
-
-<table>
-  <tr>
-    <td>cell11</td>
-    <td>cell12</td>
-  </tr>
-  <tr>
-    <td>cell21</td>
-    <td>ordered list<br /># item<br /># item 2</td>
-  </tr>
-  <tr>
-    <td>cell31</td>
-    <td>unordered list<br />* item<br />* item 2</td>
-  </tr>
-</table>
-EXPECTED
-
-    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
-  end
-
-  def test_textile_should_not_mangle_brackets
-    assert_equal '<p>[msg1][msg2]</p>', to_html('[msg1][msg2]')
-  end
-
-  def test_textile_should_escape_image_urls
-    # this is onclick="alert('XSS');" in encoded form
-    raw = '!/images/comment.png"onclick=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;;&#x22;!'
-    expected = '<p><img src="/images/comment.png&quot;onclick=&amp;#x61;&amp;#x6c;&amp;#x65;&amp;#x72;&amp;#x74;&amp;#x28;&amp;#x27;&amp;#x58;&amp;#x53;&amp;#x53;&amp;#x27;&amp;#x29;;&amp;#x22;" alt="" /></p>'
-    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
-  end
-  
-  
-  STR_WITHOUT_PRE = [
-  # 0
-"h1. Title
-
-Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
-  # 1
-"h2. Heading 2
-
-Maecenas sed elit sit amet mi accumsan vestibulum non nec velit. Proin porta tincidunt lorem, consequat rhoncus dolor fermentum in.
-
-Cras ipsum felis, ultrices at porttitor vel, faucibus eu nunc.",
-  # 2
-"h2. Heading 2
-
-Morbi facilisis accumsan orci non pharetra.
-
-h3. Heading 3
-
-Nulla nunc nisi, egestas in ornare vel, posuere ac libero.",
-  # 3
-"h3. Heading 3
-
-Praesent eget turpis nibh, a lacinia nulla.",
-  # 4
-"h2. Heading 2
-
-Ut rhoncus elementum adipiscing."]
-
-  TEXT_WITHOUT_PRE = STR_WITHOUT_PRE.join("\n\n").freeze
-  
-  def test_get_section_should_return_the_requested_section_and_its_hash
-    assert_section_with_hash STR_WITHOUT_PRE[1], TEXT_WITHOUT_PRE, 2
-    assert_section_with_hash STR_WITHOUT_PRE[2..3].join("\n\n"), TEXT_WITHOUT_PRE, 3
-    assert_section_with_hash STR_WITHOUT_PRE[3], TEXT_WITHOUT_PRE, 5
-    assert_section_with_hash STR_WITHOUT_PRE[4], TEXT_WITHOUT_PRE, 6
-    
-    assert_section_with_hash '', TEXT_WITHOUT_PRE, 0
-    assert_section_with_hash '', TEXT_WITHOUT_PRE, 10
-  end
-  
-  def test_update_section_should_update_the_requested_section
-    replacement = "New text"
-    
-    assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement)
-    assert_equal [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(3, replacement)
-    assert_equal [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(5, replacement)
-    assert_equal [STR_WITHOUT_PRE[0..3], replacement].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(6, replacement)
-    
-    assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(0, replacement)
-    assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(10, replacement)
-  end
-  
-  def test_update_section_with_hash_should_update_the_requested_section
-    replacement = "New text"
-    
-    assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"),
-      @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement, Digest::MD5.hexdigest(STR_WITHOUT_PRE[1]))
-  end
-  
-  def test_update_section_with_wrong_hash_should_raise_an_error
-    assert_raise Redmine::WikiFormatting::StaleSectionError do
-      @formatter.new(TEXT_WITHOUT_PRE).update_section(2, "New text", Digest::MD5.hexdigest("Old text"))
-    end
-  end
-
-  STR_WITH_PRE = [
-  # 0
-"h1. Title
-
-Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
-  # 1
-"h2. Heading 2
-
-<pre><code class=\"ruby\">
-  def foo
-  end
-</code></pre>
-
-<pre><code><pre><code class=\"ruby\">
-  Place your code here.
-</code></pre>
-</code></pre>
-
-Morbi facilisis accumsan orci non pharetra.
-
-<pre>
-Pre Content:
-
-h2. Inside pre
-
-<tag> inside pre block
-
-Morbi facilisis accumsan orci non pharetra.
-</pre>",
-  # 2
-"h3. Heading 3
-
-Nulla nunc nisi, egestas in ornare vel, posuere ac libero."]
-
-  def test_get_section_should_ignore_pre_content
-    text = STR_WITH_PRE.join("\n\n")
-
-    assert_section_with_hash STR_WITH_PRE[1..2].join("\n\n"), text, 2
-    assert_section_with_hash STR_WITH_PRE[2], text, 3
-  end
-
-  def test_update_section_should_not_escape_pre_content_outside_section
-    text = STR_WITH_PRE.join("\n\n")
-    replacement = "New text"
-    
-    assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"),
-      @formatter.new(text).update_section(3, replacement)
-  end
-
-  def test_get_section_should_support_lines_with_spaces_before_heading
-    # the lines after Content 2 and Heading 4 contain a space
-    text = <<-STR
-h1. Heading 1
-
-Content 1
-
-h1. Heading 2
-
-Content 2
- 
-h1. Heading 3
-
-Content 3
-
-h1. Heading 4
- 
-Content 4
-STR
-
-    [1, 2, 3, 4].each do |index|
-      assert_match /\Ah1. Heading #{index}.+Content #{index}/m, @formatter.new(text).get_section(index).first
-    end
-  end
-
-  def test_get_section_should_support_headings_starting_with_a_tab
-    text = <<-STR
-h1.\tHeading 1
-
-Content 1
-
-h1. Heading 2
-
-Content 2
-STR
-
-    assert_match /\Ah1.\tHeading 1\s+Content 1\z/, @formatter.new(text).get_section(1).first
-  end
-
-  private
-
-  def assert_html_output(to_test, expect_paragraph = true)
-    to_test.each do |text, expected|
-      assert_equal(( expect_paragraph ? "<p>#{expected}</p>" : expected ), @formatter.new(text).to_html, "Formatting the following text failed:\n===\n#{text}\n===\n")
-    end
-  end
-
-  def to_html(text)
-    @formatter.new(text).to_html
-  end
-  
-  def assert_section_with_hash(expected, text, index)
-    result = @formatter.new(text).get_section(index)
-    
-    assert_kind_of Array, result
-    assert_equal 2, result.size
-    assert_equal expected, result.first, "section content did not match"
-    assert_equal Digest::MD5.hexdigest(expected), result.last, "section hash did not match"
-  end
-end
--- a/.svn/pristine/4b/4b33122ac4316f4c1a07b0e693b6a8dd1a319fd4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ReportsControllerTest < ActionController::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :versions
-
-  def test_get_issue_report
-    get :issue_report, :id => 1
-
-    assert_response :success
-    assert_template 'issue_report'
-
-    [:issues_by_tracker, :issues_by_version, :issues_by_category, :issues_by_assigned_to,
-     :issues_by_author, :issues_by_subproject, :issues_by_priority].each do |ivar|
-      assert_not_nil assigns(ivar)
-    end
-
-    assert_equal IssuePriority.all.reverse, assigns(:priorities)
-  end
-
-  def test_get_issue_report_details
-    %w(tracker version priority category assigned_to author subproject).each do |detail|
-      get :issue_report_details, :id => 1, :detail => detail
-
-      assert_response :success
-      assert_template 'issue_report_details'
-      assert_not_nil assigns(:field)
-      assert_not_nil assigns(:rows)
-      assert_not_nil assigns(:data)
-      assert_not_nil assigns(:report_title)
-    end
-  end
-
-  def test_get_issue_report_details_by_tracker_should_show_issue_count
-    Issue.delete_all
-    Issue.generate!(:tracker_id => 1)
-    Issue.generate!(:tracker_id => 1)
-    Issue.generate!(:tracker_id => 1, :status_id => 5)
-    Issue.generate!(:tracker_id => 2)
-
-    get :issue_report_details, :id => 1, :detail => 'tracker'
-    assert_select 'table.list tbody :nth-child(1)' do
-      assert_select 'td', :text => 'Bug'
-      assert_select ':nth-child(2)', :text => '2' # status:1
-      assert_select ':nth-child(3)', :text => '-' # status:2
-      assert_select ':nth-child(8)', :text => '2' # open
-      assert_select ':nth-child(9)', :text => '1' # closed
-      assert_select ':nth-child(10)', :text => '3' # total
-    end
-  end
-
-  def test_get_issue_report_details_by_priority
-    get :issue_report_details, :id => 1, :detail => 'priority'
-    assert_equal IssuePriority.all.reverse, assigns(:rows)
-  end
-
-  def test_get_issue_report_details_with_an_invalid_detail
-    get :issue_report_details, :id => 1, :detail => 'invalid'
-
-    assert_redirected_to '/projects/ecookbook/issues/report'
-  end
-end
--- a/.svn/pristine/4b/4ba58f8d37b5a8de881d99e50a2cc37a4cef0a15.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,297 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
-           :repositories, :issues, :issue_statuses, :changesets, :changes,
-           :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers
-
-  def setup
-    User.current = nil
-  end
-
-  def test_new
-    @request.session[:user_id] = 1
-    get :new, :project_id => 'subproject1'
-    assert_response :success
-    assert_template 'new'
-    assert_kind_of Repository::Subversion, assigns(:repository)
-    assert assigns(:repository).new_record?
-    assert_tag 'input', :attributes => {:name => 'repository[url]', :disabled => nil}
-  end
-
-  def test_new_should_propose_enabled_scm_only
-    @request.session[:user_id] = 1
-    with_settings :enabled_scm => ['Mercurial', 'Git'] do
-      get :new, :project_id => 'subproject1'
-    end
-    assert_response :success
-    assert_template 'new'
-    assert_kind_of Repository::Mercurial, assigns(:repository)
-    assert_tag 'select', :attributes => {:name => 'repository_scm'},
-      :children => {:count => 3}
-    assert_tag 'select', :attributes => {:name => 'repository_scm'},
-      :child => {:tag => 'option', :attributes => {:value => 'Mercurial', :selected => 'selected'}}
-    assert_tag 'select', :attributes => {:name => 'repository_scm'},
-      :child => {:tag => 'option', :attributes => {:value => 'Git', :selected => nil}}
-  end
-
-  def test_create
-    @request.session[:user_id] = 1
-    assert_difference 'Repository.count' do
-      post :create, :project_id => 'subproject1',
-           :repository_scm => 'Subversion',
-           :repository => {:url => 'file:///test', :is_default => '1', :identifier => ''}
-    end
-    assert_response 302
-    repository = Repository.first(:order => 'id DESC')
-    assert_kind_of Repository::Subversion, repository
-    assert_equal 'file:///test', repository.url
-  end
-
-  def test_create_with_failure
-    @request.session[:user_id] = 1
-    assert_no_difference 'Repository.count' do
-      post :create, :project_id => 'subproject1',
-           :repository_scm => 'Subversion',
-           :repository => {:url => 'invalid'}
-    end
-    assert_response :success
-    assert_template 'new'
-    assert_kind_of Repository::Subversion, assigns(:repository)
-    assert assigns(:repository).new_record?
-  end
-
-  def test_edit
-    @request.session[:user_id] = 1
-    get :edit, :id => 11
-    assert_response :success
-    assert_template 'edit'
-    assert_equal Repository.find(11), assigns(:repository)
-    assert_tag 'input', :attributes => {:name => 'repository[url]', :value => 'svn://localhost/test', :disabled => 'disabled'}
-  end
-
-  def test_update
-    @request.session[:user_id] = 1
-    put :update, :id => 11, :repository => {:password => 'test_update'}
-    assert_response 302
-    assert_equal 'test_update', Repository.find(11).password
-  end
-
-  def test_update_with_failure
-    @request.session[:user_id] = 1
-    put :update, :id => 11, :repository => {:password => 'x'*260}
-    assert_response :success
-    assert_template 'edit'
-    assert_equal Repository.find(11), assigns(:repository)
-  end
-
-  def test_destroy
-    @request.session[:user_id] = 1
-    assert_difference 'Repository.count', -1 do
-      delete :destroy, :id => 11
-    end
-    assert_response 302
-    assert_nil Repository.find_by_id(11)
-  end
-
-  def test_show_with_autofetch_changesets_enabled_should_fetch_changesets
-    Repository::Subversion.any_instance.expects(:fetch_changesets).once
-
-    with_settings :autofetch_changesets => '1' do
-      get :show, :id => 1
-    end
-  end
-
-  def test_show_with_autofetch_changesets_disabled_should_not_fetch_changesets
-    Repository::Subversion.any_instance.expects(:fetch_changesets).never
-
-    with_settings :autofetch_changesets => '0' do
-      get :show, :id => 1
-    end
-  end
-
-  def test_show_with_closed_project_should_not_fetch_changesets
-    Repository::Subversion.any_instance.expects(:fetch_changesets).never
-    Project.find(1).close
-
-    with_settings :autofetch_changesets => '1' do
-      get :show, :id => 1
-    end
-  end
-
-  def test_revisions
-    get :revisions, :id => 1
-    assert_response :success
-    assert_template 'revisions'
-    assert_equal Repository.find(10), assigns(:repository)
-    assert_not_nil assigns(:changesets)
-  end
-
-  def test_revisions_for_other_repository
-    repository = Repository::Subversion.create!(:project_id => 1, :identifier => 'foo', :url => 'file:///foo')
-
-    get :revisions, :id => 1, :repository_id => 'foo'
-    assert_response :success
-    assert_template 'revisions'
-    assert_equal repository, assigns(:repository)
-    assert_not_nil assigns(:changesets)
-  end
-
-  def test_revisions_for_invalid_repository
-    get :revisions, :id => 1, :repository_id => 'foo'
-    assert_response 404
-  end
-
-  def test_revision
-    get :revision, :id => 1, :rev => 1
-    assert_response :success
-    assert_not_nil assigns(:changeset)
-    assert_equal "1", assigns(:changeset).revision
-  end
-
-  def test_revision_should_not_change_the_project_menu_link
-    get :revision, :id => 1, :rev => 1
-    assert_response :success
-
-    assert_tag 'a', :attributes => {:href => '/projects/ecookbook/repository', :class => /repository/},
-      :ancestor => {:attributes => {:id => 'main-menu'}}
-  end
-
-  def test_revision_with_before_nil_and_afer_normal
-    get :revision, {:id => 1, :rev => 1}
-    assert_response :success
-    assert_template 'revision'
-    assert_no_tag :tag => "div", :attributes => { :class => "contextual" },
-      :child => { :tag => "a", :attributes => { :href => '/projects/ecookbook/repository/revisions/0'}
-    }
-    assert_tag :tag => "div", :attributes => { :class => "contextual" },
-        :child => { :tag => "a", :attributes => { :href => '/projects/ecookbook/repository/revisions/2'}
-    }
-  end
-
-  def test_add_related_issue
-    @request.session[:user_id] = 2
-    assert_difference 'Changeset.find(103).issues.size' do
-      xhr :post, :add_related_issue, :id => 1, :rev => 4, :issue_id => 2, :format => 'js'
-      assert_response :success
-      assert_template 'add_related_issue'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_equal [2], Changeset.find(103).issue_ids
-    assert_include 'related-issues', response.body
-    assert_include 'Feature request #2', response.body
-  end
-
-  def test_add_related_issue_should_accept_issue_id_with_sharp
-    @request.session[:user_id] = 2
-    assert_difference 'Changeset.find(103).issues.size' do
-      xhr :post, :add_related_issue, :id => 1, :rev => 4, :issue_id => "#2", :format => 'js'
-    end
-    assert_equal [2], Changeset.find(103).issue_ids
-  end
-
-  def test_add_related_issue_with_invalid_issue_id
-    @request.session[:user_id] = 2
-    assert_no_difference 'Changeset.find(103).issues.size' do
-      xhr :post, :add_related_issue, :id => 1, :rev => 4, :issue_id => 9999, :format => 'js'
-      assert_response :success
-      assert_template 'add_related_issue'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_include 'alert("Issue is invalid")', response.body
-  end
-
-  def test_remove_related_issue
-    Changeset.find(103).issues << Issue.find(1)
-    Changeset.find(103).issues << Issue.find(2)
-
-    @request.session[:user_id] = 2
-    assert_difference 'Changeset.find(103).issues.size', -1 do
-      xhr :delete, :remove_related_issue, :id => 1, :rev => 4, :issue_id => 2, :format => 'js'
-      assert_response :success
-      assert_template 'remove_related_issue'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_equal [1], Changeset.find(103).issue_ids
-    assert_include 'related-issue-2', response.body
-  end
-
-  def test_graph_commits_per_month
-    # Make sure there's some data to display
-    latest = Project.find(1).repository.changesets.maximum(:commit_date)
-    assert_not_nil latest
-    Date.stubs(:today).returns(latest.to_date + 10)
-
-    get :graph, :id => 1, :graph => 'commits_per_month'
-    assert_response :success
-    assert_equal 'image/svg+xml', @response.content_type
-  end
-
-  def test_graph_commits_per_author
-    get :graph, :id => 1, :graph => 'commits_per_author'
-    assert_response :success
-    assert_equal 'image/svg+xml', @response.content_type
-  end
-
-  def test_get_committers
-    @request.session[:user_id] = 2
-    # add a commit with an unknown user
-    Changeset.create!(
-        :repository => Project.find(1).repository,
-        :committer  => 'foo',
-        :committed_on => Time.now,
-        :revision => 100,
-        :comments => 'Committed by foo.'
-     )
-
-    get :committers, :id => 10
-    assert_response :success
-    assert_template 'committers'
-
-    assert_tag :td, :content => 'dlopper',
-                    :sibling => { :tag => 'td',
-                                  :child => { :tag => 'select', :attributes => { :name => %r{^committers\[\d+\]\[\]$} },
-                                                                :child => { :tag => 'option', :content => 'Dave Lopper',
-                                                                                              :attributes => { :value => '3', :selected => 'selected' }}}}
-    assert_tag :td, :content => 'foo',
-                    :sibling => { :tag => 'td',
-                                  :child => { :tag => 'select', :attributes => { :name => %r{^committers\[\d+\]\[\]$} }}}
-    assert_no_tag :td, :content => 'foo',
-                       :sibling => { :tag => 'td',
-                                     :descendant => { :tag => 'option', :attributes => { :selected => 'selected' }}}
-  end
-
-  def test_post_committers
-    @request.session[:user_id] = 2
-    # add a commit with an unknown user
-    c = Changeset.create!(
-            :repository => Project.find(1).repository,
-            :committer  => 'foo',
-            :committed_on => Time.now,
-            :revision => 100,
-            :comments => 'Committed by foo.'
-          )
-    assert_no_difference "Changeset.where(:user_id => 3).count" do
-      post :committers, :id => 10, :committers => { '0' => ['foo', '2'], '1' => ['dlopper', '3']}
-      assert_response 302
-      assert_equal User.find(2), c.reload.user
-    end
-  end
-end
--- a/.svn/pristine/4c/4c336c258123fb4e9b45bc7fc7cd3f56f7293d30.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module IssueCategoriesHelper
-end
--- a/.svn/pristine/4c/4cf321de05d6993523d4f53f4c3078dcaf49b46c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,265 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class SearchControllerTest < ActionController::TestCase
-  fixtures :projects, :enabled_modules, :roles, :users, :members, :member_roles,
-           :issues, :trackers, :issue_statuses, :enumerations,
-           :custom_fields, :custom_values,
-           :repositories, :changesets
-
-  def setup
-    User.current = nil
-  end
-
-  def test_search_for_projects
-    get :index
-    assert_response :success
-    assert_template 'index'
-
-    get :index, :q => "cook"
-    assert_response :success
-    assert_template 'index'
-    assert assigns(:results).include?(Project.find(1))
-  end
-
-  def test_search_all_projects
-    get :index, :q => 'recipe subproject commit', :all_words => ''
-    assert_response :success
-    assert_template 'index'
-
-    assert assigns(:results).include?(Issue.find(2))
-    assert assigns(:results).include?(Issue.find(5))
-    assert assigns(:results).include?(Changeset.find(101))
-    assert_tag :dt, :attributes => { :class => /issue/ },
-                    :child => { :tag => 'a',  :content => /Add ingredients categories/ },
-                    :sibling => { :tag => 'dd', :content => /should be classified by categories/ }
-
-    assert assigns(:results_by_type).is_a?(Hash)
-    assert_equal 5, assigns(:results_by_type)['changesets']
-    assert_tag :a, :content => 'Changesets (5)'
-  end
-
-  def test_search_issues
-    get :index, :q => 'issue', :issues => 1
-    assert_response :success
-    assert_template 'index'
-
-    assert_equal true, assigns(:all_words)
-    assert_equal false, assigns(:titles_only)
-    assert assigns(:results).include?(Issue.find(8))
-    assert assigns(:results).include?(Issue.find(5))
-    assert_tag :dt, :attributes => { :class => /issue closed/ },
-                    :child => { :tag => 'a',  :content => /Closed/ }
-  end
-
-  def test_search_issues_should_search_notes
-    Journal.create!(:journalized => Issue.find(2), :notes => 'Issue notes with searchkeyword')
-
-    get :index, :q => 'searchkeyword', :issues => 1
-    assert_response :success
-    assert_include Issue.find(2), assigns(:results)
-  end
-
-  def test_search_issues_with_multiple_matches_in_journals_should_return_issue_once
-    Journal.create!(:journalized => Issue.find(2), :notes => 'Issue notes with searchkeyword')
-    Journal.create!(:journalized => Issue.find(2), :notes => 'Issue notes with searchkeyword')
-
-    get :index, :q => 'searchkeyword', :issues => 1
-    assert_response :success
-    assert_include Issue.find(2), assigns(:results)
-    assert_equal 1, assigns(:results).size
-  end
-
-  def test_search_issues_should_search_private_notes_with_permission_only
-    Journal.create!(:journalized => Issue.find(2), :notes => 'Private notes with searchkeyword', :private_notes => true)
-    @request.session[:user_id] = 2
-
-    Role.find(1).add_permission! :view_private_notes
-    get :index, :q => 'searchkeyword', :issues => 1
-    assert_response :success
-    assert_include Issue.find(2), assigns(:results)
-
-    Role.find(1).remove_permission! :view_private_notes
-    get :index, :q => 'searchkeyword', :issues => 1
-    assert_response :success
-    assert_not_include Issue.find(2), assigns(:results)
-  end
-
-  def test_search_all_projects_with_scope_param
-    get :index, :q => 'issue', :scope => 'all'
-    assert_response :success
-    assert_template 'index'
-    assert assigns(:results).present?
-  end
-
-  def test_search_my_projects
-    @request.session[:user_id] = 2
-    get :index, :id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => ''
-    assert_response :success
-    assert_template 'index'
-    assert assigns(:results).include?(Issue.find(1))
-    assert !assigns(:results).include?(Issue.find(5))
-  end
-
-  def test_search_my_projects_without_memberships
-    # anonymous user has no memberships
-    get :index, :id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => ''
-    assert_response :success
-    assert_template 'index'
-    assert assigns(:results).empty?
-  end
-
-  def test_search_project_and_subprojects
-    get :index, :id => 1, :q => 'recipe subproject', :scope => 'subprojects', :all_words => ''
-    assert_response :success
-    assert_template 'index'
-    assert assigns(:results).include?(Issue.find(1))
-    assert assigns(:results).include?(Issue.find(5))
-  end
-
-  def test_search_without_searchable_custom_fields
-    CustomField.update_all "searchable = #{ActiveRecord::Base.connection.quoted_false}"
-
-    get :index, :id => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:project)
-
-    get :index, :id => 1, :q => "can"
-    assert_response :success
-    assert_template 'index'
-  end
-
-  def test_search_with_searchable_custom_fields
-    get :index, :id => 1, :q => "stringforcustomfield"
-    assert_response :success
-    results = assigns(:results)
-    assert_not_nil results
-    assert_equal 1, results.size
-    assert results.include?(Issue.find(7))
-  end
-
-  def test_search_all_words
-    # 'all words' is on by default
-    get :index, :id => 1, :q => 'recipe updating saving', :all_words => '1'
-    assert_equal true, assigns(:all_words)
-    results = assigns(:results)
-    assert_not_nil results
-    assert_equal 1, results.size
-    assert results.include?(Issue.find(3))
-  end
-
-  def test_search_one_of_the_words
-    get :index, :id => 1, :q => 'recipe updating saving', :all_words => ''
-    assert_equal false, assigns(:all_words)
-    results = assigns(:results)
-    assert_not_nil results
-    assert_equal 3, results.size
-    assert results.include?(Issue.find(3))
-  end
-
-  def test_search_titles_only_without_result
-    get :index, :id => 1, :q => 'recipe updating saving', :titles_only => '1'
-    results = assigns(:results)
-    assert_not_nil results
-    assert_equal 0, results.size
-  end
-
-  def test_search_titles_only
-    get :index, :id => 1, :q => 'recipe', :titles_only => '1'
-    assert_equal true, assigns(:titles_only)
-    results = assigns(:results)
-    assert_not_nil results
-    assert_equal 2, results.size
-  end
-
-  def test_search_content
-    Issue.update_all("description = 'This is a searchkeywordinthecontent'", "id=1")
-
-    get :index, :id => 1, :q => 'searchkeywordinthecontent', :titles_only => ''
-    assert_equal false, assigns(:titles_only)
-    results = assigns(:results)
-    assert_not_nil results
-    assert_equal 1, results.size
-  end
-
-  def test_search_with_offset
-    get :index, :q => 'coo', :offset => '20080806073000'
-    assert_response :success
-    results = assigns(:results)
-    assert results.any?
-    assert results.map(&:event_datetime).max < '20080806T073000'.to_time
-  end
-
-  def test_search_previous_with_offset
-    get :index, :q => 'coo', :offset => '20080806073000', :previous => '1'
-    assert_response :success
-    results = assigns(:results)
-    assert results.any?
-    assert results.map(&:event_datetime).min >= '20080806T073000'.to_time
-  end
-
-  def test_search_with_invalid_project_id
-    get :index, :id => 195, :q => 'recipe'
-    assert_response 404
-    assert_nil assigns(:results)
-  end
-
-  def test_quick_jump_to_issue
-    # issue of a public project
-    get :index, :q => "3"
-    assert_redirected_to '/issues/3'
-
-    # issue of a private project
-    get :index, :q => "4"
-    assert_response :success
-    assert_template 'index'
-  end
-
-  def test_large_integer
-    get :index, :q => '4615713488'
-    assert_response :success
-    assert_template 'index'
-  end
-
-  def test_tokens_with_quotes
-    get :index, :id => 1, :q => '"good bye" hello "bye bye"'
-    assert_equal ["good bye", "hello", "bye bye"], assigns(:tokens)
-  end
-
-  def test_results_should_be_escaped_once
-    assert Issue.find(1).update_attributes(:subject => '<subject> escaped_once', :description => '<description> escaped_once')
-    get :index, :q => 'escaped_once'
-    assert_response :success
-    assert_select '#search-results' do
-      assert_select 'dt.issue a', :text => /&lt;subject&gt;/
-      assert_select 'dd', :text => /&lt;description&gt;/
-    end
-  end
-
-  def test_keywords_should_be_highlighted
-    assert Issue.find(1).update_attributes(:subject => 'subject highlighted', :description => 'description highlighted')
-    get :index, :q => 'highlighted'
-    assert_response :success
-    assert_select '#search-results' do
-      assert_select 'dt.issue a span.highlight', :text => 'highlighted'
-      assert_select 'dd span.highlight', :text => 'highlighted'
-    end
-  end
-end
--- a/.svn/pristine/4d/4d32c1bf128521985a7cc66ecfe319a7797f8c8c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class TimeEntry < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  # could have used polymorphic association
-  # project association here allows easy loading of time entries at project level with one database trip
-  belongs_to :project
-  belongs_to :issue
-  belongs_to :user
-  belongs_to :activity, :class_name => 'TimeEntryActivity', :foreign_key => 'activity_id'
-
-  attr_protected :project_id, :user_id, :tyear, :tmonth, :tweek
-
-  acts_as_customizable
-  acts_as_event :title => Proc.new {|o| "#{l_hours(o.hours)} (#{(o.issue || o.project).event_title})"},
-                :url => Proc.new {|o| {:controller => 'timelog', :action => 'index', :project_id => o.project, :issue_id => o.issue}},
-                :author => :user,
-                :group => :issue,
-                :description => :comments
-
-  acts_as_activity_provider :timestamp => "#{table_name}.created_on",
-                            :author_key => :user_id,
-                            :find_options => {:include => :project}
-
-  validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on
-  validates_numericality_of :hours, :allow_nil => true, :message => :invalid
-  validates_length_of :comments, :maximum => 255, :allow_nil => true
-  validates :spent_on, :date => true
-  before_validation :set_project_if_nil
-  validate :validate_time_entry
-
-  scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_time_entries, *args))
-  }
-  scope :on_issue, lambda {|issue|
-    includes(:issue).where("#{Issue.table_name}.root_id = #{issue.root_id} AND #{Issue.table_name}.lft >= #{issue.lft} AND #{Issue.table_name}.rgt <= #{issue.rgt}")
-  }
-  scope :on_project, lambda {|project, include_subprojects|
-    includes(:project).where(project.project_condition(include_subprojects))
-  }
-  scope :spent_between, lambda {|from, to|
-    if from && to
-     where("#{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", from, to)
-    elsif from
-     where("#{TimeEntry.table_name}.spent_on >= ?", from)
-    elsif to
-     where("#{TimeEntry.table_name}.spent_on <= ?", to)
-    else
-     where(nil)
-    end
-  }
-
-  safe_attributes 'hours', 'comments', 'issue_id', 'activity_id', 'spent_on', 'custom_field_values', 'custom_fields'
-
-  def initialize(attributes=nil, *args)
-    super
-    if new_record? && self.activity.nil?
-      if default_activity = TimeEntryActivity.default
-        self.activity_id = default_activity.id
-      end
-      self.hours = nil if hours == 0
-    end
-  end
-
-  def set_project_if_nil
-    self.project = issue.project if issue && project.nil?
-  end
-
-  def validate_time_entry
-    errors.add :hours, :invalid if hours && (hours < 0 || hours >= 1000)
-    errors.add :project_id, :invalid if project.nil?
-    errors.add :issue_id, :invalid if (issue_id && !issue) || (issue && project!=issue.project)
-  end
-
-  def hours=(h)
-    write_attribute :hours, (h.is_a?(String) ? (h.to_hours || h) : h)
-  end
-
-  def hours
-    h = read_attribute(:hours)
-    if h.is_a?(Float)
-      h.round(2)
-    else
-      h
-    end
-  end
-
-  # tyear, tmonth, tweek assigned where setting spent_on attributes
-  # these attributes make time aggregations easier
-  def spent_on=(date)
-    super
-    if spent_on.is_a?(Time)
-      self.spent_on = spent_on.to_date
-    end
-    self.tyear = spent_on ? spent_on.year : nil
-    self.tmonth = spent_on ? spent_on.month : nil
-    self.tweek = spent_on ? Date.civil(spent_on.year, spent_on.month, spent_on.day).cweek : nil
-  end
-
-  # Returns true if the time entry can be edited by usr, otherwise false
-  def editable_by?(usr)
-    (usr == user && usr.allowed_to?(:edit_own_time_entries, project)) || usr.allowed_to?(:edit_time_entries, project)
-  end
-end
--- a/.svn/pristine/4d/4d4d388d3654f2fbefb4fdd7c3e99a9ffa1a3eeb.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class GanttsController < ApplicationController
-  menu_item :gantt
-  before_filter :find_optional_project
-
-  rescue_from Query::StatementInvalid, :with => :query_statement_invalid
-
-  helper :gantt
-  helper :issues
-  helper :projects
-  helper :queries
-  include QueriesHelper
-  helper :sort
-  include SortHelper
-  include Redmine::Export::PDF
-
-  def show
-    @gantt = Redmine::Helpers::Gantt.new(params)
-    @gantt.project = @project
-    retrieve_query
-    @query.group_by = nil
-    @gantt.query = @query if @query.valid?
-
-    basename = (@project ? "#{@project.identifier}-" : '') + 'gantt'
-
-    respond_to do |format|
-      format.html { render :action => "show", :layout => !request.xhr? }
-      format.png  { send_data(@gantt.to_image, :disposition => 'inline', :type => 'image/png', :filename => "#{basename}.png") } if @gantt.respond_to?('to_image')
-      format.pdf  { send_data(@gantt.to_pdf, :type => 'application/pdf', :filename => "#{basename}.pdf") }
-    end
-  end
-end
--- a/.svn/pristine/4d/4dbc763764f2013267075c3f49bdd12a87fc0d1b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'diff'
-require 'enumerator'
-
-class WikiPage < ActiveRecord::Base
-  include Redmine::SafeAttributes
-
-  belongs_to :wiki
-  has_one :content, :class_name => 'WikiContent', :foreign_key => 'page_id', :dependent => :destroy
-  acts_as_attachable :delete_permission => :delete_wiki_pages_attachments
-  acts_as_tree :dependent => :nullify, :order => 'title'
-
-  acts_as_watchable
-  acts_as_event :title => Proc.new {|o| "#{l(:label_wiki)}: #{o.title}"},
-                :description => :text,
-                :datetime => :created_on,
-                :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}}
-
-  acts_as_searchable :columns => ['title', "#{WikiContent.table_name}.text"],
-                     :include => [{:wiki => :project}, :content],
-                     :permission => :view_wiki_pages,
-                     :project_key => "#{Wiki.table_name}.project_id"
-
-  attr_accessor :redirect_existing_links
-
-  validates_presence_of :title
-  validates_format_of :title, :with => /\A[^,\.\/\?\;\|\s]*\z/
-  validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false
-  validates_associated :content
-
-  validate :validate_parent_title
-  before_destroy :remove_redirects
-  before_save    :handle_redirects
-
-  # eager load information about last updates, without loading text
-  scope :with_updated_on, lambda {
-    select("#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on, #{WikiContent.table_name}.version").
-      joins("LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id")
-  }
-
-  # Wiki pages that are protected by default
-  DEFAULT_PROTECTED_PAGES = %w(sidebar)
-
-  safe_attributes 'parent_id', 'parent_title',
-    :if => lambda {|page, user| page.new_record? || user.allowed_to?(:rename_wiki_pages, page.project)}
-
-  def initialize(attributes=nil, *args)
-    super
-    if new_record? && DEFAULT_PROTECTED_PAGES.include?(title.to_s.downcase)
-      self.protected = true
-    end
-  end
-
-  def visible?(user=User.current)
-    !user.nil? && user.allowed_to?(:view_wiki_pages, project)
-  end
-
-  def title=(value)
-    value = Wiki.titleize(value)
-    @previous_title = read_attribute(:title) if @previous_title.blank?
-    write_attribute(:title, value)
-  end
-
-  def handle_redirects
-    self.title = Wiki.titleize(title)
-    # Manage redirects if the title has changed
-    if !@previous_title.blank? && (@previous_title != title) && !new_record?
-      # Update redirects that point to the old title
-      wiki.redirects.find_all_by_redirects_to(@previous_title).each do |r|
-        r.redirects_to = title
-        r.title == r.redirects_to ? r.destroy : r.save
-      end
-      # Remove redirects for the new title
-      wiki.redirects.find_all_by_title(title).each(&:destroy)
-      # Create a redirect to the new title
-      wiki.redirects << WikiRedirect.new(:title => @previous_title, :redirects_to => title) unless redirect_existing_links == "0"
-      @previous_title = nil
-    end
-  end
-
-  def remove_redirects
-    # Remove redirects to this page
-    wiki.redirects.find_all_by_redirects_to(title).each(&:destroy)
-  end
-
-  def pretty_title
-    WikiPage.pretty_title(title)
-  end
-
-  def content_for_version(version=nil)
-    result = content.versions.find_by_version(version.to_i) if version
-    result ||= content
-    result
-  end
-
-  def diff(version_to=nil, version_from=nil)
-    version_to = version_to ? version_to.to_i : self.content.version
-    content_to = content.versions.find_by_version(version_to)
-    content_from = version_from ? content.versions.find_by_version(version_from.to_i) : content_to.try(:previous)
-    return nil unless content_to && content_from
-
-    if content_from.version > content_to.version
-      content_to, content_from = content_from, content_to
-    end
-
-    (content_to && content_from) ? WikiDiff.new(content_to, content_from) : nil
-  end
-
-  def annotate(version=nil)
-    version = version ? version.to_i : self.content.version
-    c = content.versions.find_by_version(version)
-    c ? WikiAnnotate.new(c) : nil
-  end
-
-  def self.pretty_title(str)
-    (str && str.is_a?(String)) ? str.tr('_', ' ') : str
-  end
-
-  def project
-    wiki.project
-  end
-
-  def text
-    content.text if content
-  end
-
-  def updated_on
-    unless @updated_on
-      if time = read_attribute(:updated_on)
-        # content updated_on was eager loaded with the page
-        begin
-          @updated_on = (self.class.default_timezone == :utc ? Time.parse(time.to_s).utc : Time.parse(time.to_s).localtime)
-        rescue
-        end
-      else
-        @updated_on = content && content.updated_on
-      end
-    end
-    @updated_on
-  end
-
-  # Returns true if usr is allowed to edit the page, otherwise false
-  def editable_by?(usr)
-    !protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project)
-  end
-
-  def attachments_deletable?(usr=User.current)
-    editable_by?(usr) && super(usr)
-  end
-
-  def parent_title
-    @parent_title || (self.parent && self.parent.pretty_title)
-  end
-
-  def parent_title=(t)
-    @parent_title = t
-    parent_page = t.blank? ? nil : self.wiki.find_page(t)
-    self.parent = parent_page
-  end
-
-  # Saves the page and its content if text was changed
-  def save_with_content(content)
-    ret = nil
-    transaction do
-      self.content = content
-      if new_record?
-        # Rails automatically saves associated content
-        ret = save
-      else
-        ret = save && (content.text_changed? ? content.save : true)
-      end
-      raise ActiveRecord::Rollback unless ret
-    end
-    ret
-  end
-
-  protected
-
-  def validate_parent_title
-    errors.add(:parent_title, :invalid) if !@parent_title.blank? && parent.nil?
-    errors.add(:parent_title, :circular_dependency) if parent && (parent == self || parent.ancestors.include?(self))
-    errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id)
-  end
-end
-
-class WikiDiff < Redmine::Helpers::Diff
-  attr_reader :content_to, :content_from
-
-  def initialize(content_to, content_from)
-    @content_to = content_to
-    @content_from = content_from
-    super(content_to.text, content_from.text)
-  end
-end
-
-class WikiAnnotate
-  attr_reader :lines, :content
-
-  def initialize(content)
-    @content = content
-    current = content
-    current_lines = current.text.split(/\r?\n/)
-    @lines = current_lines.collect {|t| [nil, nil, t]}
-    positions = []
-    current_lines.size.times {|i| positions << i}
-    while (current.previous)
-      d = current.previous.text.split(/\r?\n/).diff(current.text.split(/\r?\n/)).diffs.flatten
-      d.each_slice(3) do |s|
-        sign, line = s[0], s[1]
-        if sign == '+' && positions[line] && positions[line] != -1
-          if @lines[positions[line]][0].nil?
-            @lines[positions[line]][0] = current.version
-            @lines[positions[line]][1] = current.author
-          end
-        end
-      end
-      d.each_slice(3) do |s|
-        sign, line = s[0], s[1]
-        if sign == '-'
-          positions.insert(line, -1)
-        else
-          positions[line] = nil
-        end
-      end
-      positions.compact!
-      # Stop if every line is annotated
-      break unless @lines.detect { |line| line[0].nil? }
-      current = current.previous
-    end
-    @lines.each { |line|
-      line[0] ||= current.version
-      # if the last known version is > 1 (eg. history was cleared), we don't know the author
-      line[1] ||= current.author if current.version == 1
-    }
-  end
-end
--- a/.svn/pristine/4d/4de18371feb9c1f0e9402b1bd393643194d5f79d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingUsersTest < ActionController::IntegrationTest
-  def test_users
-    assert_routing(
-        { :method => 'get', :path => "/users" },
-        { :controller => 'users', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/users.xml" },
-        { :controller => 'users', :action => 'index', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/users/44" },
-        { :controller => 'users', :action => 'show', :id => '44' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/users/44.xml" },
-        { :controller => 'users', :action => 'show', :id => '44',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/users/current" },
-        { :controller => 'users', :action => 'show', :id => 'current' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/users/current.xml" },
-        { :controller => 'users', :action => 'show', :id => 'current',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/users/new" },
-        { :controller => 'users', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/users/444/edit" },
-        { :controller => 'users', :action => 'edit', :id => '444' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/users" },
-        { :controller => 'users', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/users.xml" },
-        { :controller => 'users', :action => 'create', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/users/444" },
-        { :controller => 'users', :action => 'update', :id => '444' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/users/444.xml" },
-        { :controller => 'users', :action => 'update', :id => '444',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/users/44" },
-        { :controller => 'users', :action => 'destroy', :id => '44' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/users/44.xml" },
-        { :controller => 'users', :action => 'destroy', :id => '44',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/users/123/memberships" },
-        { :controller => 'users', :action => 'edit_membership',
-          :id => '123' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/users/123/memberships/55" },
-        { :controller => 'users', :action => 'edit_membership',
-          :id => '123', :membership_id => '55' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/users/123/memberships/55" },
-        { :controller => 'users', :action => 'destroy_membership',
-          :id => '123', :membership_id => '55' }
-      )
-  end
-end
--- a/.svn/pristine/4f/4f68d76f852340754bcbaa389f8acdaba7e60be4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ProjectEnumerationsControllerTest < ActionController::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :custom_fields, :custom_fields_projects,
-           :custom_fields_trackers, :custom_values,
-           :time_entries
-
-  self.use_transactional_fixtures = false
-
-  def setup
-    @request.session[:user_id] = nil
-    Setting.default_language = 'en'
-  end
-
-  def test_update_to_override_system_activities
-    @request.session[:user_id] = 2 # manager
-    billable_field = TimeEntryActivityCustomField.find_by_name("Billable")
-
-    put :update, :project_id => 1, :enumerations => {
-      "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate
-      "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value
-      "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value
-      "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes
-    }
-
-    assert_response :redirect
-    assert_redirected_to '/projects/ecookbook/settings/activities'
-
-    # Created project specific activities...
-    project = Project.find('ecookbook')
-
-    # ... Design
-    design = project.time_entry_activities.find_by_name("Design")
-    assert design, "Project activity not found"
-
-    assert_equal 9, design.parent_id # Relate to the system activity
-    assert_not_equal design.parent.id, design.id # Different records
-    assert_equal design.parent.name, design.name # Same name
-    assert !design.active?
-
-    # ... Development
-    development = project.time_entry_activities.find_by_name("Development")
-    assert development, "Project activity not found"
-
-    assert_equal 10, development.parent_id # Relate to the system activity
-    assert_not_equal development.parent.id, development.id # Different records
-    assert_equal development.parent.name, development.name # Same name
-    assert development.active?
-    assert_equal "0", development.custom_value_for(billable_field).value
-
-    # ... Inactive Activity
-    previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity")
-    assert previously_inactive, "Project activity not found"
-
-    assert_equal 14, previously_inactive.parent_id # Relate to the system activity
-    assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records
-    assert_equal previously_inactive.parent.name, previously_inactive.name # Same name
-    assert previously_inactive.active?
-    assert_equal "1", previously_inactive.custom_value_for(billable_field).value
-
-    # ... QA
-    assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified"
-  end
-
-  def test_update_will_update_project_specific_activities
-    @request.session[:user_id] = 2 # manager
-
-    project_activity = TimeEntryActivity.new({
-                                               :name => 'Project Specific',
-                                               :parent => TimeEntryActivity.first,
-                                               :project => Project.find(1),
-                                               :active => true
-                                             })
-    assert project_activity.save
-    project_activity_two = TimeEntryActivity.new({
-                                                   :name => 'Project Specific Two',
-                                                   :parent => TimeEntryActivity.last,
-                                                   :project => Project.find(1),
-                                                   :active => true
-                                                 })
-    assert project_activity_two.save
-
-
-    put :update, :project_id => 1, :enumerations => {
-      project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate
-      project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate
-    }
-
-    assert_response :redirect
-    assert_redirected_to '/projects/ecookbook/settings/activities'
-
-    # Created project specific activities...
-    project = Project.find('ecookbook')
-    assert_equal 2, project.time_entry_activities.count
-
-    activity_one = project.time_entry_activities.find_by_name(project_activity.name)
-    assert activity_one, "Project activity not found"
-    assert_equal project_activity.id, activity_one.id
-    assert !activity_one.active?
-
-    activity_two = project.time_entry_activities.find_by_name(project_activity_two.name)
-    assert activity_two, "Project activity not found"
-    assert_equal project_activity_two.id, activity_two.id
-    assert !activity_two.active?
-  end
-
-  def test_update_when_creating_new_activities_will_convert_existing_data
-    assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
-
-    @request.session[:user_id] = 2 # manager
-    put :update, :project_id => 1, :enumerations => {
-      "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate
-    }
-    assert_response :redirect
-
-    # No more TimeEntries using the system activity
-    assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities"
-    # All TimeEntries using project activity
-    project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1)
-    assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(project_specific_activity.id, 1).size, "No Time Entries assigned to the project activity"
-  end
-
-  def test_update_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised
-    # TODO: Need to cause an exception on create but these tests
-    # aren't setup for mocking.  Just create a record now so the
-    # second one is a dupicate
-    parent = TimeEntryActivity.find(9)
-    TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true})
-    TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'})
-
-    assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
-    assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size
-
-    @request.session[:user_id] = 2 # manager
-    put :update, :project_id => 1, :enumerations => {
-      "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design
-      "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value
-    }
-    assert_response :redirect
-
-    # TimeEntries shouldn't have been reassigned on the failed record
-    assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities"
-    # TimeEntries shouldn't have been reassigned on the saved record either
-    assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities"
-  end
-
-  def test_destroy
-    @request.session[:user_id] = 2 # manager
-    project_activity = TimeEntryActivity.new({
-                                               :name => 'Project Specific',
-                                               :parent => TimeEntryActivity.first,
-                                               :project => Project.find(1),
-                                               :active => true
-                                             })
-    assert project_activity.save
-    project_activity_two = TimeEntryActivity.new({
-                                                   :name => 'Project Specific Two',
-                                                   :parent => TimeEntryActivity.last,
-                                                   :project => Project.find(1),
-                                                   :active => true
-                                                 })
-    assert project_activity_two.save
-
-    delete :destroy, :project_id => 1
-    assert_response :redirect
-    assert_redirected_to '/projects/ecookbook/settings/activities'
-
-    assert_nil TimeEntryActivity.find_by_id(project_activity.id)
-    assert_nil TimeEntryActivity.find_by_id(project_activity_two.id)
-  end
-
-  def test_destroy_should_reassign_time_entries_back_to_the_system_activity
-    @request.session[:user_id] = 2 # manager
-    project_activity = TimeEntryActivity.new({
-                                               :name => 'Project Specific Design',
-                                               :parent => TimeEntryActivity.find(9),
-                                               :project => Project.find(1),
-                                               :active => true
-                                             })
-    assert project_activity.save
-    assert TimeEntry.update_all("activity_id = '#{project_activity.id}'", ["project_id = ? AND activity_id = ?", 1, 9])
-    assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size
-
-    delete :destroy, :project_id => 1
-    assert_response :redirect
-    assert_redirected_to '/projects/ecookbook/settings/activities'
-
-    assert_nil TimeEntryActivity.find_by_id(project_activity.id)
-    assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size, "TimeEntries still assigned to project specific activity"
-    assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity"
-  end
-
-end
--- a/.svn/pristine/4f/4f8a45bde853d973a3752802f135b2f9fd445eb5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,870 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class QueryColumn
-  attr_accessor :name, :sortable, :groupable, :default_order
-  include Redmine::I18n
-
-  def initialize(name, options={})
-    self.name = name
-    self.sortable = options[:sortable]
-    self.groupable = options[:groupable] || false
-    if groupable == true
-      self.groupable = name.to_s
-    end
-    self.default_order = options[:default_order]
-    @inline = options.key?(:inline) ? options[:inline] : true
-    @caption_key = options[:caption] || "field_#{name}".to_sym
-    @frozen = options[:frozen]
-  end
-
-  def caption
-    @caption_key.is_a?(Symbol) ? l(@caption_key) : @caption_key
-  end
-
-  # Returns true if the column is sortable, otherwise false
-  def sortable?
-    !@sortable.nil?
-  end
-
-  def sortable
-    @sortable.is_a?(Proc) ? @sortable.call : @sortable
-  end
-
-  def inline?
-    @inline
-  end
-
-  def frozen?
-    @frozen
-  end
-
-  def value(object)
-    object.send name
-  end
-
-  def css_classes
-    name
-  end
-end
-
-class QueryCustomFieldColumn < QueryColumn
-
-  def initialize(custom_field)
-    self.name = "cf_#{custom_field.id}".to_sym
-    self.sortable = custom_field.order_statement || false
-    self.groupable = custom_field.group_statement || false
-    @inline = true
-    @cf = custom_field
-  end
-
-  def caption
-    @cf.name
-  end
-
-  def custom_field
-    @cf
-  end
-
-  def value(object)
-    if custom_field.visible_by?(object.project, User.current)
-      cv = object.custom_values.select {|v| v.custom_field_id == @cf.id}.collect {|v| @cf.cast_value(v.value)}
-      cv.size > 1 ? cv.sort {|a,b| a.to_s <=> b.to_s} : cv.first
-    else
-      nil
-    end
-  end
-
-  def css_classes
-    @css_classes ||= "#{name} #{@cf.field_format}"
-  end
-end
-
-class QueryAssociationCustomFieldColumn < QueryCustomFieldColumn
-
-  def initialize(association, custom_field)
-    super(custom_field)
-    self.name = "#{association}.cf_#{custom_field.id}".to_sym
-    # TODO: support sorting/grouping by association custom field
-    self.sortable = false
-    self.groupable = false
-    @association = association
-  end
-
-  def value(object)
-    if assoc = object.send(@association)
-      super(assoc)
-    end
-  end
-
-  def css_classes
-    @css_classes ||= "#{@association}_cf_#{@cf.id} #{@cf.field_format}"
-  end
-end
-
-class Query < ActiveRecord::Base
-  class StatementInvalid < ::ActiveRecord::StatementInvalid
-  end
-
-  VISIBILITY_PRIVATE = 0
-  VISIBILITY_ROLES   = 1
-  VISIBILITY_PUBLIC  = 2
-
-  belongs_to :project
-  belongs_to :user
-  has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}queries_roles#{table_name_suffix}", :foreign_key => "query_id"
-  serialize :filters
-  serialize :column_names
-  serialize :sort_criteria, Array
-  serialize :options, Hash
-
-  attr_protected :project_id, :user_id
-
-  validates_presence_of :name
-  validates_length_of :name, :maximum => 255
-  validates :visibility, :inclusion => { :in => [VISIBILITY_PUBLIC, VISIBILITY_ROLES, VISIBILITY_PRIVATE] }
-  validate :validate_query_filters
-  validate do |query|
-    errors.add(:base, l(:label_role_plural) + ' ' + l('activerecord.errors.messages.blank')) if query.visibility == VISIBILITY_ROLES && roles.blank?
-  end
-
-  after_save do |query|
-    if query.visibility_changed? && query.visibility != VISIBILITY_ROLES
-	    query.roles.clear
-	  end
-  end
-
-  class_attribute :operators
-  self.operators = {
-    "="   => :label_equals,
-    "!"   => :label_not_equals,
-    "o"   => :label_open_issues,
-    "c"   => :label_closed_issues,
-    "!*"  => :label_none,
-    "*"   => :label_any,
-    ">="  => :label_greater_or_equal,
-    "<="  => :label_less_or_equal,
-    "><"  => :label_between,
-    "<t+" => :label_in_less_than,
-    ">t+" => :label_in_more_than,
-    "><t+"=> :label_in_the_next_days,
-    "t+"  => :label_in,
-    "t"   => :label_today,
-    "ld"  => :label_yesterday,
-    "w"   => :label_this_week,
-    "lw"  => :label_last_week,
-    "l2w" => [:label_last_n_weeks, {:count => 2}],
-    "m"   => :label_this_month,
-    "lm"  => :label_last_month,
-    "y"   => :label_this_year,
-    ">t-" => :label_less_than_ago,
-    "<t-" => :label_more_than_ago,
-    "><t-"=> :label_in_the_past_days,
-    "t-"  => :label_ago,
-    "~"   => :label_contains,
-    "!~"  => :label_not_contains,
-    "=p"  => :label_any_issues_in_project,
-    "=!p" => :label_any_issues_not_in_project,
-    "!p"  => :label_no_issues_in_project
-  }
-
-  class_attribute :operators_by_filter_type
-  self.operators_by_filter_type = {
-    :list => [ "=", "!" ],
-    :list_status => [ "o", "=", "!", "c", "*" ],
-    :list_optional => [ "=", "!", "!*", "*" ],
-    :list_subprojects => [ "*", "!*", "=" ],
-    :date => [ "=", ">=", "<=", "><", "<t+", ">t+", "><t+", "t+", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", ">t-", "<t-", "><t-", "t-", "!*", "*" ],
-    :date_past => [ "=", ">=", "<=", "><", ">t-", "<t-", "><t-", "t-", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "!*", "*" ],
-    :string => [ "=", "~", "!", "!~", "!*", "*" ],
-    :text => [  "~", "!~", "!*", "*" ],
-    :integer => [ "=", ">=", "<=", "><", "!*", "*" ],
-    :float => [ "=", ">=", "<=", "><", "!*", "*" ],
-    :relation => ["=", "=p", "=!p", "!p", "!*", "*"]
-  }
-
-  class_attribute :available_columns
-  self.available_columns = []
-
-  class_attribute :queried_class
-
-  def queried_table_name
-    @queried_table_name ||= self.class.queried_class.table_name
-  end
-
-  def initialize(attributes=nil, *args)
-    super attributes
-    @is_for_all = project.nil?
-  end
-
-  # Builds the query from the given params
-  def build_from_params(params)
-    if params[:fields] || params[:f]
-      self.filters = {}
-      add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v])
-    else
-      available_filters.keys.each do |field|
-        add_short_filter(field, params[field]) if params[field]
-      end
-    end
-    self.group_by = params[:group_by] || (params[:query] && params[:query][:group_by])
-    self.column_names = params[:c] || (params[:query] && params[:query][:column_names])
-    self
-  end
-
-  # Builds a new query from the given params and attributes
-  def self.build_from_params(params, attributes={})
-    new(attributes).build_from_params(params)
-  end
-
-  def validate_query_filters
-    filters.each_key do |field|
-      if values_for(field)
-        case type_for(field)
-        when :integer
-          add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^[+-]?\d+$/) }
-        when :float
-          add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^[+-]?\d+(\.\d*)?$/) }
-        when :date, :date_past
-          case operator_for(field)
-          when "=", ">=", "<=", "><"
-            add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && (!v.match(/^\d{4}-\d{2}-\d{2}$/) || (Date.parse(v) rescue nil).nil?) }
-          when ">t-", "<t-", "t-", ">t+", "<t+", "t+", "><t+", "><t-"
-            add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^\d+$/) }
-          end
-        end
-      end
-
-      add_filter_error(field, :blank) unless
-          # filter requires one or more values
-          (values_for(field) and !values_for(field).first.blank?) or
-          # filter doesn't require any value
-          ["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y"].include? operator_for(field)
-    end if filters
-  end
-
-  def add_filter_error(field, message)
-    m = label_for(field) + " " + l(message, :scope => 'activerecord.errors.messages')
-    errors.add(:base, m)
-  end
-
-  def editable_by?(user)
-    return false unless user
-    # Admin can edit them all and regular users can edit their private queries
-    return true if user.admin? || (is_private? && self.user_id == user.id)
-    # Members can not edit public queries that are for all project (only admin is allowed to)
-    is_public? && !@is_for_all && user.allowed_to?(:manage_public_queries, project)
-  end
-
-  def trackers
-    @trackers ||= project.nil? ? Tracker.sorted.all : project.rolled_up_trackers
-  end
-
-  # Returns a hash of localized labels for all filter operators
-  def self.operators_labels
-    operators.inject({}) {|h, operator| h[operator.first] = l(*operator.last); h}
-  end
-
-  # Returns a representation of the available filters for JSON serialization
-  def available_filters_as_json
-    json = {}
-    available_filters.each do |field, options|
-      json[field] = options.slice(:type, :name, :values).stringify_keys
-    end
-    json
-  end
-
-  def all_projects
-    @all_projects ||= Project.visible.all
-  end
-
-  def all_projects_values
-    return @all_projects_values if @all_projects_values
-
-    values = []
-    Project.project_tree(all_projects) do |p, level|
-      prefix = (level > 0 ? ('--' * level + ' ') : '')
-      values << ["#{prefix}#{p.name}", p.id.to_s]
-    end
-    @all_projects_values = values
-  end
-
-  # Adds available filters
-  def initialize_available_filters
-    # implemented by sub-classes
-  end
-  protected :initialize_available_filters
-
-  # Adds an available filter
-  def add_available_filter(field, options)
-    @available_filters ||= ActiveSupport::OrderedHash.new
-    @available_filters[field] = options
-    @available_filters
-  end
-
-  # Removes an available filter
-  def delete_available_filter(field)
-    if @available_filters
-      @available_filters.delete(field)
-    end
-  end
-
-  # Return a hash of available filters
-  def available_filters
-    unless @available_filters
-      initialize_available_filters
-      @available_filters.each do |field, options|
-        options[:name] ||= l(options[:label] || "field_#{field}".gsub(/_id$/, ''))
-      end
-    end
-    @available_filters
-  end
-
-  def add_filter(field, operator, values=nil)
-    # values must be an array
-    return unless values.nil? || values.is_a?(Array)
-    # check if field is defined as an available filter
-    if available_filters.has_key? field
-      filter_options = available_filters[field]
-      filters[field] = {:operator => operator, :values => (values || [''])}
-    end
-  end
-
-  def add_short_filter(field, expression)
-    return unless expression && available_filters.has_key?(field)
-    field_type = available_filters[field][:type]
-    operators_by_filter_type[field_type].sort.reverse.detect do |operator|
-      next unless expression =~ /^#{Regexp.escape(operator)}(.*)$/
-      values = $1
-      add_filter field, operator, values.present? ? values.split('|') : ['']
-    end || add_filter(field, '=', expression.split('|'))
-  end
-
-  # Add multiple filters using +add_filter+
-  def add_filters(fields, operators, values)
-    if fields.is_a?(Array) && operators.is_a?(Hash) && (values.nil? || values.is_a?(Hash))
-      fields.each do |field|
-        add_filter(field, operators[field], values && values[field])
-      end
-    end
-  end
-
-  def has_filter?(field)
-    filters and filters[field]
-  end
-
-  def type_for(field)
-    available_filters[field][:type] if available_filters.has_key?(field)
-  end
-
-  def operator_for(field)
-    has_filter?(field) ? filters[field][:operator] : nil
-  end
-
-  def values_for(field)
-    has_filter?(field) ? filters[field][:values] : nil
-  end
-
-  def value_for(field, index=0)
-    (values_for(field) || [])[index]
-  end
-
-  def label_for(field)
-    label = available_filters[field][:name] if available_filters.has_key?(field)
-    label ||= l("field_#{field.to_s.gsub(/_id$/, '')}", :default => field)
-  end
-
-  def self.add_available_column(column)
-    self.available_columns << (column) if column.is_a?(QueryColumn)
-  end
-
-  # Returns an array of columns that can be used to group the results
-  def groupable_columns
-    available_columns.select {|c| c.groupable}
-  end
-
-  # Returns a Hash of columns and the key for sorting
-  def sortable_columns
-    available_columns.inject({}) {|h, column|
-      h[column.name.to_s] = column.sortable
-      h
-    }
-  end
-
-  def columns
-    # preserve the column_names order
-    cols = (has_default_columns? ? default_columns_names : column_names).collect do |name|
-       available_columns.find { |col| col.name == name }
-    end.compact
-    available_columns.select(&:frozen?) | cols
-  end
-
-  def inline_columns
-    columns.select(&:inline?)
-  end
-
-  def block_columns
-    columns.reject(&:inline?)
-  end
-
-  def available_inline_columns
-    available_columns.select(&:inline?)
-  end
-
-  def available_block_columns
-    available_columns.reject(&:inline?)
-  end
-
-  def default_columns_names
-    []
-  end
-
-  def column_names=(names)
-    if names
-      names = names.select {|n| n.is_a?(Symbol) || !n.blank? }
-      names = names.collect {|n| n.is_a?(Symbol) ? n : n.to_sym }
-      # Set column_names to nil if default columns
-      if names == default_columns_names
-        names = nil
-      end
-    end
-    write_attribute(:column_names, names)
-  end
-
-  def has_column?(column)
-    column_names && column_names.include?(column.is_a?(QueryColumn) ? column.name : column)
-  end
-
-  def has_custom_field_column?
-    columns.any? {|column| column.is_a? QueryCustomFieldColumn}
-  end
-
-  def has_default_columns?
-    column_names.nil? || column_names.empty?
-  end
-
-  def sort_criteria=(arg)
-    c = []
-    if arg.is_a?(Hash)
-      arg = arg.keys.sort.collect {|k| arg[k]}
-    end
-    c = arg.select {|k,o| !k.to_s.blank?}.slice(0,3).collect {|k,o| [k.to_s, (o == 'desc' || o == false) ? 'desc' : 'asc']}
-    write_attribute(:sort_criteria, c)
-  end
-
-  def sort_criteria
-    read_attribute(:sort_criteria) || []
-  end
-
-  def sort_criteria_key(arg)
-    sort_criteria && sort_criteria[arg] && sort_criteria[arg].first
-  end
-
-  def sort_criteria_order(arg)
-    sort_criteria && sort_criteria[arg] && sort_criteria[arg].last
-  end
-
-  def sort_criteria_order_for(key)
-    sort_criteria.detect {|k, order| key.to_s == k}.try(:last)
-  end
-
-  # Returns the SQL sort order that should be prepended for grouping
-  def group_by_sort_order
-    if grouped? && (column = group_by_column)
-      order = sort_criteria_order_for(column.name) || column.default_order
-      column.sortable.is_a?(Array) ?
-        column.sortable.collect {|s| "#{s} #{order}"}.join(',') :
-        "#{column.sortable} #{order}"
-    end
-  end
-
-  # Returns true if the query is a grouped query
-  def grouped?
-    !group_by_column.nil?
-  end
-
-  def group_by_column
-    groupable_columns.detect {|c| c.groupable && c.name.to_s == group_by}
-  end
-
-  def group_by_statement
-    group_by_column.try(:groupable)
-  end
-
-  def project_statement
-    project_clauses = []
-    if project && !project.descendants.active.empty?
-      ids = [project.id]
-      if has_filter?("subproject_id")
-        case operator_for("subproject_id")
-        when '='
-          # include the selected subprojects
-          ids += values_for("subproject_id").each(&:to_i)
-        when '!*'
-          # main project only
-        else
-          # all subprojects
-          ids += project.descendants.collect(&:id)
-        end
-      elsif Setting.display_subprojects_issues?
-        ids += project.descendants.collect(&:id)
-      end
-      project_clauses << "#{Project.table_name}.id IN (%s)" % ids.join(',')
-    elsif project
-      project_clauses << "#{Project.table_name}.id = %d" % project.id
-    end
-    project_clauses.any? ? project_clauses.join(' AND ') : nil
-  end
-
-  def statement
-    # filters clauses
-    filters_clauses = []
-    filters.each_key do |field|
-      next if field == "subproject_id"
-      v = values_for(field).clone
-      next unless v and !v.empty?
-      operator = operator_for(field)
-
-      # "me" value subsitution
-      if %w(assigned_to_id author_id user_id watcher_id).include?(field)
-        if v.delete("me")
-          if User.current.logged?
-            v.push(User.current.id.to_s)
-            v += User.current.group_ids.map(&:to_s) if field == 'assigned_to_id'
-          else
-            v.push("0")
-          end
-        end
-      end
-
-      if field == 'project_id'
-        if v.delete('mine')
-          v += User.current.memberships.map(&:project_id).map(&:to_s)
-        end
-      end
-
-      if field =~ /cf_(\d+)$/
-        # custom field
-        filters_clauses << sql_for_custom_field(field, operator, v, $1)
-      elsif respond_to?("sql_for_#{field}_field")
-        # specific statement
-        filters_clauses << send("sql_for_#{field}_field", field, operator, v)
-      else
-        # regular field
-        filters_clauses << '(' + sql_for_field(field, operator, v, queried_table_name, field) + ')'
-      end
-    end if filters and valid?
-
-    if (c = group_by_column) && c.is_a?(QueryCustomFieldColumn)
-      # Excludes results for which the grouped custom field is not visible
-      filters_clauses << c.custom_field.visibility_by_project_condition
-    end
-
-    filters_clauses << project_statement
-    filters_clauses.reject!(&:blank?)
-
-    filters_clauses.any? ? filters_clauses.join(' AND ') : nil
-  end
-
-  private
-
-  def sql_for_custom_field(field, operator, value, custom_field_id)
-    db_table = CustomValue.table_name
-    db_field = 'value'
-    filter = @available_filters[field]
-    return nil unless filter
-    if filter[:format] == 'user'
-      if value.delete('me')
-        value.push User.current.id.to_s
-      end
-    end
-    not_in = nil
-    if operator == '!'
-      # Makes ! operator work for custom fields with multiple values
-      operator = '='
-      not_in = 'NOT'
-    end
-    customized_key = "id"
-    customized_class = queried_class
-    if field =~ /^(.+)\.cf_/
-      assoc = $1
-      customized_key = "#{assoc}_id"
-      customized_class = queried_class.reflect_on_association(assoc.to_sym).klass.base_class rescue nil
-      raise "Unknown #{queried_class.name} association #{assoc}" unless customized_class
-    end
-    where = sql_for_field(field, operator, value, db_table, db_field, true)
-    if operator =~ /[<>]/
-      where = "(#{where}) AND #{db_table}.#{db_field} <> ''"
-    end
-    "#{queried_table_name}.#{customized_key} #{not_in} IN (" +
-      "SELECT #{customized_class.table_name}.id FROM #{customized_class.table_name}" +
-      " LEFT OUTER JOIN #{db_table} ON #{db_table}.customized_type='#{customized_class}' AND #{db_table}.customized_id=#{customized_class.table_name}.id AND #{db_table}.custom_field_id=#{custom_field_id}" +
-      " WHERE (#{where}) AND (#{filter[:field].visibility_by_project_condition}))"
-  end
-
-  # Helper method to generate the WHERE sql for a +field+, +operator+ and a +value+
-  def sql_for_field(field, operator, value, db_table, db_field, is_custom_filter=false)
-    sql = ''
-    case operator
-    when "="
-      if value.any?
-        case type_for(field)
-        when :date, :date_past
-          sql = date_clause(db_table, db_field, (Date.parse(value.first) rescue nil), (Date.parse(value.first) rescue nil))
-        when :integer
-          if is_custom_filter
-            sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) = #{value.first.to_i})"
-          else
-            sql = "#{db_table}.#{db_field} = #{value.first.to_i}"
-          end
-        when :float
-          if is_custom_filter
-            sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5})"
-          else
-            sql = "#{db_table}.#{db_field} BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5}"
-          end
-        else
-          sql = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
-        end
-      else
-        # IN an empty set
-        sql = "1=0"
-      end
-    when "!"
-      if value.any?
-        sql = "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))"
-      else
-        # NOT IN an empty set
-        sql = "1=1"
-      end
-    when "!*"
-      sql = "#{db_table}.#{db_field} IS NULL"
-      sql << " OR #{db_table}.#{db_field} = ''" if is_custom_filter
-    when "*"
-      sql = "#{db_table}.#{db_field} IS NOT NULL"
-      sql << " AND #{db_table}.#{db_field} <> ''" if is_custom_filter
-    when ">="
-      if [:date, :date_past].include?(type_for(field))
-        sql = date_clause(db_table, db_field, (Date.parse(value.first) rescue nil), nil)
-      else
-        if is_custom_filter
-          sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) >= #{value.first.to_f})"
-        else
-          sql = "#{db_table}.#{db_field} >= #{value.first.to_f}"
-        end
-      end
-    when "<="
-      if [:date, :date_past].include?(type_for(field))
-        sql = date_clause(db_table, db_field, nil, (Date.parse(value.first) rescue nil))
-      else
-        if is_custom_filter
-          sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) <= #{value.first.to_f})"
-        else
-          sql = "#{db_table}.#{db_field} <= #{value.first.to_f}"
-        end
-      end
-    when "><"
-      if [:date, :date_past].include?(type_for(field))
-        sql = date_clause(db_table, db_field, (Date.parse(value[0]) rescue nil), (Date.parse(value[1]) rescue nil))
-      else
-        if is_custom_filter
-          sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) BETWEEN #{value[0].to_f} AND #{value[1].to_f})"
-        else
-          sql = "#{db_table}.#{db_field} BETWEEN #{value[0].to_f} AND #{value[1].to_f}"
-        end
-      end
-    when "o"
-      sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{connection.quoted_false})" if field == "status_id"
-    when "c"
-      sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{connection.quoted_true})" if field == "status_id"
-    when "><t-"
-      # between today - n days and today
-      sql = relative_date_clause(db_table, db_field, - value.first.to_i, 0)
-    when ">t-"
-      # >= today - n days
-      sql = relative_date_clause(db_table, db_field, - value.first.to_i, nil)
-    when "<t-"
-      # <= today - n days
-      sql = relative_date_clause(db_table, db_field, nil, - value.first.to_i)
-    when "t-"
-      # = n days in past
-      sql = relative_date_clause(db_table, db_field, - value.first.to_i, - value.first.to_i)
-    when "><t+"
-      # between today and today + n days
-      sql = relative_date_clause(db_table, db_field, 0, value.first.to_i)
-    when ">t+"
-      # >= today + n days
-      sql = relative_date_clause(db_table, db_field, value.first.to_i, nil)
-    when "<t+"
-      # <= today + n days
-      sql = relative_date_clause(db_table, db_field, nil, value.first.to_i)
-    when "t+"
-      # = today + n days
-      sql = relative_date_clause(db_table, db_field, value.first.to_i, value.first.to_i)
-    when "t"
-      # = today
-      sql = relative_date_clause(db_table, db_field, 0, 0)
-    when "ld"
-      # = yesterday
-      sql = relative_date_clause(db_table, db_field, -1, -1)
-    when "w"
-      # = this week
-      first_day_of_week = l(:general_first_day_of_week).to_i
-      day_of_week = Date.today.cwday
-      days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
-      sql = relative_date_clause(db_table, db_field, - days_ago, - days_ago + 6)
-    when "lw"
-      # = last week
-      first_day_of_week = l(:general_first_day_of_week).to_i
-      day_of_week = Date.today.cwday
-      days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
-      sql = relative_date_clause(db_table, db_field, - days_ago - 7, - days_ago - 1)
-    when "l2w"
-      # = last 2 weeks
-      first_day_of_week = l(:general_first_day_of_week).to_i
-      day_of_week = Date.today.cwday
-      days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
-      sql = relative_date_clause(db_table, db_field, - days_ago - 14, - days_ago - 1)
-    when "m"
-      # = this month
-      date = Date.today
-      sql = date_clause(db_table, db_field, date.beginning_of_month, date.end_of_month)
-    when "lm"
-      # = last month
-      date = Date.today.prev_month
-      sql = date_clause(db_table, db_field, date.beginning_of_month, date.end_of_month)
-    when "y"
-      # = this year
-      date = Date.today
-      sql = date_clause(db_table, db_field, date.beginning_of_year, date.end_of_year)
-    when "~"
-      sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
-    when "!~"
-      sql = "LOWER(#{db_table}.#{db_field}) NOT LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
-    else
-      raise "Unknown query operator #{operator}"
-    end
-
-    return sql
-  end
-
-  # Adds a filter for the given custom field
-  def add_custom_field_filter(field, assoc=nil)
-    case field.field_format
-    when "text"
-      options = { :type => :text }
-    when "list"
-      options = { :type => :list_optional, :values => field.possible_values }
-    when "date"
-      options = { :type => :date }
-    when "bool"
-      options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]] }
-    when "int"
-      options = { :type => :integer }
-    when "float"
-      options = { :type => :float }
-    when "user", "version"
-      return unless project
-      values = field.possible_values_options(project)
-      if User.current.logged? && field.field_format == 'user'
-        values.unshift ["<< #{l(:label_me)} >>", "me"]
-      end
-      options = { :type => :list_optional, :values => values }
-    else
-      options = { :type => :string }
-    end
-    filter_id = "cf_#{field.id}"
-    filter_name = field.name
-    if assoc.present?
-      filter_id = "#{assoc}.#{filter_id}"
-      filter_name = l("label_attribute_of_#{assoc}", :name => filter_name)
-    end
-    add_available_filter filter_id, options.merge({
-      :name => filter_name,
-      :format => field.field_format,
-      :field => field
-    })
-  end
-
-  # Adds filters for the given custom fields scope
-  def add_custom_fields_filters(scope, assoc=nil)
-    scope.visible.where(:is_filter => true).sorted.each do |field|
-      add_custom_field_filter(field, assoc)
-    end
-  end
-
-  # Adds filters for the given associations custom fields
-  def add_associations_custom_fields_filters(*associations)
-    fields_by_class = CustomField.visible.where(:is_filter => true).group_by(&:class)
-    associations.each do |assoc|
-      association_klass = queried_class.reflect_on_association(assoc).klass
-      fields_by_class.each do |field_class, fields|
-        if field_class.customized_class <= association_klass
-          fields.sort.each do |field|
-            add_custom_field_filter(field, assoc)
-          end
-        end
-      end
-    end
-  end
-
-  # Returns a SQL clause for a date or datetime field.
-  def date_clause(table, field, from, to)
-    s = []
-    if from
-      from_yesterday = from - 1
-      from_yesterday_time = Time.local(from_yesterday.year, from_yesterday.month, from_yesterday.day)
-      if self.class.default_timezone == :utc
-        from_yesterday_time = from_yesterday_time.utc
-      end
-      s << ("#{table}.#{field} > '%s'" % [connection.quoted_date(from_yesterday_time.end_of_day)])
-    end
-    if to
-      to_time = Time.local(to.year, to.month, to.day)
-      if self.class.default_timezone == :utc
-        to_time = to_time.utc
-      end
-      s << ("#{table}.#{field} <= '%s'" % [connection.quoted_date(to_time.end_of_day)])
-    end
-    s.join(' AND ')
-  end
-
-  # Returns a SQL clause for a date or datetime field using relative dates.
-  def relative_date_clause(table, field, days_from, days_to)
-    date_clause(table, field, (days_from ? Date.today + days_from : nil), (days_to ? Date.today + days_to : nil))
-  end
-
-  # Additional joins required for the given sort options
-  def joins_for_order_statement(order_options)
-    joins = []
-
-    if order_options
-      if order_options.include?('authors')
-        joins << "LEFT OUTER JOIN #{User.table_name} authors ON authors.id = #{queried_table_name}.author_id"
-      end
-      order_options.scan(/cf_\d+/).uniq.each do |name|
-        column = available_columns.detect {|c| c.name.to_s == name}
-        join = column && column.custom_field.join_for_order_statement
-        if join
-          joins << join
-        end
-      end
-    end
-
-    joins.any? ? joins.join(' ') : nil
-  end
-end
--- a/.svn/pristine/4f/4fc2ff472415472e5bc5a895e07b22fbca85faf1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class MailHandlerController < ActionController::Base
-  before_filter :check_credential
-
-  # Submits an incoming email to MailHandler
-  def index
-    options = params.dup
-    email = options.delete(:email)
-    if MailHandler.receive(email, options)
-      render :nothing => true, :status => :created
-    else
-      render :nothing => true, :status => :unprocessable_entity
-    end
-  end
-
-  private
-
-  def check_credential
-    User.current = nil
-    unless Setting.mail_handler_api_enabled? && params[:key].to_s == Setting.mail_handler_api_key
-      render :text => 'Access denied. Incoming emails WS is disabled or key is invalid.', :status => 403
-    end
-  end
-end
--- a/.svn/pristine/4f/4fc60931645e3d4832cac83cc1c9d2c25c5df098.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class EnumerationTest < ActiveSupport::TestCase
-  fixtures :enumerations, :issues, :custom_fields, :custom_values
-
-  def test_objects_count
-    # low priority
-    assert_equal 6, Enumeration.find(4).objects_count
-    # urgent
-    assert_equal 0, Enumeration.find(7).objects_count
-  end
-
-  def test_in_use
-    # low priority
-    assert Enumeration.find(4).in_use?
-    # urgent
-    assert !Enumeration.find(7).in_use?
-  end
-
-  def test_default
-    e = Enumeration.default
-    assert e.is_a?(Enumeration)
-    assert e.is_default?
-    assert e.active?
-    assert_equal 'Default Enumeration', e.name
-  end
-
-  def test_default_non_active
-    e = Enumeration.find(12)
-    assert e.is_a?(Enumeration)
-    assert e.is_default?
-    assert e.active?
-    e.update_attributes(:active => false)
-    assert e.is_default?
-    assert !e.active?
-  end
-
-  def test_create
-    e = Enumeration.new(:name => 'Not default', :is_default => false)
-    e.type = 'Enumeration'
-    assert e.save
-    assert_equal 'Default Enumeration', Enumeration.default.name
-  end
-
-  def test_create_as_default
-    e = Enumeration.new(:name => 'Very urgent', :is_default => true)
-    e.type = 'Enumeration'
-    assert e.save
-    assert_equal e, Enumeration.default
-  end
-
-  def test_update_default
-    e = Enumeration.default
-    e.update_attributes(:name => 'Changed', :is_default => true)
-    assert_equal e, Enumeration.default
-  end
-
-  def test_update_default_to_non_default
-    e = Enumeration.default
-    e.update_attributes(:name => 'Changed', :is_default => false)
-    assert_nil Enumeration.default
-  end
-
-  def test_change_default
-    e = Enumeration.find_by_name('Default Enumeration')
-    e.update_attributes(:name => 'Changed Enumeration', :is_default => true)
-    assert_equal e, Enumeration.default
-  end
-
-  def test_destroy_with_reassign
-    Enumeration.find(4).destroy(Enumeration.find(6))
-    assert_nil Issue.where(:priority_id => 4).first
-    assert_equal 6, Enumeration.find(6).objects_count
-  end
-
-  def test_should_be_customizable
-    assert Enumeration.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
-  end
-
-  def test_should_belong_to_a_project
-    association = Enumeration.reflect_on_association(:project)
-    assert association, "No Project association found"
-    assert_equal :belongs_to, association.macro
-  end
-
-  def test_should_act_as_tree
-    enumeration = Enumeration.find(4)
-
-    assert enumeration.respond_to?(:parent)
-    assert enumeration.respond_to?(:children)
-  end
-
-  def test_is_override
-    # Defaults to off
-    enumeration = Enumeration.find(4)
-    assert !enumeration.is_override?
-
-    # Setup as an override
-    enumeration.parent = Enumeration.find(5)
-    assert enumeration.is_override?
-  end
-
-  def test_get_subclasses
-    classes = Enumeration.get_subclasses
-    assert_include IssuePriority, classes
-    assert_include DocumentCategory, classes
-    assert_include TimeEntryActivity, classes
-
-    classes.each do |klass|
-      assert_equal Enumeration, klass.superclass
-    end
-  end
-end
--- a/.svn/pristine/50/50652fe8225e67d65adfd17ea2e35e3021fb4461.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::SafeAttributesTest < ActiveSupport::TestCase
-  fixtures :users
-
-  class Base
-    def attributes=(attrs)
-      attrs.each do |key, value|
-        send("#{key}=", value)
-      end
-    end
-  end
-
-  class Person < Base
-    attr_accessor :firstname, :lastname, :login
-    include Redmine::SafeAttributes
-    safe_attributes :firstname, :lastname
-    safe_attributes :login, :if => lambda {|person, user| user.admin?}
-  end
-
-  class Book < Base
-    attr_accessor :title
-    include Redmine::SafeAttributes
-    safe_attributes :title
-  end
-
-  def test_safe_attribute_names
-    p = Person.new
-    user = User.anonymous
-    assert_equal ['firstname', 'lastname'], p.safe_attribute_names(user)
-    assert p.safe_attribute?('firstname', user)
-    assert !p.safe_attribute?('login', user)
-
-    p = Person.new
-    user = User.find(1)
-    assert_equal ['firstname', 'lastname', 'login'], p.safe_attribute_names(user)
-    assert p.safe_attribute?('firstname', user)
-    assert p.safe_attribute?('login', user)
-  end
-
-  def test_safe_attribute_names_without_user
-    p = Person.new
-    User.current = nil
-    assert_equal ['firstname', 'lastname'], p.safe_attribute_names
-    assert p.safe_attribute?('firstname')
-    assert !p.safe_attribute?('login')
-
-    p = Person.new
-    User.current = User.find(1)
-    assert_equal ['firstname', 'lastname', 'login'], p.safe_attribute_names
-    assert p.safe_attribute?('firstname')
-    assert p.safe_attribute?('login')
-  end
-
-  def test_set_safe_attributes
-    p = Person.new
-    p.send('safe_attributes=', {'firstname' => 'John', 'lastname' => 'Smith', 'login' => 'jsmith'}, User.anonymous)
-    assert_equal 'John', p.firstname
-    assert_equal 'Smith', p.lastname
-    assert_nil p.login
-
-    p = Person.new
-    User.current = User.find(1)
-    p.send('safe_attributes=', {'firstname' => 'John', 'lastname' => 'Smith', 'login' => 'jsmith'}, User.find(1))
-    assert_equal 'John', p.firstname
-    assert_equal 'Smith', p.lastname
-    assert_equal 'jsmith', p.login
-  end
-
-  def test_set_safe_attributes_without_user
-    p = Person.new
-    User.current = nil
-    p.safe_attributes = {'firstname' => 'John', 'lastname' => 'Smith', 'login' => 'jsmith'}
-    assert_equal 'John', p.firstname
-    assert_equal 'Smith', p.lastname
-    assert_nil p.login
-
-    p = Person.new
-    User.current = User.find(1)
-    p.safe_attributes = {'firstname' => 'John', 'lastname' => 'Smith', 'login' => 'jsmith'}
-    assert_equal 'John', p.firstname
-    assert_equal 'Smith', p.lastname
-    assert_equal 'jsmith', p.login
-  end
-end
--- a/.svn/pristine/51/514f8aeb54e3381fa2badbe487c0d7fd6bad2fd0.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueCategoriesControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules, :issue_categories,
-           :issues
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 2
-  end
-
-  def test_new
-    @request.session[:user_id] = 2 # manager
-    get :new, :project_id => '1'
-    assert_response :success
-    assert_template 'new'
-    assert_select 'input[name=?]', 'issue_category[name]'
-  end
-
-  def test_new_from_issue_form
-    @request.session[:user_id] = 2 # manager
-    xhr :get, :new, :project_id => '1'
-
-    assert_response :success
-    assert_template 'new'
-    assert_equal 'text/javascript', response.content_type
-  end
-
-  def test_create
-    @request.session[:user_id] = 2 # manager
-    assert_difference 'IssueCategory.count' do
-      post :create, :project_id => '1', :issue_category => {:name => 'New category'}
-    end
-    assert_redirected_to '/projects/ecookbook/settings/categories'
-    category = IssueCategory.find_by_name('New category')
-    assert_not_nil category
-    assert_equal 1, category.project_id
-  end
-
-  def test_create_failure
-    @request.session[:user_id] = 2
-    post :create, :project_id => '1', :issue_category => {:name => ''}
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_create_from_issue_form
-    @request.session[:user_id] = 2 # manager
-    assert_difference 'IssueCategory.count' do
-      xhr :post, :create, :project_id => '1', :issue_category => {:name => 'New category'}
-    end
-    category = IssueCategory.first(:order => 'id DESC')
-    assert_equal 'New category', category.name
-
-    assert_response :success
-    assert_template 'create'
-    assert_equal 'text/javascript', response.content_type
-  end
-
-  def test_create_from_issue_form_with_failure
-    @request.session[:user_id] = 2 # manager
-    assert_no_difference 'IssueCategory.count' do
-      xhr :post, :create, :project_id => '1', :issue_category => {:name => ''}
-    end
-
-    assert_response :success
-    assert_template 'new'
-    assert_equal 'text/javascript', response.content_type
-  end
-
-  def test_edit
-    @request.session[:user_id] = 2
-    get :edit, :id => 2
-    assert_response :success
-    assert_template 'edit'
-    assert_select 'input[name=?][value=?]', 'issue_category[name]', 'Recipes'
-  end
-
-  def test_update
-    assert_no_difference 'IssueCategory.count' do
-      put :update, :id => 2, :issue_category => { :name => 'Testing' }
-    end
-    assert_redirected_to '/projects/ecookbook/settings/categories'
-    assert_equal 'Testing', IssueCategory.find(2).name
-  end
-
-  def test_update_failure
-    put :update, :id => 2, :issue_category => { :name => '' }
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_update_not_found
-    put :update, :id => 97, :issue_category => { :name => 'Testing' }
-    assert_response 404
-  end
-
-  def test_destroy_category_not_in_use
-    delete :destroy, :id => 2
-    assert_redirected_to '/projects/ecookbook/settings/categories'
-    assert_nil IssueCategory.find_by_id(2)
-  end
-
-  def test_destroy_category_in_use
-    delete :destroy, :id => 1
-    assert_response :success
-    assert_template 'destroy'
-    assert_not_nil IssueCategory.find_by_id(1)
-  end
-
-  def test_destroy_category_in_use_with_reassignment
-    issue = Issue.where(:category_id => 1).first
-    delete :destroy, :id => 1, :todo => 'reassign', :reassign_to_id => 2
-    assert_redirected_to '/projects/ecookbook/settings/categories'
-    assert_nil IssueCategory.find_by_id(1)
-    # check that the issue was reassign
-    assert_equal 2, issue.reload.category_id
-  end
-
-  def test_destroy_category_in_use_without_reassignment
-    issue = Issue.where(:category_id => 1).first
-    delete :destroy, :id => 1, :todo => 'nullify'
-    assert_redirected_to '/projects/ecookbook/settings/categories'
-    assert_nil IssueCategory.find_by_id(1)
-    # check that the issue category was nullified
-    assert_nil issue.reload.category_id
-  end
-end
--- a/.svn/pristine/53/539b469592377fe5ec04bc7018cfe2f6bf2322bc.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingIssuesTest < ActionController::IntegrationTest
-  def test_issues_rest_actions
-    assert_routing(
-        { :method => 'get', :path => "/issues" },
-        { :controller => 'issues', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues.pdf" },
-        { :controller => 'issues', :action => 'index', :format => 'pdf' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues.atom" },
-        { :controller => 'issues', :action => 'index', :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues.xml" },
-        { :controller => 'issues', :action => 'index', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/64" },
-        { :controller => 'issues', :action => 'show', :id => '64' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/64.pdf" },
-        { :controller => 'issues', :action => 'show', :id => '64',
-          :format => 'pdf' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/64.atom" },
-        { :controller => 'issues', :action => 'show', :id => '64',
-          :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/64.xml" },
-        { :controller => 'issues', :action => 'show', :id => '64',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issues.xml" },
-        { :controller => 'issues', :action => 'create', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/64/edit" },
-        { :controller => 'issues', :action => 'edit', :id => '64' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/issues/1.xml" },
-        { :controller => 'issues', :action => 'update', :id => '1',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/issues/1.xml" },
-        { :controller => 'issues', :action => 'destroy', :id => '1',
-          :format => 'xml' }
-      )
-  end
-
-  def test_issues_rest_actions_scoped_under_project
-    assert_routing(
-        { :method => 'get', :path => "/projects/23/issues" },
-        { :controller => 'issues', :action => 'index', :project_id => '23' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/23/issues.pdf" },
-        { :controller => 'issues', :action => 'index', :project_id => '23',
-          :format => 'pdf' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/23/issues.atom" },
-        { :controller => 'issues', :action => 'index', :project_id => '23',
-          :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/23/issues.xml" },
-        { :controller => 'issues', :action => 'index', :project_id => '23',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/23/issues" },
-        { :controller => 'issues', :action => 'create', :project_id => '23' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/23/issues/new" },
-        { :controller => 'issues', :action => 'new', :project_id => '23' }
-      )
-  end
-
-  def test_issues_form_update
-    ["post", "put"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/projects/23/issues/update_form" },
-          { :controller => 'issues', :action => 'update_form', :project_id => '23' }
-        )
-    end
-  end
-
-  def test_issues_extra_actions
-    assert_routing(
-        { :method => 'get', :path => "/projects/23/issues/64/copy" },
-        { :controller => 'issues', :action => 'new', :project_id => '23',
-          :copy_from => '64' }
-      )
-    # For updating the bulk edit form
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/issues/bulk_edit" },
-          { :controller => 'issues', :action => 'bulk_edit' }
-        )
-    end
-    assert_routing(
-        { :method => 'post', :path => "/issues/bulk_update" },
-        { :controller => 'issues', :action => 'bulk_update' }
-      )
-  end
-end
--- a/.svn/pristine/53/53a436ecc8b372b3e21fc3c743b6fa4cc9e4b865.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,535 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ChangesetTest < ActiveSupport::TestCase
-  fixtures :projects, :repositories,
-           :issues, :issue_statuses, :issue_categories,
-           :changesets, :changes,
-           :enumerations,
-           :custom_fields, :custom_values,
-           :users, :members, :member_roles, :trackers,
-           :enabled_modules, :roles
-
-  def test_ref_keywords_any
-    ActionMailer::Base.deliveries.clear
-    Setting.commit_ref_keywords = '*'
-    Setting.commit_update_keywords = [{'keywords' => 'fixes , closes', 'status_id' => '5', 'done_ratio' => '90'}]
-
-    c = Changeset.new(:repository   => Project.find(1).repository,
-                      :committed_on => Time.now,
-                      :comments     => 'New commit (#2). Fixes #1',
-                      :revision     => '12345')
-    assert c.save
-    assert_equal [1, 2], c.issue_ids.sort
-    fixed = Issue.find(1)
-    assert fixed.closed?
-    assert_equal 90, fixed.done_ratio
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_ref_keywords
-    Setting.commit_ref_keywords = 'refs'
-    Setting.commit_update_keywords = ''
-    c = Changeset.new(:repository   => Project.find(1).repository,
-                      :committed_on => Time.now,
-                      :comments     => 'Ignores #2. Refs #1',
-                      :revision     => '12345')
-    assert c.save
-    assert_equal [1], c.issue_ids.sort
-  end
-
-  def test_ref_keywords_any_only
-    Setting.commit_ref_keywords = '*'
-    Setting.commit_update_keywords = ''
-    c = Changeset.new(:repository   => Project.find(1).repository,
-                      :committed_on => Time.now,
-                      :comments     => 'Ignores #2. Refs #1',
-                      :revision     => '12345')
-    assert c.save
-    assert_equal [1, 2], c.issue_ids.sort
-  end
-
-  def test_ref_keywords_any_with_timelog
-    Setting.commit_ref_keywords = '*'
-    Setting.commit_logtime_enabled = '1'
-
-    {
-      '2' => 2.0,
-      '2h' => 2.0,
-      '2hours' => 2.0,
-      '15m' => 0.25,
-      '15min' => 0.25,
-      '3h15' => 3.25,
-      '3h15m' => 3.25,
-      '3h15min' => 3.25,
-      '3:15' => 3.25,
-      '3.25' => 3.25,
-      '3.25h' => 3.25,
-      '3,25' => 3.25,
-      '3,25h' => 3.25,
-    }.each do |syntax, expected_hours|
-      c = Changeset.new(:repository   => Project.find(1).repository,
-                        :committed_on => 24.hours.ago,
-                        :comments     => "Worked on this issue #1 @#{syntax}",
-                        :revision     => '520',
-                        :user         => User.find(2))
-      assert_difference 'TimeEntry.count' do
-        c.scan_comment_for_issue_ids
-      end
-      assert_equal [1], c.issue_ids.sort
-
-      time = TimeEntry.first(:order => 'id desc')
-      assert_equal 1, time.issue_id
-      assert_equal 1, time.project_id
-      assert_equal 2, time.user_id
-      assert_equal expected_hours, time.hours,
-          "@#{syntax} should be logged as #{expected_hours} hours but was #{time.hours}"
-      assert_equal Date.yesterday, time.spent_on
-      assert time.activity.is_default?
-      assert time.comments.include?('r520'),
-            "r520 was expected in time_entry comments: #{time.comments}"
-    end
-  end
-
-  def test_ref_keywords_closing_with_timelog
-    Setting.commit_ref_keywords = '*'
-    Setting.commit_update_keywords = [{'keywords' => 'fixes , closes', 'status_id' => IssueStatus.where(:is_closed => true).first.id.to_s}]
-    Setting.commit_logtime_enabled = '1'
-
-    c = Changeset.new(:repository   => Project.find(1).repository,
-                      :committed_on => Time.now,
-                      :comments     => 'This is a comment. Fixes #1 @4.5, #2 @1',
-                      :user         => User.find(2))
-    assert_difference 'TimeEntry.count', 2 do
-      c.scan_comment_for_issue_ids
-    end
-
-    assert_equal [1, 2], c.issue_ids.sort
-    assert Issue.find(1).closed?
-    assert Issue.find(2).closed?
-
-    times = TimeEntry.all(:order => 'id desc', :limit => 2)
-    assert_equal [1, 2], times.collect(&:issue_id).sort
-  end
-
-  def test_ref_keywords_any_line_start
-    Setting.commit_ref_keywords = '*'
-    c = Changeset.new(:repository   => Project.find(1).repository,
-                      :committed_on => Time.now,
-                      :comments     => '#1 is the reason of this commit',
-                      :revision     => '12345')
-    assert c.save
-    assert_equal [1], c.issue_ids.sort
-  end
-
-  def test_ref_keywords_allow_brackets_around_a_issue_number
-    Setting.commit_ref_keywords = '*'
-    c = Changeset.new(:repository   => Project.find(1).repository,
-                      :committed_on => Time.now,
-                      :comments     => '[#1] Worked on this issue',
-                      :revision     => '12345')
-    assert c.save
-    assert_equal [1], c.issue_ids.sort
-  end
-
-  def test_ref_keywords_allow_brackets_around_multiple_issue_numbers
-    Setting.commit_ref_keywords = '*'
-    c = Changeset.new(:repository   => Project.find(1).repository,
-                      :committed_on => Time.now,
-                      :comments     => '[#1 #2, #3] Worked on these',
-                      :revision     => '12345')
-    assert c.save
-    assert_equal [1,2,3], c.issue_ids.sort
-  end
-
-  def test_update_keywords_with_multiple_rules
-    with_settings :commit_update_keywords => [
-      {'keywords' => 'fixes, closes', 'status_id' => '5'},
-      {'keywords' => 'resolves', 'status_id' => '3'}
-    ] do
-
-      issue1 = Issue.generate!
-      issue2 = Issue.generate!
-      Changeset.generate!(:comments => "Closes ##{issue1.id}\nResolves ##{issue2.id}")
-      assert_equal 5, issue1.reload.status_id
-      assert_equal 3, issue2.reload.status_id
-    end
-  end
-
-  def test_update_keywords_with_multiple_rules_should_match_tracker
-    with_settings :commit_update_keywords => [
-      {'keywords' => 'fixes', 'status_id' => '5', 'if_tracker_id' => '2'},
-      {'keywords' => 'fixes', 'status_id' => '3', 'if_tracker_id' => ''}
-    ] do
-
-      issue1 = Issue.generate!(:tracker_id => 2)
-      issue2 = Issue.generate!
-      Changeset.generate!(:comments => "Fixes ##{issue1.id}, ##{issue2.id}")
-      assert_equal 5, issue1.reload.status_id
-      assert_equal 3, issue2.reload.status_id
-    end
-  end
-
-  def test_update_keywords_with_multiple_rules_and_no_match
-    with_settings :commit_update_keywords => [
-      {'keywords' => 'fixes', 'status_id' => '5', 'if_tracker_id' => '2'},
-      {'keywords' => 'fixes', 'status_id' => '3', 'if_tracker_id' => '3'}
-    ] do
-
-      issue1 = Issue.generate!(:tracker_id => 2)
-      issue2 = Issue.generate!
-      Changeset.generate!(:comments => "Fixes ##{issue1.id}, ##{issue2.id}")
-      assert_equal 5, issue1.reload.status_id
-      assert_equal 1, issue2.reload.status_id # no updates
-    end
-  end
-
-  def test_commit_referencing_a_subproject_issue
-    c = Changeset.new(:repository   => Project.find(1).repository,
-                      :committed_on => Time.now,
-                      :comments     => 'refs #5, a subproject issue',
-                      :revision     => '12345')
-    assert c.save
-    assert_equal [5], c.issue_ids.sort
-    assert c.issues.first.project != c.project
-  end
-
-  def test_commit_closing_a_subproject_issue
-    with_settings :commit_update_keywords => [{'keywords' => 'closes', 'status_id' => '5'}],
-                  :default_language => 'en' do
-      issue = Issue.find(5)
-      assert !issue.closed?
-      assert_difference 'Journal.count' do
-        c = Changeset.new(:repository   => Project.find(1).repository,
-                          :committed_on => Time.now,
-                          :comments     => 'closes #5, a subproject issue',
-                          :revision     => '12345')
-        assert c.save
-      end
-      assert issue.reload.closed?
-      journal = Journal.first(:order => 'id DESC')
-      assert_equal issue, journal.issue
-      assert_include "Applied in changeset ecookbook:r12345.", journal.notes
-    end
-  end
-
-  def test_commit_referencing_a_parent_project_issue
-    # repository of child project
-    r = Repository::Subversion.create!(
-          :project => Project.find(3),
-          :url     => 'svn://localhost/test')
-    c = Changeset.new(:repository   => r,
-                      :committed_on => Time.now,
-                      :comments     => 'refs #2, an issue of a parent project',
-                      :revision     => '12345')
-    assert c.save
-    assert_equal [2], c.issue_ids.sort
-    assert c.issues.first.project != c.project
-  end
-
-  def test_commit_referencing_a_project_with_commit_cross_project_ref_disabled
-    r = Repository::Subversion.create!(
-          :project => Project.find(3),
-          :url     => 'svn://localhost/test')
-          
-    with_settings :commit_cross_project_ref => '0' do
-      c = Changeset.new(:repository   => r,
-                        :committed_on => Time.now,
-                        :comments     => 'refs #4, an issue of a different project',
-                        :revision     => '12345')
-      assert c.save
-      assert_equal [], c.issue_ids
-    end
-  end
-
-  def test_commit_referencing_a_project_with_commit_cross_project_ref_enabled
-    r = Repository::Subversion.create!(
-          :project => Project.find(3),
-          :url     => 'svn://localhost/test')
-          
-    with_settings :commit_cross_project_ref => '1' do
-      c = Changeset.new(:repository   => r,
-                        :committed_on => Time.now,
-                        :comments     => 'refs #4, an issue of a different project',
-                        :revision     => '12345')
-      assert c.save
-      assert_equal [4], c.issue_ids
-    end
-  end
-
-  def test_old_commits_should_not_update_issues_nor_log_time
-    Setting.commit_ref_keywords = '*'
-    Setting.commit_update_keywords = {'fixes , closes' => {'status_id' => '5', 'done_ratio' => '90'}}
-    Setting.commit_logtime_enabled = '1'
-
-    repository = Project.find(1).repository
-    repository.created_on = Time.now
-    repository.save!
-
-    c = Changeset.new(:repository   => repository,
-                      :committed_on => 1.month.ago,
-                      :comments     => 'New commit (#2). Fixes #1 @1h',
-                      :revision     => '12345')
-    assert_no_difference 'TimeEntry.count' do
-      assert c.save
-    end
-    assert_equal [1, 2], c.issue_ids.sort
-    issue = Issue.find(1)
-    assert_equal 1, issue.status_id
-    assert_equal 0, issue.done_ratio
-  end
-
-  def test_text_tag_revision
-    c = Changeset.new(:revision => '520')
-    assert_equal 'r520', c.text_tag
-  end
-
-  def test_text_tag_revision_with_same_project
-    c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
-    assert_equal 'r520', c.text_tag(Project.find(1))
-  end
-
-  def test_text_tag_revision_with_different_project
-    c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
-    assert_equal 'ecookbook:r520', c.text_tag(Project.find(2))
-  end
-
-  def test_text_tag_revision_with_repository_identifier
-    r = Repository::Subversion.create!(
-          :project_id => 1,
-          :url     => 'svn://localhost/test',
-          :identifier => 'documents')
-    
-    c = Changeset.new(:revision => '520', :repository => r)
-    assert_equal 'documents|r520', c.text_tag
-    assert_equal 'ecookbook:documents|r520', c.text_tag(Project.find(2))
-  end
-
-  def test_text_tag_hash
-    c = Changeset.new(
-          :scmid    => '7234cb2750b63f47bff735edc50a1c0a433c2518',
-          :revision => '7234cb2750b63f47bff735edc50a1c0a433c2518')
-    assert_equal 'commit:7234cb2750b63f47bff735edc50a1c0a433c2518', c.text_tag
-  end
-
-  def test_text_tag_hash_with_same_project
-    c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
-    assert_equal 'commit:7234cb27', c.text_tag(Project.find(1))
-  end
-
-  def test_text_tag_hash_with_different_project
-    c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
-    assert_equal 'ecookbook:commit:7234cb27', c.text_tag(Project.find(2))
-  end
-
-  def test_text_tag_hash_all_number
-    c = Changeset.new(:scmid => '0123456789', :revision => '0123456789')
-    assert_equal 'commit:0123456789', c.text_tag
-  end
-
-  def test_previous
-    changeset = Changeset.find_by_revision('3')
-    assert_equal Changeset.find_by_revision('2'), changeset.previous
-  end
-
-  def test_previous_nil
-    changeset = Changeset.find_by_revision('1')
-    assert_nil changeset.previous
-  end
-
-  def test_next
-    changeset = Changeset.find_by_revision('2')
-    assert_equal Changeset.find_by_revision('3'), changeset.next
-  end
-
-  def test_next_nil
-    changeset = Changeset.find_by_revision('10')
-    assert_nil changeset.next
-  end
-
-  def test_comments_should_be_converted_to_utf8
-    proj = Project.find(3)
-    # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
-    str = "Texte encod\xe9 en ISO-8859-1."
-    str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
-    r = Repository::Bazaar.create!(
-            :project      => proj,
-            :url          => '/tmp/test/bazaar',
-            :log_encoding => 'ISO-8859-1' )
-    assert r
-    c = Changeset.new(:repository   => r,
-                      :committed_on => Time.now,
-                      :revision     => '123',
-                      :scmid        => '12345',
-                      :comments     => str)
-    assert( c.save )
-    str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1."
-    str_utf8.force_encoding("UTF-8") if str_utf8.respond_to?(:force_encoding)
-    assert_equal str_utf8, c.comments
-  end
-
-  def test_invalid_utf8_sequences_in_comments_should_be_replaced_latin1
-    proj = Project.find(3)
-    # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
-    str1 = "Texte encod\xe9 en ISO-8859-1."
-    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
-    str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
-    r = Repository::Bazaar.create!(
-            :project      => proj,
-            :url          => '/tmp/test/bazaar',
-            :log_encoding => 'UTF-8' )
-    assert r
-    c = Changeset.new(:repository   => r,
-                      :committed_on => Time.now,
-                      :revision     => '123',
-                      :scmid        => '12345',
-                      :comments     => str1,
-                      :committer    => str2)
-    assert( c.save )
-    assert_equal "Texte encod? en ISO-8859-1.", c.comments
-    assert_equal "?a?b?c?d?e test", c.committer
-  end
-
-  def test_invalid_utf8_sequences_in_comments_should_be_replaced_ja_jis
-    proj = Project.find(3)
-    str = "test\xb5\xfetest\xb5\xfe"
-    if str.respond_to?(:force_encoding)
-      str.force_encoding('ASCII-8BIT')
-    end
-    r = Repository::Bazaar.create!(
-            :project      => proj,
-            :url          => '/tmp/test/bazaar',
-            :log_encoding => 'ISO-2022-JP' )
-    assert r
-    c = Changeset.new(:repository   => r,
-                      :committed_on => Time.now,
-                      :revision     => '123',
-                      :scmid        => '12345',
-                      :comments     => str)
-    assert( c.save )
-    assert_equal "test??test??", c.comments
-  end
-
-  def test_comments_should_be_converted_all_latin1_to_utf8
-    s1 = "\xC2\x80"
-    s2 = "\xc3\x82\xc2\x80"
-    s4 = s2.dup
-    if s1.respond_to?(:force_encoding)
-      s3 = s1.dup
-      s1.force_encoding('ASCII-8BIT')
-      s2.force_encoding('ASCII-8BIT')
-      s3.force_encoding('ISO-8859-1')
-      s4.force_encoding('UTF-8')
-      assert_equal s3.encode('UTF-8'), s4
-    end
-    proj = Project.find(3)
-    r = Repository::Bazaar.create!(
-            :project      => proj,
-            :url          => '/tmp/test/bazaar',
-            :log_encoding => 'ISO-8859-1' )
-    assert r
-    c = Changeset.new(:repository   => r,
-                      :committed_on => Time.now,
-                      :revision     => '123',
-                      :scmid        => '12345',
-                      :comments     => s1)
-    assert( c.save )
-    assert_equal s4, c.comments
-  end
-
-  def test_invalid_utf8_sequences_in_paths_should_be_replaced
-    proj = Project.find(3)
-    str1 = "Texte encod\xe9 en ISO-8859-1"
-    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
-    str1.force_encoding("UTF-8")      if str1.respond_to?(:force_encoding)
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
-    r = Repository::Bazaar.create!(
-            :project => proj,
-            :url => '/tmp/test/bazaar',
-            :log_encoding => 'UTF-8' )
-    assert r
-    cs = Changeset.new(
-               :repository   => r,
-               :committed_on => Time.now,
-               :revision     => '123',
-               :scmid        => '12345',
-               :comments     => "test")
-    assert(cs.save)
-    ch = Change.new(
-                  :changeset     => cs,
-                  :action        => "A",
-                  :path          => str1,
-                  :from_path     => str2,
-                  :from_revision => "345")
-    assert(ch.save)
-    assert_equal "Texte encod? en ISO-8859-1", ch.path
-    assert_equal "?a?b?c?d?e test", ch.from_path
-  end
-
-  def test_comments_nil
-    proj = Project.find(3)
-    r = Repository::Bazaar.create!(
-            :project      => proj,
-            :url          => '/tmp/test/bazaar',
-            :log_encoding => 'ISO-8859-1' )
-    assert r
-    c = Changeset.new(:repository   => r,
-                      :committed_on => Time.now,
-                      :revision     => '123',
-                      :scmid        => '12345',
-                      :comments     => nil,
-                      :committer    => nil)
-    assert( c.save )
-    assert_equal "", c.comments
-    assert_equal nil, c.committer
-    if c.comments.respond_to?(:force_encoding)
-      assert_equal "UTF-8", c.comments.encoding.to_s
-    end
-  end
-
-  def test_comments_empty
-    proj = Project.find(3)
-    r = Repository::Bazaar.create!(
-            :project      => proj,
-            :url          => '/tmp/test/bazaar',
-            :log_encoding => 'ISO-8859-1' )
-    assert r
-    c = Changeset.new(:repository   => r,
-                      :committed_on => Time.now,
-                      :revision     => '123',
-                      :scmid        => '12345',
-                      :comments     => "",
-                      :committer    => "")
-    assert( c.save )
-    assert_equal "", c.comments
-    assert_equal "", c.committer
-    if c.comments.respond_to?(:force_encoding)
-      assert_equal "UTF-8", c.comments.encoding.to_s
-      assert_equal "UTF-8", c.committer.encoding.to_s
-    end
-  end
-
-  def test_identifier
-    c = Changeset.find_by_revision('1')
-    assert_equal c.revision, c.identifier
-  end
-end
--- a/.svn/pristine/53/53a91881211d028f264cd0f5ef639191d1262e38.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::AccessControlTest < ActiveSupport::TestCase
-
-  def setup
-    @access_module = Redmine::AccessControl
-  end
-
-  def test_permissions
-    perms = @access_module.permissions
-    assert perms.is_a?(Array)
-    assert perms.first.is_a?(Redmine::AccessControl::Permission)
-  end
-
-  def test_module_permission
-    perm = @access_module.permission(:view_issues)
-    assert perm.is_a?(Redmine::AccessControl::Permission)
-    assert_equal :view_issues, perm.name
-    assert_equal :issue_tracking, perm.project_module
-    assert perm.actions.is_a?(Array)
-    assert perm.actions.include?('issues/index')
-  end
-
-  def test_no_module_permission
-    perm = @access_module.permission(:edit_project)
-    assert perm.is_a?(Redmine::AccessControl::Permission)
-    assert_equal :edit_project, perm.name
-    assert_nil perm.project_module
-    assert perm.actions.is_a?(Array)
-    assert perm.actions.include?('projects/settings')
-  end
-
-  def test_read_action_should_return_true_for_read_actions
-    assert_equal true, @access_module.read_action?(:view_project)
-    assert_equal true, @access_module.read_action?(:controller => 'projects', :action => 'show')
-  end
-
-  def test_read_action_should_return_false_for_update_actions
-    assert_equal false, @access_module.read_action?(:edit_project)
-    assert_equal false, @access_module.read_action?(:controller => 'projects', :action => 'edit')
-  end
-end
--- a/.svn/pristine/53/53be7ecb5340425e02b87b5afa5c2fd05785f736.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::VersionsTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :versions
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /projects/:project_id/versions.xml should return project versions" do
-    get '/projects/1/versions.xml'
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'versions',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'version',
-        :child => {
-          :tag => 'id',
-          :content => '2',
-          :sibling => {
-            :tag => 'name',
-            :content => '1.0'
-          }
-        }
-      }
-  end
-
-  test "POST /projects/:project_id/versions.xml should create the version" do
-    assert_difference 'Version.count' do
-      post '/projects/1/versions.xml', {:version => {:name => 'API test'}}, credentials('jsmith')
-    end
-
-    version = Version.first(:order => 'id DESC')
-    assert_equal 'API test', version.name
-
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'version', :child => {:tag => 'id', :content => version.id.to_s}
-  end
-
-  test "POST /projects/:project_id/versions.xml should create the version with due date" do
-    assert_difference 'Version.count' do
-      post '/projects/1/versions.xml', {:version => {:name => 'API test', :due_date => '2012-01-24'}}, credentials('jsmith')
-    end
-
-    version = Version.first(:order => 'id DESC')
-    assert_equal 'API test', version.name
-    assert_equal Date.parse('2012-01-24'), version.due_date
-
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'version', :child => {:tag => 'id', :content => version.id.to_s}
-  end
-
-  test "POST /projects/:project_id/versions.xml should create the version with custom fields" do
-    field = VersionCustomField.generate!
-
-    assert_difference 'Version.count' do
-      post '/projects/1/versions.xml', {
-          :version => {
-            :name => 'API test',
-            :custom_fields => [
-              {'id' => field.id.to_s, 'value' => 'Some value'}
-            ]
-          }
-        }, credentials('jsmith')
-    end
-
-    version = Version.first(:order => 'id DESC')
-    assert_equal 'API test', version.name
-    assert_equal 'Some value', version.custom_field_value(field)
-
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-    assert_select 'version>custom_fields>custom_field[id=?]>value', field.id.to_s, 'Some value'
-  end
-
-  test "POST /projects/:project_id/versions.xml with failure should return the errors" do
-    assert_no_difference('Version.count') do
-      post '/projects/1/versions.xml', {:version => {:name => ''}}, credentials('jsmith')
-    end
-
-    assert_response :unprocessable_entity
-    assert_tag :errors, :child => {:tag => 'error', :content => "Name can't be blank"}
-  end
-
-  test "GET /versions/:id.xml should return the version" do
-    get '/versions/2.xml'
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_select 'version' do
-      assert_select 'id', :text => '2'
-      assert_select 'name', :text => '1.0'
-      assert_select 'sharing', :text => 'none'
-    end
-  end
-
-  test "PUT /versions/:id.xml should update the version" do
-    put '/versions/2.xml', {:version => {:name => 'API update'}}, credentials('jsmith')
-
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_equal 'API update', Version.find(2).name
-  end
-
-  test "DELETE /versions/:id.xml should destroy the version" do
-    assert_difference 'Version.count', -1 do
-      delete '/versions/3.xml', {}, credentials('jsmith')
-    end
-
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_nil Version.find_by_id(3)
-  end
-end
--- a/.svn/pristine/54/545555b790077e8ce0b627745954990d978f492e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class EnabledModuleTest < ActiveSupport::TestCase
-  fixtures :projects, :wikis
-
-  def test_enabling_wiki_should_create_a_wiki
-    CustomField.delete_all
-    project = Project.create!(:name => 'Project with wiki', :identifier => 'wikiproject')
-    assert_nil project.wiki
-    project.enabled_module_names = ['wiki']
-    project.reload
-    assert_not_nil project.wiki
-    assert_equal 'Wiki', project.wiki.start_page
-  end
-
-  def test_reenabling_wiki_should_not_create_another_wiki
-    project = Project.find(1)
-    assert_not_nil project.wiki
-    project.enabled_module_names = []
-    project.reload
-    assert_no_difference 'Wiki.count' do
-      project.enabled_module_names = ['wiki']
-    end
-    assert_not_nil project.wiki
-  end
-end
--- a/.svn/pristine/56/56225b936777b98c482ec9e85d159d74d839691e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class Redmine::WikiFormatting::MacrosTest < ActionView::TestCase
-  include ApplicationHelper
-  include ActionView::Helpers::TextHelper
-  include ActionView::Helpers::SanitizeHelper
-  include ERB::Util
-  extend ActionView::Helpers::SanitizeHelper::ClassMethods
-
-  fixtures :projects, :roles, :enabled_modules, :users,
-                      :repositories, :changesets,
-                      :trackers, :issue_statuses, :issues,
-                      :versions, :documents,
-                      :wikis, :wiki_pages, :wiki_contents,
-                      :boards, :messages,
-                      :attachments
-
-  def setup
-    super
-    @project = nil
-  end
-
-  def teardown
-  end
-
-  def test_macro_registration
-    Redmine::WikiFormatting::Macros.register do
-      macro :foo do |obj, args|
-        "Foo: #{args.size} (#{args.join(',')}) (#{args.class.name})"
-      end
-    end
-
-    assert_equal '<p>Foo: 0 () (Array)</p>', textilizable("{{foo}}")
-    assert_equal '<p>Foo: 0 () (Array)</p>', textilizable("{{foo()}}")
-    assert_equal '<p>Foo: 1 (arg1) (Array)</p>', textilizable("{{foo(arg1)}}")
-    assert_equal '<p>Foo: 2 (arg1,arg2) (Array)</p>', textilizable("{{foo(arg1, arg2)}}")
-  end
-
-  def test_macro_registration_parse_args_set_to_false_should_disable_arguments_parsing
-    Redmine::WikiFormatting::Macros.register do
-      macro :bar, :parse_args => false do |obj, args|
-        "Bar: (#{args}) (#{args.class.name})"
-      end
-    end
-
-    assert_equal '<p>Bar: (args, more args) (String)</p>', textilizable("{{bar(args, more args)}}")
-    assert_equal '<p>Bar: () (String)</p>', textilizable("{{bar}}")
-    assert_equal '<p>Bar: () (String)</p>', textilizable("{{bar()}}")
-  end
-
-  def test_macro_registration_with_3_args_should_receive_text_argument
-    Redmine::WikiFormatting::Macros.register do
-      macro :baz do |obj, args, text|
-        "Baz: (#{args.join(',')}) (#{text.class.name}) (#{text})"
-      end
-    end
-
-    assert_equal "<p>Baz: () (NilClass) ()</p>", textilizable("{{baz}}")
-    assert_equal "<p>Baz: () (NilClass) ()</p>", textilizable("{{baz()}}")
-    assert_equal "<p>Baz: () (String) (line1\nline2)</p>", textilizable("{{baz()\nline1\nline2\n}}")
-    assert_equal "<p>Baz: (arg1,arg2) (String) (line1\nline2)</p>", textilizable("{{baz(arg1, arg2)\nline1\nline2\n}}")
-  end
-
-  def test_macro_name_with_upper_case
-    Redmine::WikiFormatting::Macros.macro(:UpperCase) {|obj, args| "Upper"}
-
-    assert_equal "<p>Upper</p>", textilizable("{{UpperCase}}")
-  end
-
-  def test_multiple_macros_on_the_same_line
-    Redmine::WikiFormatting::Macros.macro :foo do |obj, args|
-      args.any? ? "args: #{args.join(',')}" : "no args" 
-    end
-
-    assert_equal '<p>no args no args</p>', textilizable("{{foo}} {{foo}}")
-    assert_equal '<p>args: a,b no args</p>', textilizable("{{foo(a,b)}} {{foo}}")
-    assert_equal '<p>args: a,b args: c,d</p>', textilizable("{{foo(a,b)}} {{foo(c,d)}}")
-    assert_equal '<p>no args args: c,d</p>', textilizable("{{foo}} {{foo(c,d)}}")
-  end
-
-  def test_macro_should_receive_the_object_as_argument_when_with_object_and_attribute
-    issue = Issue.find(1)
-    issue.description = "{{hello_world}}"
-    assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(issue, :description)
-  end
-
-  def test_macro_should_receive_the_object_as_argument_when_called_with_object_option
-    text = "{{hello_world}}"
-    assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(text, :object => Issue.find(1))
-  end
-
-  def test_extract_macro_options_should_with_args
-    options = extract_macro_options(["arg1", "arg2"], :foo, :size)
-    assert_equal([["arg1", "arg2"], {}], options)
-  end
-
-  def test_extract_macro_options_should_with_options
-    options = extract_macro_options(["foo=bar", "size=2"], :foo, :size)
-    assert_equal([[], {:foo => "bar", :size => "2"}], options)
-  end
-
-  def test_extract_macro_options_should_with_args_and_options
-    options = extract_macro_options(["arg1", "arg2", "foo=bar", "size=2"], :foo, :size)
-    assert_equal([["arg1", "arg2"], {:foo => "bar", :size => "2"}], options)
-  end
-
-  def test_extract_macro_options_should_parse_options_lazily
-    options = extract_macro_options(["params=x=1&y=2"], :params)
-    assert_equal([[], {:params => "x=1&y=2"}], options)
-  end
-
-  def test_macro_exception_should_be_displayed
-    Redmine::WikiFormatting::Macros.macro :exception do |obj, args|
-      raise "My message"
-    end
-
-    text = "{{exception}}"
-    assert_include '<div class="flash error">Error executing the <strong>exception</strong> macro (My message)</div>', textilizable(text)
-  end
-
-  def test_macro_arguments_should_not_be_parsed_by_formatters
-    text = '{{hello_world(http://www.redmine.org, #1)}}'
-    assert_include 'Arguments: http://www.redmine.org, #1', textilizable(text)
-  end
-
-  def test_exclamation_mark_should_not_run_macros
-    text = "!{{hello_world}}"
-    assert_equal '<p>{{hello_world}}</p>', textilizable(text)
-  end
-
-  def test_exclamation_mark_should_escape_macros
-    text = "!{{hello_world(<tag>)}}"
-    assert_equal '<p>{{hello_world(&lt;tag&gt;)}}</p>', textilizable(text)
-  end
-
-  def test_unknown_macros_should_not_be_replaced
-    text = "{{unknown}}"
-    assert_equal '<p>{{unknown}}</p>', textilizable(text)
-  end
-
-  def test_unknown_macros_should_parsed_as_text
-    text = "{{unknown(*test*)}}"
-    assert_equal '<p>{{unknown(<strong>test</strong>)}}</p>', textilizable(text)
-  end
-
-  def test_unknown_macros_should_be_escaped
-    text = "{{unknown(<tag>)}}"
-    assert_equal '<p>{{unknown(&lt;tag&gt;)}}</p>', textilizable(text)
-  end
-
-  def test_html_safe_macro_output_should_not_be_escaped
-    Redmine::WikiFormatting::Macros.macro :safe_macro do |obj, args|
-      "<tag>".html_safe
-    end
-    assert_equal '<p><tag></p>', textilizable("{{safe_macro}}")
-  end
-
-  def test_macro_hello_world
-    text = "{{hello_world}}"
-    assert textilizable(text).match(/Hello world!/)
-  end
-
-  def test_macro_hello_world_should_escape_arguments
-    text = "{{hello_world(<tag>)}}"
-    assert_include 'Arguments: &lt;tag&gt;', textilizable(text)
-  end
-
-  def test_macro_macro_list
-    text = "{{macro_list}}"
-    assert_match %r{<code>hello_world</code>}, textilizable(text)
-  end
-
-  def test_macro_include
-    @project = Project.find(1)
-    # include a page of the current project wiki
-    text = "{{include(Another page)}}"
-    assert_include 'This is a link to a ticket', textilizable(text)
-
-    @project = nil
-    # include a page of a specific project wiki
-    text = "{{include(ecookbook:Another page)}}"
-    assert_include 'This is a link to a ticket', textilizable(text)
-
-    text = "{{include(ecookbook:)}}"
-    assert_include 'CookBook documentation', textilizable(text)
-
-    text = "{{include(unknowidentifier:somepage)}}"
-    assert_include 'Page not found', textilizable(text)
-  end
-
-  def test_macro_collapse
-    text = "{{collapse\n*Collapsed* block of text\n}}"
-    result = textilizable(text)
-
-    assert_select_in result, 'div.collapsed-text'
-    assert_select_in result, 'strong', :text => 'Collapsed'
-    assert_select_in result, 'a.collapsible.collapsed', :text => 'Show'
-    assert_select_in result, 'a.collapsible', :text => 'Hide'
-  end
-
-  def test_macro_collapse_with_one_arg
-    text = "{{collapse(Example)\n*Collapsed* block of text\n}}"
-    result = textilizable(text)
-
-    assert_select_in result, 'div.collapsed-text'
-    assert_select_in result, 'strong', :text => 'Collapsed'
-    assert_select_in result, 'a.collapsible.collapsed', :text => 'Example'
-    assert_select_in result, 'a.collapsible', :text => 'Example'
-  end
-
-  def test_macro_collapse_with_two_args
-    text = "{{collapse(Show example, Hide example)\n*Collapsed* block of text\n}}"
-    result = textilizable(text)
-
-    assert_select_in result, 'div.collapsed-text'
-    assert_select_in result, 'strong', :text => 'Collapsed'
-    assert_select_in result, 'a.collapsible.collapsed', :text => 'Show example'
-    assert_select_in result, 'a.collapsible', :text => 'Hide example'
-  end
-
-  def test_macro_child_pages
-    expected =  "<p><ul class=\"pages-hierarchy\">\n" +
-                 "<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a>\n" +
-                 "<ul class=\"pages-hierarchy\">\n<li><a href=\"/projects/ecookbook/wiki/Child_1_1\">Child 1 1</a></li>\n</ul>\n</li>\n" +
-                 "<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
-                 "</ul>\n</p>"
-
-    @project = Project.find(1)
-    # child pages of the current wiki page
-    assert_equal expected, textilizable("{{child_pages}}", :object => WikiPage.find(2).content)
-    # child pages of another page
-    assert_equal expected, textilizable("{{child_pages(Another_page)}}", :object => WikiPage.find(1).content)
-
-    @project = Project.find(2)
-    assert_equal expected, textilizable("{{child_pages(ecookbook:Another_page)}}", :object => WikiPage.find(1).content)
-  end
-
-  def test_macro_child_pages_with_parent_option
-    expected =  "<p><ul class=\"pages-hierarchy\">\n" +
-                 "<li><a href=\"/projects/ecookbook/wiki/Another_page\">Another page</a>\n" +
-                 "<ul class=\"pages-hierarchy\">\n" +
-                 "<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a>\n" +
-                 "<ul class=\"pages-hierarchy\">\n<li><a href=\"/projects/ecookbook/wiki/Child_1_1\">Child 1 1</a></li>\n</ul>\n</li>\n" +
-                 "<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
-                 "</ul>\n</li>\n</ul>\n</p>"
-
-    @project = Project.find(1)
-    # child pages of the current wiki page
-    assert_equal expected, textilizable("{{child_pages(parent=1)}}", :object => WikiPage.find(2).content)
-    # child pages of another page
-    assert_equal expected, textilizable("{{child_pages(Another_page, parent=1)}}", :object => WikiPage.find(1).content)
-
-    @project = Project.find(2)
-    assert_equal expected, textilizable("{{child_pages(ecookbook:Another_page, parent=1)}}", :object => WikiPage.find(1).content)
-  end
-
-  def test_macro_child_pages_with_depth_option
-    expected =  "<p><ul class=\"pages-hierarchy\">\n" +
-                 "<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a></li>\n" +
-                 "<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
-                 "</ul>\n</p>"
-
-    @project = Project.find(1)
-    assert_equal expected, textilizable("{{child_pages(depth=1)}}", :object => WikiPage.find(2).content)
-  end
-
-  def test_macro_child_pages_without_wiki_page_should_fail
-    assert_match /can be called from wiki pages only/, textilizable("{{child_pages}}")
-  end
-
-  def test_macro_thumbnail
-    assert_equal '<p><a href="/attachments/17" class="thumbnail" title="testfile.PNG"><img alt="testfile.PNG" src="/attachments/thumbnail/17" /></a></p>',
-      textilizable("{{thumbnail(testfile.png)}}", :object => Issue.find(14))
-  end
-
-  def test_macro_thumbnail_with_size
-    assert_equal '<p><a href="/attachments/17" class="thumbnail" title="testfile.PNG"><img alt="testfile.PNG" src="/attachments/thumbnail/17/200" /></a></p>',
-      textilizable("{{thumbnail(testfile.png, size=200)}}", :object => Issue.find(14))
-  end
-
-  def test_macro_thumbnail_with_title
-    assert_equal '<p><a href="/attachments/17" class="thumbnail" title="Cool image"><img alt="testfile.PNG" src="/attachments/thumbnail/17" /></a></p>',
-      textilizable("{{thumbnail(testfile.png, title=Cool image)}}", :object => Issue.find(14))
-  end
-
-  def test_macro_thumbnail_with_invalid_filename_should_fail
-    assert_include 'test.png not found',
-      textilizable("{{thumbnail(test.png)}}", :object => Issue.find(14))
-  end
-
-  def test_macros_should_not_be_executed_in_pre_tags
-    text = <<-RAW
-{{hello_world(foo)}}
-
-<pre>
-{{hello_world(pre)}}
-!{{hello_world(pre)}}
-</pre>
-
-{{hello_world(bar)}}
-RAW
-
-    expected = <<-EXPECTED
-<p>Hello world! Object: NilClass, Arguments: foo and no block of text.</p>
-
-<pre>
-{{hello_world(pre)}}
-!{{hello_world(pre)}}
-</pre>
-
-<p>Hello world! Object: NilClass, Arguments: bar and no block of text.</p>
-EXPECTED
-
-    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(text).gsub(%r{[\r\n\t]}, '')
-  end
-
-  def test_macros_should_be_escaped_in_pre_tags
-    text = "<pre>{{hello_world(<tag>)}}</pre>"
-    assert_equal "<pre>{{hello_world(&lt;tag&gt;)}}</pre>", textilizable(text)
-  end
-
-  def test_macros_should_not_mangle_next_macros_outputs
-    text = '{{macro(2)}} !{{macro(2)}} {{hello_world(foo)}}'
-    assert_equal '<p>{{macro(2)}} {{macro(2)}} Hello world! Object: NilClass, Arguments: foo and no block of text.</p>', textilizable(text)
-  end
-
-  def test_macros_with_text_should_not_mangle_following_macros
-    text = <<-RAW
-{{hello_world
-Line of text
-}}
-
-{{hello_world
-Another line of text
-}}
-RAW
-
-    expected = <<-EXPECTED
-<p>Hello world! Object: NilClass, Called with no argument and a 12 bytes long block of text.</p>
-<p>Hello world! Object: NilClass, Called with no argument and a 20 bytes long block of text.</p>
-EXPECTED
-
-    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(text).gsub(%r{[\r\n\t]}, '')
-  end
-end
--- a/.svn/pristine/56/5649977123508ab2f6673a662fcdabf65b2787e2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,784 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'active_record'
-require 'iconv' if RUBY_VERSION < '1.9'
-require 'pp'
-
-namespace :redmine do
-  desc 'Trac migration script'
-  task :migrate_from_trac => :environment do
-
-    module TracMigrate
-        TICKET_MAP = []
-
-        DEFAULT_STATUS = IssueStatus.default
-        assigned_status = IssueStatus.find_by_position(2)
-        resolved_status = IssueStatus.find_by_position(3)
-        feedback_status = IssueStatus.find_by_position(4)
-        closed_status = IssueStatus.where(:is_closed => true).first
-        STATUS_MAPPING = {'new' => DEFAULT_STATUS,
-                          'reopened' => feedback_status,
-                          'assigned' => assigned_status,
-                          'closed' => closed_status
-                          }
-
-        priorities = IssuePriority.all
-        DEFAULT_PRIORITY = priorities[0]
-        PRIORITY_MAPPING = {'lowest' => priorities[0],
-                            'low' => priorities[0],
-                            'normal' => priorities[1],
-                            'high' => priorities[2],
-                            'highest' => priorities[3],
-                            # ---
-                            'trivial' => priorities[0],
-                            'minor' => priorities[1],
-                            'major' => priorities[2],
-                            'critical' => priorities[3],
-                            'blocker' => priorities[4]
-                            }
-
-        TRACKER_BUG = Tracker.find_by_position(1)
-        TRACKER_FEATURE = Tracker.find_by_position(2)
-        DEFAULT_TRACKER = TRACKER_BUG
-        TRACKER_MAPPING = {'defect' => TRACKER_BUG,
-                           'enhancement' => TRACKER_FEATURE,
-                           'task' => TRACKER_FEATURE,
-                           'patch' =>TRACKER_FEATURE
-                           }
-
-        roles = Role.where(:builtin => 0).order('position ASC').all
-        manager_role = roles[0]
-        developer_role = roles[1]
-        DEFAULT_ROLE = roles.last
-        ROLE_MAPPING = {'admin' => manager_role,
-                        'developer' => developer_role
-                        }
-
-      class ::Time
-        class << self
-          alias :real_now :now
-          def now
-            real_now - @fake_diff.to_i
-          end
-          def fake(time)
-            @fake_diff = real_now - time
-            res = yield
-            @fake_diff = 0
-           res
-          end
-        end
-      end
-
-      class TracComponent < ActiveRecord::Base
-        self.table_name = :component
-      end
-
-      class TracMilestone < ActiveRecord::Base
-        self.table_name = :milestone
-        # If this attribute is set a milestone has a defined target timepoint
-        def due
-          if read_attribute(:due) && read_attribute(:due) > 0
-            Time.at(read_attribute(:due)).to_date
-          else
-            nil
-          end
-        end
-        # This is the real timepoint at which the milestone has finished.
-        def completed
-          if read_attribute(:completed) && read_attribute(:completed) > 0
-            Time.at(read_attribute(:completed)).to_date
-          else
-            nil
-          end
-        end
-
-        def description
-          # Attribute is named descr in Trac v0.8.x
-          has_attribute?(:descr) ? read_attribute(:descr) : read_attribute(:description)
-        end
-      end
-
-      class TracTicketCustom < ActiveRecord::Base
-        self.table_name = :ticket_custom
-      end
-
-      class TracAttachment < ActiveRecord::Base
-        self.table_name = :attachment
-        set_inheritance_column :none
-
-        def time; Time.at(read_attribute(:time)) end
-
-        def original_filename
-          filename
-        end
-
-        def content_type
-          ''
-        end
-
-        def exist?
-          File.file? trac_fullpath
-        end
-
-        def open
-          File.open("#{trac_fullpath}", 'rb') {|f|
-            @file = f
-            yield self
-          }
-        end
-
-        def read(*args)
-          @file.read(*args)
-        end
-
-        def description
-          read_attribute(:description).to_s.slice(0,255)
-        end
-
-      private
-        def trac_fullpath
-          attachment_type = read_attribute(:type)
-          #replace exotic characters with their hex representation to avoid invalid filenames
-          trac_file = filename.gsub( /[^a-zA-Z0-9\-_\.!~*']/n ) do |x|
-            codepoint = RUBY_VERSION < '1.9' ? x[0] : x.codepoints.to_a[0]
-            sprintf('%%%02x', codepoint)
-          end
-          "#{TracMigrate.trac_attachments_directory}/#{attachment_type}/#{id}/#{trac_file}"
-        end
-      end
-
-      class TracTicket < ActiveRecord::Base
-        self.table_name = :ticket
-        set_inheritance_column :none
-
-        # ticket changes: only migrate status changes and comments
-        has_many :ticket_changes, :class_name => "TracTicketChange", :foreign_key => :ticket
-        has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket
-
-        def attachments
-          TracMigrate::TracAttachment.all(:conditions => ["type = 'ticket' AND id = ?", self.id.to_s])
-        end
-
-        def ticket_type
-          read_attribute(:type)
-        end
-
-        def summary
-          read_attribute(:summary).blank? ? "(no subject)" : read_attribute(:summary)
-        end
-
-        def description
-          read_attribute(:description).blank? ? summary : read_attribute(:description)
-        end
-
-        def time; Time.at(read_attribute(:time)) end
-        def changetime; Time.at(read_attribute(:changetime)) end
-      end
-
-      class TracTicketChange < ActiveRecord::Base
-        self.table_name = :ticket_change
-
-        def self.columns
-          # Hides Trac field 'field' to prevent clash with AR field_changed? method (Rails 3.0)
-          super.select {|column| column.name.to_s != 'field'}
-        end
-
-        def time; Time.at(read_attribute(:time)) end
-      end
-
-      TRAC_WIKI_PAGES = %w(InterMapTxt InterTrac InterWiki RecentChanges SandBox TracAccessibility TracAdmin TracBackup TracBrowser TracCgi TracChangeset \
-                           TracEnvironment TracFastCgi TracGuide TracImport TracIni TracInstall TracInterfaceCustomization \
-                           TracLinks TracLogging TracModPython TracNotification TracPermissions TracPlugins TracQuery \
-                           TracReports TracRevisionLog TracRoadmap TracRss TracSearch TracStandalone TracSupport TracSyntaxColoring TracTickets \
-                           TracTicketsCustomFields TracTimeline TracUnicode TracUpgrade TracWiki WikiDeletePage WikiFormatting \
-                           WikiHtml WikiMacros WikiNewPage WikiPageNames WikiProcessors WikiRestructuredText WikiRestructuredTextLinks \
-                           CamelCase TitleIndex)
-
-      class TracWikiPage < ActiveRecord::Base
-        self.table_name = :wiki
-        set_primary_key :name
-
-        def self.columns
-          # Hides readonly Trac field to prevent clash with AR readonly? method (Rails 2.0)
-          super.select {|column| column.name.to_s != 'readonly'}
-        end
-
-        def attachments
-          TracMigrate::TracAttachment.all(:conditions => ["type = 'wiki' AND id = ?", self.id.to_s])
-        end
-
-        def time; Time.at(read_attribute(:time)) end
-      end
-
-      class TracPermission < ActiveRecord::Base
-        self.table_name = :permission
-      end
-
-      class TracSessionAttribute < ActiveRecord::Base
-        self.table_name = :session_attribute
-      end
-
-      def self.find_or_create_user(username, project_member = false)
-        return User.anonymous if username.blank?
-
-        u = User.find_by_login(username)
-        if !u
-          # Create a new user if not found
-          mail = username[0, User::MAIL_LENGTH_LIMIT]
-          if mail_attr = TracSessionAttribute.find_by_sid_and_name(username, 'email')
-            mail = mail_attr.value
-          end
-          mail = "#{mail}@foo.bar" unless mail.include?("@")
-
-          name = username
-          if name_attr = TracSessionAttribute.find_by_sid_and_name(username, 'name')
-            name = name_attr.value
-          end
-          name =~ (/(\w+)(\s+\w+)?/)
-          fn = ($1 || "-").strip
-          ln = ($2 || '-').strip
-
-          u = User.new :mail => mail.gsub(/[^-@a-z0-9\.]/i, '-'),
-                       :firstname => fn[0, limit_for(User, 'firstname')],
-                       :lastname => ln[0, limit_for(User, 'lastname')]
-
-          u.login = username[0, User::LOGIN_LENGTH_LIMIT].gsub(/[^a-z0-9_\-@\.]/i, '-')
-          u.password = 'trac'
-          u.admin = true if TracPermission.find_by_username_and_action(username, 'admin')
-          # finally, a default user is used if the new user is not valid
-          u = User.first unless u.save
-        end
-        # Make sure user is a member of the project
-        if project_member && !u.member_of?(@target_project)
-          role = DEFAULT_ROLE
-          if u.admin
-            role = ROLE_MAPPING['admin']
-          elsif TracPermission.find_by_username_and_action(username, 'developer')
-            role = ROLE_MAPPING['developer']
-          end
-          Member.create(:user => u, :project => @target_project, :roles => [role])
-          u.reload
-        end
-        u
-      end
-
-      # Basic wiki syntax conversion
-      def self.convert_wiki_text(text)
-        # Titles
-        text = text.gsub(/^(\=+)\s(.+)\s(\=+)/) {|s| "\nh#{$1.length}. #{$2}\n"}
-        # External Links
-        text = text.gsub(/\[(http[^\s]+)\s+([^\]]+)\]/) {|s| "\"#{$2}\":#{$1}"}
-        # Ticket links:
-        #      [ticket:234 Text],[ticket:234 This is a test]
-        text = text.gsub(/\[ticket\:([^\ ]+)\ (.+?)\]/, '"\2":/issues/show/\1')
-        #      ticket:1234
-        #      #1 is working cause Redmine uses the same syntax.
-        text = text.gsub(/ticket\:([^\ ]+)/, '#\1')
-        # Milestone links:
-        #      [milestone:"0.1.0 Mercury" Milestone 0.1.0 (Mercury)]
-        #      The text "Milestone 0.1.0 (Mercury)" is not converted,
-        #      cause Redmine's wiki does not support this.
-        text = text.gsub(/\[milestone\:\"([^\"]+)\"\ (.+?)\]/, 'version:"\1"')
-        #      [milestone:"0.1.0 Mercury"]
-        text = text.gsub(/\[milestone\:\"([^\"]+)\"\]/, 'version:"\1"')
-        text = text.gsub(/milestone\:\"([^\"]+)\"/, 'version:"\1"')
-        #      milestone:0.1.0
-        text = text.gsub(/\[milestone\:([^\ ]+)\]/, 'version:\1')
-        text = text.gsub(/milestone\:([^\ ]+)/, 'version:\1')
-        # Internal Links
-        text = text.gsub(/\[\[BR\]\]/, "\n") # This has to go before the rules below
-        text = text.gsub(/\[\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
-        text = text.gsub(/\[wiki:\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
-        text = text.gsub(/\[wiki:\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
-        text = text.gsub(/\[wiki:([^\s\]]+)\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
-        text = text.gsub(/\[wiki:([^\s\]]+)\s(.*)\]/) {|s| "[[#{$1.delete(',./?;|:')}|#{$2.delete(',./?;|:')}]]"}
-
-  # Links to pages UsingJustWikiCaps
-  text = text.gsub(/([^!]|^)(^| )([A-Z][a-z]+[A-Z][a-zA-Z]+)/, '\\1\\2[[\3]]')
-  # Normalize things that were supposed to not be links
-  # like !NotALink
-  text = text.gsub(/(^| )!([A-Z][A-Za-z]+)/, '\1\2')
-        # Revisions links
-        text = text.gsub(/\[(\d+)\]/, 'r\1')
-        # Ticket number re-writing
-        text = text.gsub(/#(\d+)/) do |s|
-          if $1.length < 10
-#            TICKET_MAP[$1.to_i] ||= $1
-            "\##{TICKET_MAP[$1.to_i] || $1}"
-          else
-            s
-          end
-        end
-        # We would like to convert the Code highlighting too
-        # This will go into the next line.
-        shebang_line = false
-        # Reguar expression for start of code
-        pre_re = /\{\{\{/
-        # Code hightlighing...
-        shebang_re = /^\#\!([a-z]+)/
-        # Regular expression for end of code
-        pre_end_re = /\}\}\}/
-
-        # Go through the whole text..extract it line by line
-        text = text.gsub(/^(.*)$/) do |line|
-          m_pre = pre_re.match(line)
-          if m_pre
-            line = '<pre>'
-          else
-            m_sl = shebang_re.match(line)
-            if m_sl
-              shebang_line = true
-              line = '<code class="' + m_sl[1] + '">'
-            end
-            m_pre_end = pre_end_re.match(line)
-            if m_pre_end
-              line = '</pre>'
-              if shebang_line
-                line = '</code>' + line
-              end
-            end
-          end
-          line
-        end
-
-        # Highlighting
-        text = text.gsub(/'''''([^\s])/, '_*\1')
-        text = text.gsub(/([^\s])'''''/, '\1*_')
-        text = text.gsub(/'''/, '*')
-        text = text.gsub(/''/, '_')
-        text = text.gsub(/__/, '+')
-        text = text.gsub(/~~/, '-')
-        text = text.gsub(/`/, '@')
-        text = text.gsub(/,,/, '~')
-        # Lists
-        text = text.gsub(/^([ ]+)\* /) {|s| '*' * $1.length + " "}
-
-        text
-      end
-
-      def self.migrate
-        establish_connection
-
-        # Quick database test
-        TracComponent.count
-
-        migrated_components = 0
-        migrated_milestones = 0
-        migrated_tickets = 0
-        migrated_custom_values = 0
-        migrated_ticket_attachments = 0
-        migrated_wiki_edits = 0
-        migrated_wiki_attachments = 0
-
-        #Wiki system initializing...
-        @target_project.wiki.destroy if @target_project.wiki
-        @target_project.reload
-        wiki = Wiki.new(:project => @target_project, :start_page => 'WikiStart')
-        wiki_edit_count = 0
-
-        # Components
-        print "Migrating components"
-        issues_category_map = {}
-        TracComponent.all.each do |component|
-        print '.'
-        STDOUT.flush
-          c = IssueCategory.new :project => @target_project,
-                                :name => encode(component.name[0, limit_for(IssueCategory, 'name')])
-        next unless c.save
-        issues_category_map[component.name] = c
-        migrated_components += 1
-        end
-        puts
-
-        # Milestones
-        print "Migrating milestones"
-        version_map = {}
-        TracMilestone.all.each do |milestone|
-          print '.'
-          STDOUT.flush
-          # First we try to find the wiki page...
-          p = wiki.find_or_new_page(milestone.name.to_s)
-          p.content = WikiContent.new(:page => p) if p.new_record?
-          p.content.text = milestone.description.to_s
-          p.content.author = find_or_create_user('trac')
-          p.content.comments = 'Milestone'
-          p.save
-
-          v = Version.new :project => @target_project,
-                          :name => encode(milestone.name[0, limit_for(Version, 'name')]),
-                          :description => nil,
-                          :wiki_page_title => milestone.name.to_s,
-                          :effective_date => milestone.completed
-
-          next unless v.save
-          version_map[milestone.name] = v
-          migrated_milestones += 1
-        end
-        puts
-
-        # Custom fields
-        # TODO: read trac.ini instead
-        print "Migrating custom fields"
-        custom_field_map = {}
-        TracTicketCustom.find_by_sql("SELECT DISTINCT name FROM #{TracTicketCustom.table_name}").each do |field|
-          print '.'
-          STDOUT.flush
-          # Redmine custom field name
-          field_name = encode(field.name[0, limit_for(IssueCustomField, 'name')]).humanize
-          # Find if the custom already exists in Redmine
-          f = IssueCustomField.find_by_name(field_name)
-          # Or create a new one
-          f ||= IssueCustomField.create(:name => encode(field.name[0, limit_for(IssueCustomField, 'name')]).humanize,
-                                        :field_format => 'string')
-
-          next if f.new_record?
-          f.trackers = Tracker.all
-          f.projects << @target_project
-          custom_field_map[field.name] = f
-        end
-        puts
-
-        # Trac 'resolution' field as a Redmine custom field
-        r = IssueCustomField.where(:name => "Resolution").first
-        r = IssueCustomField.new(:name => 'Resolution',
-                                 :field_format => 'list',
-                                 :is_filter => true) if r.nil?
-        r.trackers = Tracker.all
-        r.projects << @target_project
-        r.possible_values = (r.possible_values + %w(fixed invalid wontfix duplicate worksforme)).flatten.compact.uniq
-        r.save!
-        custom_field_map['resolution'] = r
-
-        # Tickets
-        print "Migrating tickets"
-          TracTicket.find_each(:batch_size => 200) do |ticket|
-          print '.'
-          STDOUT.flush
-          i = Issue.new :project => @target_project,
-                          :subject => encode(ticket.summary[0, limit_for(Issue, 'subject')]),
-                          :description => convert_wiki_text(encode(ticket.description)),
-                          :priority => PRIORITY_MAPPING[ticket.priority] || DEFAULT_PRIORITY,
-                          :created_on => ticket.time
-          i.author = find_or_create_user(ticket.reporter)
-          i.category = issues_category_map[ticket.component] unless ticket.component.blank?
-          i.fixed_version = version_map[ticket.milestone] unless ticket.milestone.blank?
-          i.status = STATUS_MAPPING[ticket.status] || DEFAULT_STATUS
-          i.tracker = TRACKER_MAPPING[ticket.ticket_type] || DEFAULT_TRACKER
-          i.id = ticket.id unless Issue.exists?(ticket.id)
-          next unless Time.fake(ticket.changetime) { i.save }
-          TICKET_MAP[ticket.id] = i.id
-          migrated_tickets += 1
-
-          # Owner
-            unless ticket.owner.blank?
-              i.assigned_to = find_or_create_user(ticket.owner, true)
-              Time.fake(ticket.changetime) { i.save }
-            end
-
-          # Comments and status/resolution changes
-          ticket.ticket_changes.group_by(&:time).each do |time, changeset|
-              status_change = changeset.select {|change| change.field == 'status'}.first
-              resolution_change = changeset.select {|change| change.field == 'resolution'}.first
-              comment_change = changeset.select {|change| change.field == 'comment'}.first
-
-              n = Journal.new :notes => (comment_change ? convert_wiki_text(encode(comment_change.newvalue)) : ''),
-                              :created_on => time
-              n.user = find_or_create_user(changeset.first.author)
-              n.journalized = i
-              if status_change &&
-                   STATUS_MAPPING[status_change.oldvalue] &&
-                   STATUS_MAPPING[status_change.newvalue] &&
-                   (STATUS_MAPPING[status_change.oldvalue] != STATUS_MAPPING[status_change.newvalue])
-                n.details << JournalDetail.new(:property => 'attr',
-                                               :prop_key => 'status_id',
-                                               :old_value => STATUS_MAPPING[status_change.oldvalue].id,
-                                               :value => STATUS_MAPPING[status_change.newvalue].id)
-              end
-              if resolution_change
-                n.details << JournalDetail.new(:property => 'cf',
-                                               :prop_key => custom_field_map['resolution'].id,
-                                               :old_value => resolution_change.oldvalue,
-                                               :value => resolution_change.newvalue)
-              end
-              n.save unless n.details.empty? && n.notes.blank?
-          end
-
-          # Attachments
-          ticket.attachments.each do |attachment|
-            next unless attachment.exist?
-              attachment.open {
-                a = Attachment.new :created_on => attachment.time
-                a.file = attachment
-                a.author = find_or_create_user(attachment.author)
-                a.container = i
-                a.description = attachment.description
-                migrated_ticket_attachments += 1 if a.save
-              }
-          end
-
-          # Custom fields
-          custom_values = ticket.customs.inject({}) do |h, custom|
-            if custom_field = custom_field_map[custom.name]
-              h[custom_field.id] = custom.value
-              migrated_custom_values += 1
-            end
-            h
-          end
-          if custom_field_map['resolution'] && !ticket.resolution.blank?
-            custom_values[custom_field_map['resolution'].id] = ticket.resolution
-          end
-          i.custom_field_values = custom_values
-          i.save_custom_field_values
-        end
-
-        # update issue id sequence if needed (postgresql)
-        Issue.connection.reset_pk_sequence!(Issue.table_name) if Issue.connection.respond_to?('reset_pk_sequence!')
-        puts
-
-        # Wiki
-        print "Migrating wiki"
-        if wiki.save
-          TracWikiPage.order('name, version').all.each do |page|
-            # Do not migrate Trac manual wiki pages
-            next if TRAC_WIKI_PAGES.include?(page.name)
-            wiki_edit_count += 1
-            print '.'
-            STDOUT.flush
-            p = wiki.find_or_new_page(page.name)
-            p.content = WikiContent.new(:page => p) if p.new_record?
-            p.content.text = page.text
-            p.content.author = find_or_create_user(page.author) unless page.author.blank? || page.author == 'trac'
-            p.content.comments = page.comment
-            Time.fake(page.time) { p.new_record? ? p.save : p.content.save }
-
-            next if p.content.new_record?
-            migrated_wiki_edits += 1
-
-            # Attachments
-            page.attachments.each do |attachment|
-              next unless attachment.exist?
-              next if p.attachments.find_by_filename(attachment.filename.gsub(/^.*(\\|\/)/, '').gsub(/[^\w\.\-]/,'_')) #add only once per page
-              attachment.open {
-                a = Attachment.new :created_on => attachment.time
-                a.file = attachment
-                a.author = find_or_create_user(attachment.author)
-                a.description = attachment.description
-                a.container = p
-                migrated_wiki_attachments += 1 if a.save
-              }
-            end
-          end
-
-          wiki.reload
-          wiki.pages.each do |page|
-            page.content.text = convert_wiki_text(page.content.text)
-            Time.fake(page.content.updated_on) { page.content.save }
-          end
-        end
-        puts
-
-        puts
-        puts "Components:      #{migrated_components}/#{TracComponent.count}"
-        puts "Milestones:      #{migrated_milestones}/#{TracMilestone.count}"
-        puts "Tickets:         #{migrated_tickets}/#{TracTicket.count}"
-        puts "Ticket files:    #{migrated_ticket_attachments}/" + TracAttachment.count(:conditions => {:type => 'ticket'}).to_s
-        puts "Custom values:   #{migrated_custom_values}/#{TracTicketCustom.count}"
-        puts "Wiki edits:      #{migrated_wiki_edits}/#{wiki_edit_count}"
-        puts "Wiki files:      #{migrated_wiki_attachments}/" + TracAttachment.count(:conditions => {:type => 'wiki'}).to_s
-      end
-
-      def self.limit_for(klass, attribute)
-        klass.columns_hash[attribute.to_s].limit
-      end
-
-      def self.encoding(charset)
-        @charset = charset
-      end
-
-      def self.set_trac_directory(path)
-        @@trac_directory = path
-        raise "This directory doesn't exist!" unless File.directory?(path)
-        raise "#{trac_attachments_directory} doesn't exist!" unless File.directory?(trac_attachments_directory)
-        @@trac_directory
-      rescue Exception => e
-        puts e
-        return false
-      end
-
-      def self.trac_directory
-        @@trac_directory
-      end
-
-      def self.set_trac_adapter(adapter)
-        return false if adapter.blank?
-        raise "Unknown adapter: #{adapter}!" unless %w(sqlite3 mysql postgresql).include?(adapter)
-        # If adapter is sqlite or sqlite3, make sure that trac.db exists
-        raise "#{trac_db_path} doesn't exist!" if %w(sqlite3).include?(adapter) && !File.exist?(trac_db_path)
-        @@trac_adapter = adapter
-      rescue Exception => e
-        puts e
-        return false
-      end
-
-      def self.set_trac_db_host(host)
-        return nil if host.blank?
-        @@trac_db_host = host
-      end
-
-      def self.set_trac_db_port(port)
-        return nil if port.to_i == 0
-        @@trac_db_port = port.to_i
-      end
-
-      def self.set_trac_db_name(name)
-        return nil if name.blank?
-        @@trac_db_name = name
-      end
-
-      def self.set_trac_db_username(username)
-        @@trac_db_username = username
-      end
-
-      def self.set_trac_db_password(password)
-        @@trac_db_password = password
-      end
-
-      def self.set_trac_db_schema(schema)
-        @@trac_db_schema = schema
-      end
-
-      mattr_reader :trac_directory, :trac_adapter, :trac_db_host, :trac_db_port, :trac_db_name, :trac_db_schema, :trac_db_username, :trac_db_password
-
-      def self.trac_db_path; "#{trac_directory}/db/trac.db" end
-      def self.trac_attachments_directory; "#{trac_directory}/attachments" end
-
-      def self.target_project_identifier(identifier)
-        project = Project.find_by_identifier(identifier)
-        if !project
-          # create the target project
-          project = Project.new :name => identifier.humanize,
-                                :description => ''
-          project.identifier = identifier
-          puts "Unable to create a project with identifier '#{identifier}'!" unless project.save
-          # enable issues and wiki for the created project
-          project.enabled_module_names = ['issue_tracking', 'wiki']
-        else
-          puts
-          puts "This project already exists in your Redmine database."
-          print "Are you sure you want to append data to this project ? [Y/n] "
-          STDOUT.flush
-          exit if STDIN.gets.match(/^n$/i)
-        end
-        project.trackers << TRACKER_BUG unless project.trackers.include?(TRACKER_BUG)
-        project.trackers << TRACKER_FEATURE unless project.trackers.include?(TRACKER_FEATURE)
-        @target_project = project.new_record? ? nil : project
-        @target_project.reload
-      end
-
-      def self.connection_params
-        if trac_adapter == 'sqlite3'
-          {:adapter => 'sqlite3',
-           :database => trac_db_path}
-        else
-          {:adapter => trac_adapter,
-           :database => trac_db_name,
-           :host => trac_db_host,
-           :port => trac_db_port,
-           :username => trac_db_username,
-           :password => trac_db_password,
-           :schema_search_path => trac_db_schema
-          }
-        end
-      end
-
-      def self.establish_connection
-        constants.each do |const|
-          klass = const_get(const)
-          next unless klass.respond_to? 'establish_connection'
-          klass.establish_connection connection_params
-        end
-      end
-
-      def self.encode(text)
-        if RUBY_VERSION < '1.9'
-          @ic ||= Iconv.new('UTF-8', @charset)
-          @ic.iconv text
-        else
-          text.to_s.force_encoding(@charset).encode('UTF-8')
-        end
-      end
-    end
-
-    puts
-    if Redmine::DefaultData::Loader.no_data?
-      puts "Redmine configuration need to be loaded before importing data."
-      puts "Please, run this first:"
-      puts
-      puts "  rake redmine:load_default_data RAILS_ENV=\"#{ENV['RAILS_ENV']}\""
-      exit
-    end
-
-    puts "WARNING: a new project will be added to Redmine during this process."
-    print "Are you sure you want to continue ? [y/N] "
-    STDOUT.flush
-    break unless STDIN.gets.match(/^y$/i)
-    puts
-
-    def prompt(text, options = {}, &block)
-      default = options[:default] || ''
-      while true
-        print "#{text} [#{default}]: "
-        STDOUT.flush
-        value = STDIN.gets.chomp!
-        value = default if value.blank?
-        break if yield value
-      end
-    end
-
-    DEFAULT_PORTS = {'mysql' => 3306, 'postgresql' => 5432}
-
-    prompt('Trac directory') {|directory| TracMigrate.set_trac_directory directory.strip}
-    prompt('Trac database adapter (sqlite3, mysql2, postgresql)', :default => 'sqlite3') {|adapter| TracMigrate.set_trac_adapter adapter}
-    unless %w(sqlite3).include?(TracMigrate.trac_adapter)
-      prompt('Trac database host', :default => 'localhost') {|host| TracMigrate.set_trac_db_host host}
-      prompt('Trac database port', :default => DEFAULT_PORTS[TracMigrate.trac_adapter]) {|port| TracMigrate.set_trac_db_port port}
-      prompt('Trac database name') {|name| TracMigrate.set_trac_db_name name}
-      prompt('Trac database schema', :default => 'public') {|schema| TracMigrate.set_trac_db_schema schema}
-      prompt('Trac database username') {|username| TracMigrate.set_trac_db_username username}
-      prompt('Trac database password') {|password| TracMigrate.set_trac_db_password password}
-    end
-    prompt('Trac database encoding', :default => 'UTF-8') {|encoding| TracMigrate.encoding encoding}
-    prompt('Target project identifier') {|identifier| TracMigrate.target_project_identifier identifier}
-    puts
-
-    old_notified_events = Setting.notified_events
-    old_password_min_length = Setting.password_min_length
-    begin
-      # Turn off email notifications temporarily
-      Setting.notified_events = []
-      Setting.password_min_length = 4
-      # Run the migration
-      TracMigrate.migrate
-    ensure
-      # Restore previous settings
-      Setting.notified_events = old_notified_events
-      Setting.password_min_length = old_password_min_length
-    end
-  end
-end
-
--- a/.svn/pristine/56/565b665c10da577a12dc50053706643709a0c80a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class CustomFieldTest < ActiveSupport::TestCase
-  fixtures :custom_fields
-
-  def test_create
-    field = UserCustomField.new(:name => 'Money money money', :field_format => 'float')
-    assert field.save
-  end
-
-  def test_before_validation
-    field = CustomField.new(:name => 'test_before_validation', :field_format => 'int')
-    field.searchable = true
-    assert field.save
-    assert_equal false, field.searchable
-    field.searchable = true
-    assert field.save
-    assert_equal false, field.searchable
-  end
-
-  def test_regexp_validation
-    field = IssueCustomField.new(:name => 'regexp', :field_format => 'text', :regexp => '[a-z0-9')
-    assert !field.save
-    assert_include I18n.t('activerecord.errors.messages.invalid'),
-                   field.errors[:regexp]
-    field.regexp = '[a-z0-9]'
-    assert field.save
-  end
-
-  def test_default_value_should_be_validated
-    field = CustomField.new(:name => 'Test', :field_format => 'int')
-    field.default_value = 'abc'
-    assert !field.valid?
-    field.default_value = '6'
-    assert field.valid?
-  end
-
-  def test_default_value_should_not_be_validated_when_blank
-    field = CustomField.new(:name => 'Test', :field_format => 'list', :possible_values => ['a', 'b'], :is_required => true, :default_value => '')
-    assert field.valid?
-  end
-
-  def test_field_format_should_be_validated
-    field = CustomField.new(:name => 'Test', :field_format => 'foo')
-    assert !field.valid?
-  end
-
-  def test_field_format_validation_should_accept_formats_added_at_runtime
-    Redmine::CustomFieldFormat.register 'foobar'
-
-    field = CustomField.new(:name => 'Some Custom Field', :field_format => 'foobar')
-    assert field.valid?, 'field should be valid'
-  ensure
-    Redmine::CustomFieldFormat.delete 'foobar'
-  end
-
-  def test_should_not_change_field_format_of_existing_custom_field
-    field = CustomField.find(1)
-    field.field_format = 'int'
-    assert_equal 'list', field.field_format
-  end
-
-  def test_possible_values_should_accept_an_array
-    field = CustomField.new
-    field.possible_values = ["One value", ""]
-    assert_equal ["One value"], field.possible_values
-  end
-
-  def test_possible_values_should_accept_a_string
-    field = CustomField.new
-    field.possible_values = "One value"
-    assert_equal ["One value"], field.possible_values
-  end
-
-  def test_possible_values_should_accept_a_multiline_string
-    field = CustomField.new
-    field.possible_values = "One value\nAnd another one  \r\n \n"
-    assert_equal ["One value", "And another one"], field.possible_values
-  end
-
-  if "string".respond_to?(:encoding)
-    def test_possible_values_stored_as_binary_should_be_utf8_encoded
-      field = CustomField.find(11)
-      assert_kind_of Array, field.possible_values
-      assert field.possible_values.size > 0
-      field.possible_values.each do |value|
-        assert_equal "UTF-8", value.encoding.name
-      end
-    end
-  end
-
-  def test_destroy
-    field = CustomField.find(1)
-    assert field.destroy
-  end
-
-  def test_new_subclass_instance_should_return_an_instance
-    f = CustomField.new_subclass_instance('IssueCustomField')
-    assert_kind_of IssueCustomField, f
-  end
-
-  def test_new_subclass_instance_should_set_attributes
-    f = CustomField.new_subclass_instance('IssueCustomField', :name => 'Test')
-    assert_kind_of IssueCustomField, f
-    assert_equal 'Test', f.name
-  end
-
-  def test_new_subclass_instance_with_invalid_class_name_should_return_nil
-    assert_nil CustomField.new_subclass_instance('WrongClassName')
-  end
-
-  def test_new_subclass_instance_with_non_subclass_name_should_return_nil
-    assert_nil CustomField.new_subclass_instance('Project')
-  end
-
-  def test_string_field_validation_with_blank_value
-    f = CustomField.new(:field_format => 'string')
-
-    assert f.valid_field_value?(nil)
-    assert f.valid_field_value?('')
-
-    f.is_required = true
-    assert !f.valid_field_value?(nil)
-    assert !f.valid_field_value?('')
-  end
-
-  def test_string_field_validation_with_min_and_max_lengths
-    f = CustomField.new(:field_format => 'string', :min_length => 2, :max_length => 5)
-
-    assert f.valid_field_value?(nil)
-    assert f.valid_field_value?('')
-    assert f.valid_field_value?('a' * 2)
-    assert !f.valid_field_value?('a')
-    assert !f.valid_field_value?('a' * 6)
-  end
-
-  def test_string_field_validation_with_regexp
-    f = CustomField.new(:field_format => 'string', :regexp => '^[A-Z0-9]*$')
-
-    assert f.valid_field_value?(nil)
-    assert f.valid_field_value?('')
-    assert f.valid_field_value?('ABC')
-    assert !f.valid_field_value?('abc')
-  end
-
-  def test_date_field_validation
-    f = CustomField.new(:field_format => 'date')
-
-    assert f.valid_field_value?(nil)
-    assert f.valid_field_value?('')
-    assert f.valid_field_value?('1975-07-14')
-    assert !f.valid_field_value?('1975-07-33')
-    assert !f.valid_field_value?('abc')
-  end
-
-  def test_list_field_validation
-    f = CustomField.new(:field_format => 'list', :possible_values => ['value1', 'value2'])
-
-    assert f.valid_field_value?(nil)
-    assert f.valid_field_value?('')
-    assert f.valid_field_value?('value2')
-    assert !f.valid_field_value?('abc')
-  end
-
-  def test_int_field_validation
-    f = CustomField.new(:field_format => 'int')
-
-    assert f.valid_field_value?(nil)
-    assert f.valid_field_value?('')
-    assert f.valid_field_value?('123')
-    assert f.valid_field_value?('+123')
-    assert f.valid_field_value?('-123')
-    assert !f.valid_field_value?('6abc')
-  end
-
-  def test_float_field_validation
-    f = CustomField.new(:field_format => 'float')
-
-    assert f.valid_field_value?(nil)
-    assert f.valid_field_value?('')
-    assert f.valid_field_value?('11.2')
-    assert f.valid_field_value?('-6.250')
-    assert f.valid_field_value?('5')
-    assert !f.valid_field_value?('6abc')
-  end
-
-  def test_multi_field_validation
-    f = CustomField.new(:field_format => 'list', :multiple => 'true', :possible_values => ['value1', 'value2'])
-
-    assert f.valid_field_value?(nil)
-    assert f.valid_field_value?('')
-    assert f.valid_field_value?([])
-    assert f.valid_field_value?([nil])
-    assert f.valid_field_value?([''])
-
-    assert f.valid_field_value?('value2')
-    assert !f.valid_field_value?('abc')
-
-    assert f.valid_field_value?(['value2'])
-    assert !f.valid_field_value?(['abc'])
-
-    assert f.valid_field_value?(['', 'value2'])
-    assert !f.valid_field_value?(['', 'abc'])
-
-    assert f.valid_field_value?(['value1', 'value2'])
-    assert !f.valid_field_value?(['value1', 'abc'])
-  end
-
-  def test_changing_multiple_to_false_should_delete_multiple_values
-    field = ProjectCustomField.create!(:name => 'field', :field_format => 'list', :multiple => 'true', :possible_values => ['field1', 'field2'])
-    other = ProjectCustomField.create!(:name => 'other', :field_format => 'list', :multiple => 'true', :possible_values => ['other1', 'other2'])
-
-    item_with_multiple_values = Project.generate!(:custom_field_values => {field.id => ['field1', 'field2'], other.id => ['other1', 'other2']})
-    item_with_single_values = Project.generate!(:custom_field_values => {field.id => ['field1'], other.id => ['other2']})
-
-    assert_difference 'CustomValue.count', -1 do
-      field.multiple = false
-      field.save!
-    end
-
-    item_with_multiple_values = Project.find(item_with_multiple_values.id)
-    assert_kind_of String, item_with_multiple_values.custom_field_value(field)
-    assert_kind_of Array, item_with_multiple_values.custom_field_value(other)
-    assert_equal 2, item_with_multiple_values.custom_field_value(other).size
-  end
-
-  def test_value_class_should_return_the_class_used_for_fields_values
-    assert_equal User, CustomField.new(:field_format => 'user').value_class
-    assert_equal Version, CustomField.new(:field_format => 'version').value_class
-  end
-
-  def test_value_class_should_return_nil_for_other_fields
-    assert_nil CustomField.new(:field_format => 'text').value_class
-    assert_nil CustomField.new.value_class
-  end
-
-  def test_value_from_keyword_for_list_custom_field
-    field = CustomField.find(1)
-    assert_equal 'PostgreSQL', field.value_from_keyword('postgresql', Issue.find(1))
-  end
-
-  def test_visibile_scope_with_admin_should_return_all_custom_fields
-    CustomField.delete_all
-    fields = [
-      CustomField.generate!(:visible => true),
-      CustomField.generate!(:visible => false),
-      CustomField.generate!(:visible => false, :role_ids => [1, 3]),
-      CustomField.generate!(:visible => false, :role_ids => [1, 2]),
-    ]
-
-    assert_equal 4, CustomField.visible(User.find(1)).count
-  end
-
-  def test_visibile_scope_with_non_admin_user_should_return_visible_custom_fields
-    CustomField.delete_all
-    fields = [
-      CustomField.generate!(:visible => true),
-      CustomField.generate!(:visible => false),
-      CustomField.generate!(:visible => false, :role_ids => [1, 3]),
-      CustomField.generate!(:visible => false, :role_ids => [1, 2]),
-    ]
-    user = User.generate!
-    User.add_to_project(user, Project.first, Role.find(3))
-
-    assert_equal [fields[0], fields[2]], CustomField.visible(user).order("id").to_a
-  end
-
-  def test_visibile_scope_with_anonymous_user_should_return_visible_custom_fields
-    CustomField.delete_all
-    fields = [
-      CustomField.generate!(:visible => true),
-      CustomField.generate!(:visible => false),
-      CustomField.generate!(:visible => false, :role_ids => [1, 3]),
-      CustomField.generate!(:visible => false, :role_ids => [1, 2]),
-    ]
-
-    assert_equal [fields[0]], CustomField.visible(User.anonymous).order("id").to_a
-  end
-end
--- a/.svn/pristine/57/570f0eb4fa534b2c22e5b144e19ab45bcea2dbda.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module SafeAttributes
-    def self.included(base)
-      base.extend(ClassMethods)
-    end
-
-    module ClassMethods
-      # Declares safe attributes
-      # An optional Proc can be given for conditional inclusion
-      #
-      # Example:
-      #   safe_attributes 'title', 'pages'
-      #   safe_attributes 'isbn', :if => {|book, user| book.author == user}
-      def safe_attributes(*args)
-        @safe_attributes ||= []
-        if args.empty?
-          if superclass.include?(Redmine::SafeAttributes)
-            @safe_attributes + superclass.safe_attributes 
-          else
-            @safe_attributes
-          end
-        else
-          options = args.last.is_a?(Hash) ? args.pop : {}
-          @safe_attributes << [args, options]
-        end
-      end
-    end
-
-    # Returns an array that can be safely set by user or current user
-    #
-    # Example:
-    #   book.safe_attributes # => ['title', 'pages']
-    #   book.safe_attributes(book.author) # => ['title', 'pages', 'isbn']
-    def safe_attribute_names(user=nil)
-      return @safe_attribute_names if @safe_attribute_names && user.nil?
-      names = []
-      self.class.safe_attributes.collect do |attrs, options|
-        if options[:if].nil? || options[:if].call(self, user || User.current)
-          names += attrs.collect(&:to_s)
-        end
-      end
-      names.uniq!
-      @safe_attribute_names = names if user.nil?
-      names
-    end
-
-    # Returns true if attr can be set by user or the current user
-    def safe_attribute?(attr, user=nil)
-      safe_attribute_names(user).include?(attr.to_s)
-    end
-
-    # Returns a hash with unsafe attributes removed
-    # from the given attrs hash
-    #
-    # Example:
-    #   book.delete_unsafe_attributes({'title' => 'My book', 'foo' => 'bar'})
-    #   # => {'title' => 'My book'}
-    def delete_unsafe_attributes(attrs, user=User.current)
-      safe = safe_attribute_names(user)
-      attrs.dup.delete_if {|k,v| !safe.include?(k)}
-    end
-
-    # Sets attributes from attrs that are safe
-    # attrs is a Hash with string keys
-    def safe_attributes=(attrs, user=User.current)
-      return unless attrs.is_a?(Hash)
-      self.attributes = delete_unsafe_attributes(attrs, user)
-    end
-  end
-end
--- a/.svn/pristine/58/58427de0be17a56a22c9ff50d1ec281682e9bdab.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-<!DOCTYPE html>
-<html lang="<%= current_language %>">
-<head>
-<meta charset="utf-8" />
-<title><%=h html_title %></title>
-<meta name="description" content="<%= Redmine::Info.app_name %>" />
-<meta name="keywords" content="issue,bug,tracker" />
-<%= csrf_meta_tag %>
-<%= favicon %>
-<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', 'application', :media => 'all' %>
-<%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %>
-<%= javascript_heads %>
-<%= heads_for_theme %>
-<%= call_hook :view_layouts_base_html_head %>
-<!-- page specific tags -->
-<%= yield :header_tags -%>
-</head>
-<body class="<%=h body_css_classes %>">
-<div id="wrapper">
-<div id="wrapper2">
-<div id="wrapper3">
-<div id="top-menu">
-    <div id="account">
-        <%= render_menu :account_menu -%>
-    </div>
-    <%= content_tag('div', "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}".html_safe, :id => 'loggedas') if User.current.logged? %>
-    <%= render_menu :top_menu if User.current.logged? || !Setting.login_required? -%>
-</div>
-
-<div id="header">
-    <% if User.current.logged? || !Setting.login_required? %>
-    <div id="quick-search">
-        <%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
-        <%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %>
-        <label for='q'>
-          <%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project}, :accesskey => accesskey(:search) %>:
-        </label>
-        <%= text_field_tag 'q', @question, :size => 20, :class => 'small', :accesskey => accesskey(:quick_search) %>
-        <% end %>
-        <%= render_project_jump_box %>
-    </div>
-    <% end %>
-
-    <h1><%= page_header_title %></h1>
-
-    <% if display_main_menu?(@project) %>
-    <div id="main-menu">
-        <%= render_main_menu(@project) %>
-    </div>
-    <% end %>
-</div>
-
-<div id="main" class="<%= sidebar_content? ? '' : 'nosidebar' %>">
-    <div id="sidebar">
-        <%= yield :sidebar %>
-        <%= view_layouts_base_sidebar_hook_response %>
-    </div>
-
-    <div id="content">
-        <%= render_flash_messages %>
-        <%= yield %>
-        <%= call_hook :view_layouts_base_content %>
-        <div style="clear:both;"></div>
-    </div>
-</div>
-</div>
-
-<div id="ajax-indicator" style="display:none;"><span><%= l(:label_loading) %></span></div>
-<div id="ajax-modal" style="display:none;"></div>
-
-<div id="footer">
-  <div class="bgl"><div class="bgr">
-    Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> &copy; 2006-2013 Jean-Philippe Lang
-  </div></div>
-</div>
-</div>
-</div>
-<%= call_hook :view_layouts_base_body_bottom %>
-</body>
-</html>
--- a/.svn/pristine/58/584923323e8dc0fd68ba4e96b679332b9ee9eb19.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::IssueStatusesTest < Redmine::ApiTest::Base
-  fixtures :issue_statuses
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /issue_statuses.xml should return issue statuses" do
-    get '/issue_statuses.xml'
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'issue_statuses',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'issue_status',
-        :child => {
-          :tag => 'id',
-          :content => '2',
-          :sibling => {
-            :tag => 'name',
-            :content => 'Assigned'
-          }
-        }
-      }
-  end
-end
--- a/.svn/pristine/58/58ad4095c1a6118f6d53fd92a945cd194604e422.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class PreviewsControllerTest < ActionController::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :journals, :journal_details,
-           :news
-
-  def test_preview_new_issue
-    @request.session[:user_id] = 2
-    post :issue, :project_id => '1', :issue => {:description => 'Foo'}
-    assert_response :success
-    assert_template 'preview'
-    assert_not_nil assigns(:description)
-  end
-
-  def test_preview_issue_notes
-    @request.session[:user_id] = 2
-    post :issue, :project_id => '1', :id => 1,
-         :issue => {:description => Issue.find(1).description, :notes => 'Foo'}
-    assert_response :success
-    assert_template 'preview'
-    assert_not_nil assigns(:notes)
-  end
-
-  def test_preview_journal_notes_for_update
-    @request.session[:user_id] = 2
-    post :issue, :project_id => '1', :id => 1, :notes => 'Foo'
-    assert_response :success
-    assert_template 'preview'
-    assert_not_nil assigns(:notes)
-    assert_tag :p, :content => 'Foo'
-  end
-
-  def test_preview_new_news
-    get :news, :project_id => 1,
-                  :news => {:title => '',
-                            :description => 'News description',
-                            :summary => ''}
-    assert_response :success
-    assert_template 'common/_preview'
-    assert_tag :tag => 'fieldset', :attributes => { :class => 'preview' },
-                                   :content => /News description/
-  end
-
-  def test_existing_new_news
-    get :news, :project_id => 1, :id => 2,
-                  :news => {:title => '',
-                            :description => 'News description',
-                            :summary => ''}
-    assert_response :success
-    assert_template 'common/_preview'
-    assert_equal News.find(2), assigns(:previewed)
-    assert_not_nil assigns(:attachments)
-
-    assert_tag :tag => 'fieldset', :attributes => { :class => 'preview' },
-                                   :content => /News description/
-  end
-end
--- a/.svn/pristine/59/59560647b1b38d17ca5eda58f2c560506ef65f44.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssuePriority < Enumeration
-  has_many :issues, :foreign_key => 'priority_id'
-
-  after_destroy {|priority| priority.class.compute_position_names}
-  after_save {|priority| priority.class.compute_position_names if priority.position_changed? && priority.position}
-
-  OptionName = :enumeration_issue_priorities
-
-  def option_name
-    OptionName
-  end
-
-  def objects_count
-    issues.count
-  end
-
-  def transfer_relations(to)
-    issues.update_all("priority_id = #{to.id}")
-  end
-
-  def css_classes
-    "priority-#{id} priority-#{position_name}"
-  end
-
-  # Clears position_name for all priorities
-  # Called from migration 20121026003537_populate_enumerations_position_name
-  def self.clear_position_names
-    update_all :position_name => nil
-  end
-
-  # Updates position_name for active priorities
-  # Called from migration 20121026003537_populate_enumerations_position_name
-  def self.compute_position_names
-    priorities = where(:active => true).all.sort_by(&:position)
-    if priorities.any?
-      default = priorities.detect(&:is_default?) || priorities[(priorities.size - 1) / 2]
-      priorities.each_with_index do |priority, index|
-        name = case
-          when priority.position == default.position
-            "default"
-          when priority.position < default.position
-            index == 0 ? "lowest" : "low#{index+1}"
-          else
-            index == (priorities.size - 1) ? "highest" : "high#{priorities.size - index}"
-          end
-
-        update_all({:position_name => name}, :id => priority.id)
-      end
-    end
-  end
-end
--- a/.svn/pristine/59/5957c73ec3e45b1dba5f2bd95614bcd541de4b15.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class WorkflowsController < ApplicationController
-  layout 'admin'
-
-  before_filter :require_admin, :find_roles, :find_trackers
-
-  def index
-    @workflow_counts = WorkflowTransition.count_by_tracker_and_role
-  end
-
-  def edit
-    @role = Role.find_by_id(params[:role_id]) if params[:role_id]
-    @tracker = Tracker.find_by_id(params[:tracker_id]) if params[:tracker_id]
-
-    if request.post?
-      WorkflowTransition.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
-      (params[:issue_status] || []).each { |status_id, transitions|
-        transitions.each { |new_status_id, options|
-          author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
-          assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
-          WorkflowTransition.create(:role_id => @role.id, :tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
-        }
-      }
-      if @role.save
-        redirect_to workflows_edit_path(:role_id => @role, :tracker_id => @tracker, :used_statuses_only => params[:used_statuses_only])
-        return
-      end
-    end
-
-    @used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
-    if @tracker && @used_statuses_only && @tracker.issue_statuses.any?
-      @statuses = @tracker.issue_statuses
-    end
-    @statuses ||= IssueStatus.sorted.all
-
-    if @tracker && @role && @statuses.any?
-      workflows = WorkflowTransition.where(:role_id => @role.id, :tracker_id => @tracker.id).all
-      @workflows = {}
-      @workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
-      @workflows['author'] = workflows.select {|w| w.author}
-      @workflows['assignee'] = workflows.select {|w| w.assignee}
-    end
-  end
-
-  def permissions
-    @role = Role.find_by_id(params[:role_id]) if params[:role_id]
-    @tracker = Tracker.find_by_id(params[:tracker_id]) if params[:tracker_id]
-
-    if request.post? && @role && @tracker
-      WorkflowPermission.replace_permissions(@tracker, @role, params[:permissions] || {})
-      redirect_to workflows_permissions_path(:role_id => @role, :tracker_id => @tracker, :used_statuses_only => params[:used_statuses_only])
-      return
-    end
-
-    @used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
-    if @tracker && @used_statuses_only && @tracker.issue_statuses.any?
-      @statuses = @tracker.issue_statuses
-    end
-    @statuses ||= IssueStatus.sorted.all
-
-    if @role && @tracker
-      @fields = (Tracker::CORE_FIELDS_ALL - @tracker.disabled_core_fields).map {|field| [field, l("field_"+field.sub(/_id$/, ''))]}
-      @custom_fields = @tracker.custom_fields
-
-      @permissions = WorkflowPermission.where(:tracker_id => @tracker.id, :role_id => @role.id).all.inject({}) do |h, w|
-        h[w.old_status_id] ||= {}
-        h[w.old_status_id][w.field_name] = w.rule
-        h
-      end
-      @statuses.each {|status| @permissions[status.id] ||= {}}
-    end
-  end
-
-  def copy
-
-    if params[:source_tracker_id].blank? || params[:source_tracker_id] == 'any'
-      @source_tracker = nil
-    else
-      @source_tracker = Tracker.find_by_id(params[:source_tracker_id].to_i)
-    end
-    if params[:source_role_id].blank? || params[:source_role_id] == 'any'
-      @source_role = nil
-    else
-      @source_role = Role.find_by_id(params[:source_role_id].to_i)
-    end
-
-    @target_trackers = params[:target_tracker_ids].blank? ? nil : Tracker.find_all_by_id(params[:target_tracker_ids])
-    @target_roles = params[:target_role_ids].blank? ? nil : Role.find_all_by_id(params[:target_role_ids])
-
-    if request.post?
-      if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?)
-        flash.now[:error] = l(:error_workflow_copy_source)
-      elsif @target_trackers.blank? || @target_roles.blank?
-        flash.now[:error] = l(:error_workflow_copy_target)
-      else
-        WorkflowRule.copy(@source_tracker, @source_role, @target_trackers, @target_roles)
-        flash[:notice] = l(:notice_successful_update)
-        redirect_to workflows_copy_path(:source_tracker_id => @source_tracker, :source_role_id => @source_role)
-      end
-    end
-  end
-
-  private
-
-  def find_roles
-    @roles = Role.sorted.all
-  end
-
-  def find_trackers
-    @trackers = Tracker.sorted.all
-  end
-end
--- a/.svn/pristine/5b/5b5912958e71fec54e66733c9c7981555c23902f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::HttpBasicLoginWithApiTokenTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def setup
-    Setting.rest_api_enabled = '1'
-    Setting.login_required = '1'
-  end
-
-  def teardown
-    Setting.rest_api_enabled = '0'
-    Setting.login_required = '0'
-  end
-
-  # Using the NewsController because it's a simple API.
-  context "get /news" do
-
-    context "in :xml format" do
-      should_allow_http_basic_auth_with_key(:get, "/news.xml")
-    end
-
-    context "in :json format" do
-      should_allow_http_basic_auth_with_key(:get, "/news.json")
-    end
-  end
-end
--- a/.svn/pristine/5b/5b67cbc43876349cb50763840008cc0544dfb9b5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class GroupTest < ActiveSupport::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :groups_users
-
-  include Redmine::I18n
-
-  def test_create
-    g = Group.new(:name => 'New group')
-    assert g.save
-    g.reload
-    assert_equal 'New group', g.name
-  end
-
-  def test_name_should_accept_255_characters
-    name = 'a' * 255
-    g = Group.new(:name => name)
-    assert g.save
-    g.reload
-    assert_equal name, g.name
-  end
-
-  def test_blank_name_error_message
-    set_language_if_valid 'en'
-    g = Group.new
-    assert !g.save
-    assert_include "Name can't be blank", g.errors.full_messages
-  end
-
-  def test_blank_name_error_message_fr
-    set_language_if_valid 'fr'
-    str = "Nom doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    g = Group.new
-    assert !g.save
-    assert_include str, g.errors.full_messages
-  end
-
-  def test_group_roles_should_be_given_to_added_user
-    group = Group.find(11)
-    user = User.find(9)
-    project = Project.first
-
-    Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
-    group.users << user
-    assert user.member_of?(project)
-  end
-
-  def test_new_roles_should_be_given_to_existing_user
-    group = Group.find(11)
-    user = User.find(9)
-    project = Project.first
-
-    group.users << user
-    m = Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
-    assert user.member_of?(project)
-  end
-
-  def test_user_roles_should_updated_when_updating_user_ids
-    group = Group.find(11)
-    user = User.find(9)
-    project = Project.first
-
-    Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
-    group.user_ids = [user.id]
-    group.save!
-    assert User.find(9).member_of?(project)
-
-    group.user_ids = [1]
-    group.save!
-    assert !User.find(9).member_of?(project)
-  end
-
-  def test_user_roles_should_updated_when_updating_group_roles
-    group = Group.find(11)
-    user = User.find(9)
-    project = Project.first
-    group.users << user
-    m = Member.create!(:principal => group, :project => project, :role_ids => [1])
-    assert_equal [1], user.reload.roles_for_project(project).collect(&:id).sort
-
-    m.role_ids = [1, 2]
-    assert_equal [1, 2], user.reload.roles_for_project(project).collect(&:id).sort
-
-    m.role_ids = [2]
-    assert_equal [2], user.reload.roles_for_project(project).collect(&:id).sort
-
-    m.role_ids = [1]
-    assert_equal [1], user.reload.roles_for_project(project).collect(&:id).sort
-  end
-
-  def test_user_memberships_should_be_removed_when_removing_group_membership
-    assert User.find(8).member_of?(Project.find(5))
-    Member.find_by_project_id_and_user_id(5, 10).destroy
-    assert !User.find(8).member_of?(Project.find(5))
-  end
-
-  def test_user_roles_should_be_removed_when_removing_user_from_group
-    assert User.find(8).member_of?(Project.find(5))
-    User.find(8).groups = []
-    assert !User.find(8).member_of?(Project.find(5))
-  end
-
-  def test_destroy_should_unassign_issues
-    group = Group.first
-    Issue.update_all(["assigned_to_id = ?", group.id], 'id = 1')
-
-    assert group.destroy
-    assert group.destroyed?
-
-    assert_equal nil, Issue.find(1).assigned_to_id
-  end
-end
--- a/.svn/pristine/5b/5bd58dbcc9700e9a0143a2bd31d516491119c122.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'zlib'
-
-class WikiContent < ActiveRecord::Base
-  self.locking_column = 'version'
-  belongs_to :page, :class_name => 'WikiPage', :foreign_key => 'page_id'
-  belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
-  validates_presence_of :text
-  validates_length_of :comments, :maximum => 255, :allow_nil => true
-
-  acts_as_versioned
-
-  after_save :send_notification
-
-  def visible?(user=User.current)
-    page.visible?(user)
-  end
-
-  def project
-    page.project
-  end
-
-  def attachments
-    page.nil? ? [] : page.attachments
-  end
-
-  # Returns the mail adresses of users that should be notified
-  def recipients
-    notified = project.notified_users
-    notified.reject! {|user| !visible?(user)}
-    notified.collect(&:mail)
-  end
-
-  # Return true if the content is the current page content
-  def current_version?
-    true
-  end
-
-  class Version
-    belongs_to :page, :class_name => '::WikiPage', :foreign_key => 'page_id'
-    belongs_to :author, :class_name => '::User', :foreign_key => 'author_id'
-    attr_protected :data
-
-    acts_as_event :title => Proc.new {|o| "#{l(:label_wiki_edit)}: #{o.page.title} (##{o.version})"},
-                  :description => :comments,
-                  :datetime => :updated_on,
-                  :type => 'wiki-page',
-                  :group => :page,
-                  :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.page.wiki.project, :id => o.page.title, :version => o.version}}
-
-    acts_as_activity_provider :type => 'wiki_edits',
-                              :timestamp => "#{WikiContent.versioned_table_name}.updated_on",
-                              :author_key => "#{WikiContent.versioned_table_name}.author_id",
-                              :permission => :view_wiki_edits,
-                              :find_options => {:select => "#{WikiContent.versioned_table_name}.updated_on, #{WikiContent.versioned_table_name}.comments, " +
-                                                           "#{WikiContent.versioned_table_name}.#{WikiContent.version_column}, #{WikiPage.table_name}.title, " +
-                                                           "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " +
-                                                           "#{WikiContent.versioned_table_name}.id",
-                                                :joins => "LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " +
-                                                          "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id " +
-                                                          "LEFT JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Wiki.table_name}.project_id"}
-
-    after_destroy :page_update_after_destroy
-
-    def text=(plain)
-      case Setting.wiki_compression
-      when 'gzip'
-      begin
-        self.data = Zlib::Deflate.deflate(plain, Zlib::BEST_COMPRESSION)
-        self.compression = 'gzip'
-      rescue
-        self.data = plain
-        self.compression = ''
-      end
-      else
-        self.data = plain
-        self.compression = ''
-      end
-      plain
-    end
-
-    def text
-      @text ||= begin
-        str = case compression
-              when 'gzip'
-                Zlib::Inflate.inflate(data)
-              else
-                # uncompressed data
-                data
-              end
-        str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
-        str
-      end
-    end
-
-    def project
-      page.project
-    end
-
-    # Return true if the content is the current page content
-    def current_version?
-      page.content.version == self.version
-    end
-
-    # Returns the previous version or nil
-    def previous
-      @previous ||= WikiContent::Version.
-        reorder('version DESC').
-        includes(:author).
-        where("wiki_content_id = ? AND version < ?", wiki_content_id, version).first
-    end
-
-    # Returns the next version or nil
-    def next
-      @next ||= WikiContent::Version.
-        reorder('version ASC').
-        includes(:author).
-        where("wiki_content_id = ? AND version > ?", wiki_content_id, version).first
-    end
-
-    private
-
-    # Updates page's content if the latest version is removed
-    # or destroys the page if it was the only version
-    def page_update_after_destroy
-      latest = page.content.versions.reorder("#{self.class.table_name}.version DESC").first
-      if latest && page.content.version != latest.version
-        raise ActiveRecord::Rollback unless page.content.revert_to!(latest)
-      elsif latest.nil?
-        raise ActiveRecord::Rollback unless page.destroy
-      end
-    end
-  end
-
-  private
-
-  def send_notification
-    # new_record? returns false in after_save callbacks
-    if id_changed?
-      if Setting.notified_events.include?('wiki_content_added')
-        Mailer.wiki_content_added(self).deliver
-      end
-    elsif text_changed?
-      if Setting.notified_events.include?('wiki_content_updated')
-        Mailer.wiki_content_updated(self).deliver
-      end
-    end
-  end
-end
--- a/.svn/pristine/5c/5c1734e1eca1c54bac30b17ddeecdedbc05caf30.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-
-namespace :db do
-  desc 'Encrypts SCM and LDAP passwords in the database.'
-  task :encrypt => :environment do
-    unless (Repository.encrypt_all(:password) &&
-      AuthSource.encrypt_all(:account_password))
-      raise "Some objects could not be saved after encryption, update was rollback'ed."
-    end
-  end
-
-  desc 'Decrypts SCM and LDAP passwords in the database.'
-  task :decrypt => :environment do
-    unless (Repository.decrypt_all(:password) &&
-      AuthSource.decrypt_all(:account_password))
-      raise "Some objects could not be saved after decryption, update was rollback'ed."
-    end
-  end
-end
--- a/.svn/pristine/5c/5cefc982f83157ee64c82964ccc1a3e15fc78cb5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,356 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-# The WikiController follows the Rails REST controller pattern but with
-# a few differences
-#
-# * index - shows a list of WikiPages grouped by page or date
-# * new - not used
-# * create - not used
-# * show - will also show the form for creating a new wiki page
-# * edit - used to edit an existing or new page
-# * update - used to save a wiki page update to the database, including new pages
-# * destroy - normal
-#
-# Other member and collection methods are also used
-#
-# TODO: still being worked on
-class WikiController < ApplicationController
-  default_search_scope :wiki_pages
-  before_filter :find_wiki, :authorize
-  before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
-  before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
-  accept_api_auth :index, :show, :update, :destroy
-  before_filter :find_attachments, :only => [:preview]
-
-  helper :attachments
-  include AttachmentsHelper
-  helper :watchers
-  include Redmine::Export::PDF
-
-  # List of pages, sorted alphabetically and by parent (hierarchy)
-  def index
-    load_pages_for_index
-
-    respond_to do |format|
-      format.html {
-        @pages_by_parent_id = @pages.group_by(&:parent_id)
-      }
-      format.api
-    end
-  end
-
-  # List of page, by last update
-  def date_index
-    load_pages_for_index
-    @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
-  end
-
-  # display a page (in editing mode if it doesn't exist)
-  def show
-    if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
-      deny_access
-      return
-    end
-    @content = @page.content_for_version(params[:version])
-    if @content.nil?
-      if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? && !api_request?
-        edit
-        render :action => 'edit'
-      else
-        render_404
-      end
-      return
-    end
-    if User.current.allowed_to?(:export_wiki_pages, @project)
-      if params[:format] == 'pdf'
-        send_data(wiki_page_to_pdf(@page, @project), :type => 'application/pdf', :filename => "#{@page.title}.pdf")
-        return
-      elsif params[:format] == 'html'
-        export = render_to_string :action => 'export', :layout => false
-        send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
-        return
-      elsif params[:format] == 'txt'
-        send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
-        return
-      end
-    end
-    @editable = editable?
-    @sections_editable = @editable && User.current.allowed_to?(:edit_wiki_pages, @page.project) &&
-      @content.current_version? &&
-      Redmine::WikiFormatting.supports_section_edit?
-
-    respond_to do |format|
-      format.html
-      format.api
-    end
-  end
-
-  # edit an existing page or a new one
-  def edit
-    return render_403 unless editable?
-    if @page.new_record?
-      if params[:parent].present?
-        @page.parent = @page.wiki.find_page(params[:parent].to_s)
-      end
-    end
-
-    @content = @page.content_for_version(params[:version])
-    @content ||= WikiContent.new(:page => @page)
-    @content.text = initial_page_content(@page) if @content.text.blank?
-    # don't keep previous comment
-    @content.comments = nil
-
-    # To prevent StaleObjectError exception when reverting to a previous version
-    @content.version = @page.content.version if @page.content
-
-    @text = @content.text
-    if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
-      @section = params[:section].to_i
-      @text, @section_hash = Redmine::WikiFormatting.formatter.new(@text).get_section(@section)
-      render_404 if @text.blank?
-    end
-  end
-
-  # Creates a new page or updates an existing one
-  def update
-    return render_403 unless editable?
-    was_new_page = @page.new_record?
-    @page.safe_attributes = params[:wiki_page]
-
-    @content = @page.content || WikiContent.new(:page => @page)
-    content_params = params[:content]
-    if content_params.nil? && params[:wiki_page].is_a?(Hash)
-      content_params = params[:wiki_page].slice(:text, :comments, :version)
-    end
-    content_params ||= {}
-
-    @content.comments = content_params[:comments]
-    @text = content_params[:text]
-    if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
-      @section = params[:section].to_i
-      @section_hash = params[:section_hash]
-      @content.text = Redmine::WikiFormatting.formatter.new(@content.text).update_section(@section, @text, @section_hash)
-    else
-      @content.version = content_params[:version] if content_params[:version]
-      @content.text = @text
-    end
-    @content.author = User.current
-
-    if @page.save_with_content(@content)
-      attachments = Attachment.attach_files(@page, params[:attachments])
-      render_attachment_warning_if_needed(@page)
-      call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
-
-      respond_to do |format|
-        format.html {
-          anchor = @section ? "section-#{@section}" : nil
-          redirect_to project_wiki_page_path(@project, @page.title, :anchor => anchor)
-        }
-        format.api {
-          if was_new_page
-            render :action => 'show', :status => :created, :location => project_wiki_page_path(@project, @page.title)
-          else
-            render_api_ok
-          end
-        }
-      end
-    else
-      respond_to do |format|
-        format.html { render :action => 'edit' }
-        format.api { render_validation_errors(@content) }
-      end
-    end
-
-  rescue ActiveRecord::StaleObjectError, Redmine::WikiFormatting::StaleSectionError
-    # Optimistic locking exception
-    respond_to do |format|
-      format.html {
-        flash.now[:error] = l(:notice_locking_conflict)
-        render :action => 'edit'
-      }
-      format.api { render_api_head :conflict }
-    end
-  rescue ActiveRecord::RecordNotSaved
-    respond_to do |format|
-      format.html { render :action => 'edit' }
-      format.api { render_validation_errors(@content) }
-    end
-  end
-
-  # rename a page
-  def rename
-    return render_403 unless editable?
-    @page.redirect_existing_links = true
-    # used to display the *original* title if some AR validation errors occur
-    @original_title = @page.pretty_title
-    if request.post? && @page.update_attributes(params[:wiki_page])
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to project_wiki_page_path(@project, @page.title)
-    end
-  end
-
-  def protect
-    @page.update_attribute :protected, params[:protected]
-    redirect_to project_wiki_page_path(@project, @page.title)
-  end
-
-  # show page history
-  def history
-    @version_count = @page.content.versions.count
-    @version_pages = Paginator.new @version_count, per_page_option, params['page']
-    # don't load text
-    @versions = @page.content.versions.
-      select("id, author_id, comments, updated_on, version").
-      reorder('version DESC').
-      limit(@version_pages.per_page + 1).
-      offset(@version_pages.offset).
-      all
-
-    render :layout => false if request.xhr?
-  end
-
-  def diff
-    @diff = @page.diff(params[:version], params[:version_from])
-    render_404 unless @diff
-  end
-
-  def annotate
-    @annotate = @page.annotate(params[:version])
-    render_404 unless @annotate
-  end
-
-  # Removes a wiki page and its history
-  # Children can be either set as root pages, removed or reassigned to another parent page
-  def destroy
-    return render_403 unless editable?
-
-    @descendants_count = @page.descendants.size
-    if @descendants_count > 0
-      case params[:todo]
-      when 'nullify'
-        # Nothing to do
-      when 'destroy'
-        # Removes all its descendants
-        @page.descendants.each(&:destroy)
-      when 'reassign'
-        # Reassign children to another parent page
-        reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
-        return unless reassign_to
-        @page.children.each do |child|
-          child.update_attribute(:parent, reassign_to)
-        end
-      else
-        @reassignable_to = @wiki.pages - @page.self_and_descendants
-        # display the destroy form if it's a user request
-        return unless api_request?
-      end
-    end
-    @page.destroy
-    respond_to do |format|
-      format.html { redirect_to project_wiki_index_path(@project) }
-      format.api { render_api_ok }
-    end
-  end
-
-  def destroy_version
-    return render_403 unless editable?
-
-    @content = @page.content_for_version(params[:version])
-    @content.destroy
-    redirect_to_referer_or history_project_wiki_page_path(@project, @page.title)
-  end
-
-  # Export wiki to a single pdf or html file
-  def export
-    @pages = @wiki.pages.all(:order => 'title', :include => [:content, {:attachments => :author}])
-    respond_to do |format|
-      format.html {
-        export = render_to_string :action => 'export_multiple', :layout => false
-        send_data(export, :type => 'text/html', :filename => "wiki.html")
-      }
-      format.pdf {
-        send_data(wiki_pages_to_pdf(@pages, @project), :type => 'application/pdf', :filename => "#{@project.identifier}.pdf")
-      }
-    end
-  end
-
-  def preview
-    page = @wiki.find_page(params[:id])
-    # page is nil when previewing a new page
-    return render_403 unless page.nil? || editable?(page)
-    if page
-      @attachments += page.attachments
-      @previewed = page.content
-    end
-    @text = params[:content][:text]
-    render :partial => 'common/preview'
-  end
-
-  def add_attachment
-    return render_403 unless editable?
-    attachments = Attachment.attach_files(@page, params[:attachments])
-    render_attachment_warning_if_needed(@page)
-    redirect_to :action => 'show', :id => @page.title, :project_id => @project
-  end
-
-private
-
-  def find_wiki
-    @project = Project.find(params[:project_id])
-    @wiki = @project.wiki
-    render_404 unless @wiki
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  # Finds the requested page or a new page if it doesn't exist
-  def find_existing_or_new_page
-    @page = @wiki.find_or_new_page(params[:id])
-    if @wiki.page_found_with_redirect?
-      redirect_to params.update(:id => @page.title)
-    end
-  end
-
-  # Finds the requested page and returns a 404 error if it doesn't exist
-  def find_existing_page
-    @page = @wiki.find_page(params[:id])
-    if @page.nil?
-      render_404
-      return
-    end
-    if @wiki.page_found_with_redirect?
-      redirect_to params.update(:id => @page.title)
-    end
-  end
-
-  # Returns true if the current user is allowed to edit the page, otherwise false
-  def editable?(page = @page)
-    page.editable_by?(User.current)
-  end
-
-  # Returns the default content of a new wiki page
-  def initial_page_content(page)
-    helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
-    extend helper unless self.instance_of?(helper)
-    helper.instance_method(:initial_page_content).bind(self).call(page)
-  end
-
-  def load_pages_for_index
-    @pages = @wiki.pages.with_updated_on.reorder("#{WikiPage.table_name}.title").includes(:wiki => :project).includes(:parent).all
-  end
-end
--- a/.svn/pristine/5d/5d26bd43e6982490a87abc50362d543225e9666c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Change < ActiveRecord::Base
-  belongs_to :changeset
-
-  validates_presence_of :changeset_id, :action, :path
-  before_save :init_path
-  before_validation :replace_invalid_utf8_of_path
-
-  def relative_path
-    changeset.repository.relative_path(path)
-  end
-
-  def replace_invalid_utf8_of_path
-    self.path      = Redmine::CodesetUtil.replace_invalid_utf8(self.path)
-    self.from_path = Redmine::CodesetUtil.replace_invalid_utf8(self.from_path)
-  end
-
-  def init_path
-    self.path ||= ""
-  end
-end
--- a/.svn/pristine/5f/5f34122110535f3ec5de210020321433576b63f3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module DefaultData
-    class DataAlreadyLoaded < Exception; end
-
-    module Loader
-      include Redmine::I18n
-
-      class << self
-        # Returns true if no data is already loaded in the database
-        # otherwise false
-        def no_data?
-          !Role.where(:builtin => 0).exists? &&
-            !Tracker.exists? &&
-            !IssueStatus.exists? &&
-            !Enumeration.exists?
-        end
-
-        # Loads the default data
-        # Raises a RecordNotSaved exception if something goes wrong
-        def load(lang=nil)
-          raise DataAlreadyLoaded.new("Some configuration data is already loaded.") unless no_data?
-          set_language_if_valid(lang)
-
-          Role.transaction do
-            # Roles
-            manager = Role.create! :name => l(:default_role_manager),
-                                   :issues_visibility => 'all',
-                                   :position => 1
-            manager.permissions = manager.setable_permissions.collect {|p| p.name}
-            manager.save!
-
-            developer = Role.create!  :name => l(:default_role_developer),
-                                      :position => 2,
-                                      :permissions => [:manage_versions,
-                                                      :manage_categories,
-                                                      :view_issues,
-                                                      :add_issues,
-                                                      :edit_issues,
-                                                      :view_private_notes,
-                                                      :set_notes_private,
-                                                      :manage_issue_relations,
-                                                      :manage_subtasks,
-                                                      :add_issue_notes,
-                                                      :save_queries,
-                                                      :view_gantt,
-                                                      :view_calendar,
-                                                      :log_time,
-                                                      :view_time_entries,
-                                                      :comment_news,
-                                                      :view_documents,
-                                                      :view_wiki_pages,
-                                                      :view_wiki_edits,
-                                                      :edit_wiki_pages,
-                                                      :delete_wiki_pages,
-                                                      :add_messages,
-                                                      :edit_own_messages,
-                                                      :view_files,
-                                                      :manage_files,
-                                                      :browse_repository,
-                                                      :view_changesets,
-                                                      :commit_access,
-                                                      :manage_related_issues]
-
-            reporter = Role.create! :name => l(:default_role_reporter),
-                                    :position => 3,
-                                    :permissions => [:view_issues,
-                                                    :add_issues,
-                                                    :add_issue_notes,
-                                                    :save_queries,
-                                                    :view_gantt,
-                                                    :view_calendar,
-                                                    :log_time,
-                                                    :view_time_entries,
-                                                    :comment_news,
-                                                    :view_documents,
-                                                    :view_wiki_pages,
-                                                    :view_wiki_edits,
-                                                    :add_messages,
-                                                    :edit_own_messages,
-                                                    :view_files,
-                                                    :browse_repository,
-                                                    :view_changesets]
-
-            Role.non_member.update_attribute :permissions, [:view_issues,
-                                                            :add_issues,
-                                                            :add_issue_notes,
-                                                            :save_queries,
-                                                            :view_gantt,
-                                                            :view_calendar,
-                                                            :view_time_entries,
-                                                            :comment_news,
-                                                            :view_documents,
-                                                            :view_wiki_pages,
-                                                            :view_wiki_edits,
-                                                            :add_messages,
-                                                            :view_files,
-                                                            :browse_repository,
-                                                            :view_changesets]
-
-            Role.anonymous.update_attribute :permissions, [:view_issues,
-                                                           :view_gantt,
-                                                           :view_calendar,
-                                                           :view_time_entries,
-                                                           :view_documents,
-                                                           :view_wiki_pages,
-                                                           :view_wiki_edits,
-                                                           :view_files,
-                                                           :browse_repository,
-                                                           :view_changesets]
-
-            # Trackers
-            Tracker.create!(:name => l(:default_tracker_bug),     :is_in_chlog => true,  :is_in_roadmap => false, :position => 1)
-            Tracker.create!(:name => l(:default_tracker_feature), :is_in_chlog => true,  :is_in_roadmap => true,  :position => 2)
-            Tracker.create!(:name => l(:default_tracker_support), :is_in_chlog => false, :is_in_roadmap => false, :position => 3)
-
-            # Issue statuses
-            new       = IssueStatus.create!(:name => l(:default_issue_status_new), :is_closed => false, :is_default => true, :position => 1)
-            in_progress  = IssueStatus.create!(:name => l(:default_issue_status_in_progress), :is_closed => false, :is_default => false, :position => 2)
-            resolved  = IssueStatus.create!(:name => l(:default_issue_status_resolved), :is_closed => false, :is_default => false, :position => 3)
-            feedback  = IssueStatus.create!(:name => l(:default_issue_status_feedback), :is_closed => false, :is_default => false, :position => 4)
-            closed    = IssueStatus.create!(:name => l(:default_issue_status_closed), :is_closed => true, :is_default => false, :position => 5)
-            rejected  = IssueStatus.create!(:name => l(:default_issue_status_rejected), :is_closed => true, :is_default => false, :position => 6)
-
-            # Workflow
-            Tracker.all.each { |t|
-              IssueStatus.all.each { |os|
-                IssueStatus.all.each { |ns|
-                  WorkflowTransition.create!(:tracker_id => t.id, :role_id => manager.id, :old_status_id => os.id, :new_status_id => ns.id) unless os == ns
-                }
-              }
-            }
-
-            Tracker.all.each { |t|
-              [new, in_progress, resolved, feedback].each { |os|
-                [in_progress, resolved, feedback, closed].each { |ns|
-                  WorkflowTransition.create!(:tracker_id => t.id, :role_id => developer.id, :old_status_id => os.id, :new_status_id => ns.id) unless os == ns
-                }
-              }
-            }
-
-            Tracker.all.each { |t|
-              [new, in_progress, resolved, feedback].each { |os|
-                [closed].each { |ns|
-                  WorkflowTransition.create!(:tracker_id => t.id, :role_id => reporter.id, :old_status_id => os.id, :new_status_id => ns.id) unless os == ns
-                }
-              }
-              WorkflowTransition.create!(:tracker_id => t.id, :role_id => reporter.id, :old_status_id => resolved.id, :new_status_id => feedback.id)
-            }
-
-            # Enumerations
-            IssuePriority.create!(:name => l(:default_priority_low), :position => 1)
-            IssuePriority.create!(:name => l(:default_priority_normal), :position => 2, :is_default => true)
-            IssuePriority.create!(:name => l(:default_priority_high), :position => 3)
-            IssuePriority.create!(:name => l(:default_priority_urgent), :position => 4)
-            IssuePriority.create!(:name => l(:default_priority_immediate), :position => 5)
-
-            DocumentCategory.create!(:name => l(:default_doc_category_user), :position => 1)
-            DocumentCategory.create!(:name => l(:default_doc_category_tech), :position => 2)
-
-            TimeEntryActivity.create!(:name => l(:default_activity_design), :position => 1)
-            TimeEntryActivity.create!(:name => l(:default_activity_development), :position => 2)
-          end
-          true
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/5f/5f91c8ec766f59461497fadde2dab5afeb5e2ac6.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::NotifiableTest < ActiveSupport::TestCase
-  def setup
-  end
-
-  def test_all
-    assert_equal 12, Redmine::Notifiable.all.length
-
-    %w(issue_added issue_updated issue_note_added issue_status_updated issue_priority_updated news_added news_comment_added document_added file_added message_posted wiki_content_added wiki_content_updated).each do |notifiable|
-      assert Redmine::Notifiable.all.collect(&:name).include?(notifiable), "missing #{notifiable}"
-    end
-  end
-end
--- a/.svn/pristine/60/60a95a1966b625bd87358ca8fc028478e501f2bb.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::GroupsTest < Redmine::ApiTest::Base
-  fixtures :users, :groups_users
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /groups.xml should require authentication" do
-    get '/groups.xml'
-    assert_response 401
-  end
-
-  test "GET /groups.xml should return groups" do
-    get '/groups.xml', {}, credentials('admin')
-    assert_response :success
-    assert_equal 'application/xml', response.content_type
-
-    assert_select 'groups' do
-      assert_select 'group' do
-        assert_select 'name', :text => 'A Team'
-        assert_select 'id', :text => '10'
-      end
-    end
-  end
-
-  test "GET /groups.json should require authentication" do
-    get '/groups.json'
-    assert_response 401
-  end
-
-  test "GET /groups.json should return groups" do
-    get '/groups.json', {}, credentials('admin')
-    assert_response :success
-    assert_equal 'application/json', response.content_type
-
-    json = MultiJson.load(response.body)
-    groups = json['groups']
-    assert_kind_of Array, groups
-    group = groups.detect {|g| g['name'] == 'A Team'}
-    assert_not_nil group
-    assert_equal({'id' => 10, 'name' => 'A Team'}, group)
-  end
-
-  test "GET /groups/:id.xml should return the group with its users" do
-    get '/groups/10.xml', {}, credentials('admin')
-    assert_response :success
-    assert_equal 'application/xml', response.content_type
-
-    assert_select 'group' do
-      assert_select 'name', :text => 'A Team'
-      assert_select 'id', :text => '10'
-    end
-  end
-
-  test "GET /groups/:id.xml should include users if requested" do
-    get '/groups/10.xml?include=users', {}, credentials('admin')
-    assert_response :success
-    assert_equal 'application/xml', response.content_type
-
-    assert_select 'group' do
-      assert_select 'users' do
-        assert_select 'user', Group.find(10).users.count
-        assert_select 'user[id=8]'
-      end
-    end
-  end
-
-  test "GET /groups/:id.xml include memberships if requested" do
-    get '/groups/10.xml?include=memberships', {}, credentials('admin')
-    assert_response :success
-    assert_equal 'application/xml', response.content_type
-
-    assert_select 'group' do
-      assert_select 'memberships'
-    end
-  end
-
-  test "POST /groups.xml with valid parameters should create the group" do
-    assert_difference('Group.count') do
-      post '/groups.xml', {:group => {:name => 'Test', :user_ids => [2, 3]}}, credentials('admin')
-      assert_response :created
-      assert_equal 'application/xml', response.content_type
-    end
-
-    group = Group.order('id DESC').first
-    assert_equal 'Test', group.name
-    assert_equal [2, 3], group.users.map(&:id).sort
-
-    assert_select 'group' do
-      assert_select 'name', :text => 'Test'
-    end
-  end
-
-  test "POST /groups.xml with invalid parameters should return errors" do
-    assert_no_difference('Group.count') do
-      post '/groups.xml', {:group => {:name => ''}}, credentials('admin')
-    end
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', response.content_type
-
-    assert_select 'errors' do
-      assert_select 'error', :text => /Name can't be blank/
-    end
-  end
-
-  test "PUT /groups/:id.xml with valid parameters should update the group" do
-    put '/groups/10.xml', {:group => {:name => 'New name', :user_ids => [2, 3]}}, credentials('admin')
-    assert_response :ok
-    assert_equal '', @response.body
-
-    group = Group.find(10)
-    assert_equal 'New name', group.name
-    assert_equal [2, 3], group.users.map(&:id).sort
-  end
-
-  test "PUT /groups/:id.xml with invalid parameters should return errors" do
-    put '/groups/10.xml', {:group => {:name => ''}}, credentials('admin')
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', response.content_type
-
-    assert_select 'errors' do
-      assert_select 'error', :text => /Name can't be blank/
-    end
-  end
-
-  test "DELETE /groups/:id.xml should delete the group" do
-    assert_difference 'Group.count', -1 do
-      delete '/groups/10.xml', {}, credentials('admin')
-      assert_response :ok
-      assert_equal '', @response.body
-    end
-  end
-
-  test "POST /groups/:id/users.xml should add user to the group" do
-    assert_difference 'Group.find(10).users.count' do
-      post '/groups/10/users.xml', {:user_id => 5}, credentials('admin')
-      assert_response :ok
-      assert_equal '', @response.body
-    end
-    assert_include User.find(5), Group.find(10).users
-  end
-
-  test "DELETE /groups/:id/users/:user_id.xml should remove user from the group" do
-    assert_difference 'Group.find(10).users.count', -1 do
-      delete '/groups/10/users/8.xml', {}, credentials('admin')
-      assert_response :ok
-      assert_equal '', @response.body
-    end
-    assert_not_include User.find(8), Group.find(10).users
-  end
-end
--- a/.svn/pristine/61/61f5175c584e56d932e6fd6922f31fce1b57acd4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssueRelationsController < ApplicationController
-  before_filter :find_issue, :find_project_from_association, :authorize, :only => [:index, :create]
-  before_filter :find_relation, :except => [:index, :create]
-
-  accept_api_auth :index, :show, :create, :destroy
-
-  def index
-    @relations = @issue.relations
-
-    respond_to do |format|
-      format.html { render :nothing => true }
-      format.api
-    end
-  end
-
-  def show
-    raise Unauthorized unless @relation.visible?
-
-    respond_to do |format|
-      format.html { render :nothing => true }
-      format.api
-    end
-  end
-
-  def create
-    @relation = IssueRelation.new(params[:relation])
-    @relation.issue_from = @issue
-    if params[:relation] && m = params[:relation][:issue_to_id].to_s.strip.match(/^#?(\d+)$/)
-      @relation.issue_to = Issue.visible.find_by_id(m[1].to_i)
-    end
-    saved = @relation.save
-
-    respond_to do |format|
-      format.html { redirect_to issue_path(@issue) }
-      format.js {
-        @relations = @issue.reload.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
-      }
-      format.api {
-        if saved
-          render :action => 'show', :status => :created, :location => relation_url(@relation)
-        else
-          render_validation_errors(@relation)
-        end
-      }
-    end
-  end
-
-  def destroy
-    raise Unauthorized unless @relation.deletable?
-    @relation.destroy
-
-    respond_to do |format|
-      format.html { redirect_to issue_path(@relation.issue_from) }
-      format.js
-      format.api  { render_api_ok }
-    end
-  end
-
-private
-  def find_issue
-    @issue = @object = Issue.find(params[:issue_id])
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def find_relation
-    @relation = IssueRelation.find(params[:id])
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/63/6303e4e27f22b7c0923d90722df3a66861c6f0f3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,950 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Helpers
-    # Simple class to handle gantt chart data
-    class Gantt
-      include ERB::Util
-      include Redmine::I18n
-      include Redmine::Utils::DateCalculation
-
-      # Relation types that are rendered
-      DRAW_TYPES = {
-        IssueRelation::TYPE_BLOCKS   => { :landscape_margin => 16, :color => '#F34F4F' },
-        IssueRelation::TYPE_PRECEDES => { :landscape_margin => 20, :color => '#628FEA' }
-      }.freeze
-
-      # :nodoc:
-      # Some utility methods for the PDF export
-      class PDF
-        MaxCharactorsForSubject = 45
-        TotalWidth = 280
-        LeftPaneWidth = 100
-
-        def self.right_pane_width
-          TotalWidth - LeftPaneWidth
-        end
-      end
-
-      attr_reader :year_from, :month_from, :date_from, :date_to, :zoom, :months, :truncated, :max_rows
-      attr_accessor :query
-      attr_accessor :project
-      attr_accessor :view
-
-      def initialize(options={})
-        options = options.dup
-        if options[:year] && options[:year].to_i >0
-          @year_from = options[:year].to_i
-          if options[:month] && options[:month].to_i >=1 && options[:month].to_i <= 12
-            @month_from = options[:month].to_i
-          else
-            @month_from = 1
-          end
-        else
-          @month_from ||= Date.today.month
-          @year_from ||= Date.today.year
-        end
-        zoom = (options[:zoom] || User.current.pref[:gantt_zoom]).to_i
-        @zoom = (zoom > 0 && zoom < 5) ? zoom : 2
-        months = (options[:months] || User.current.pref[:gantt_months]).to_i
-        @months = (months > 0 && months < 25) ? months : 6
-        # Save gantt parameters as user preference (zoom and months count)
-        if (User.current.logged? && (@zoom != User.current.pref[:gantt_zoom] ||
-              @months != User.current.pref[:gantt_months]))
-          User.current.pref[:gantt_zoom], User.current.pref[:gantt_months] = @zoom, @months
-          User.current.preference.save
-        end
-        @date_from = Date.civil(@year_from, @month_from, 1)
-        @date_to = (@date_from >> @months) - 1
-        @subjects = ''
-        @lines = ''
-        @number_of_rows = nil
-        @issue_ancestors = []
-        @truncated = false
-        if options.has_key?(:max_rows)
-          @max_rows = options[:max_rows]
-        else
-          @max_rows = Setting.gantt_items_limit.blank? ? nil : Setting.gantt_items_limit.to_i
-        end
-      end
-
-      def common_params
-        { :controller => 'gantts', :action => 'show', :project_id => @project }
-      end
-
-      def params
-        common_params.merge({:zoom => zoom, :year => year_from,
-                             :month => month_from, :months => months})
-      end
-
-      def params_previous
-        common_params.merge({:year => (date_from << months).year,
-                             :month => (date_from << months).month,
-                             :zoom => zoom, :months => months})
-      end
-
-      def params_next
-        common_params.merge({:year => (date_from >> months).year,
-                             :month => (date_from >> months).month,
-                             :zoom => zoom, :months => months})
-      end
-
-      # Returns the number of rows that will be rendered on the Gantt chart
-      def number_of_rows
-        return @number_of_rows if @number_of_rows
-        rows = projects.inject(0) {|total, p| total += number_of_rows_on_project(p)}
-        rows > @max_rows ? @max_rows : rows
-      end
-
-      # Returns the number of rows that will be used to list a project on
-      # the Gantt chart.  This will recurse for each subproject.
-      def number_of_rows_on_project(project)
-        return 0 unless projects.include?(project)
-        count = 1
-        count += project_issues(project).size
-        count += project_versions(project).size
-        count
-      end
-
-      # Renders the subjects of the Gantt chart, the left side.
-      def subjects(options={})
-        render(options.merge(:only => :subjects)) unless @subjects_rendered
-        @subjects
-      end
-
-      # Renders the lines of the Gantt chart, the right side
-      def lines(options={})
-        render(options.merge(:only => :lines)) unless @lines_rendered
-        @lines
-      end
-
-      # Returns issues that will be rendered
-      def issues
-        @issues ||= @query.issues(
-          :include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
-          :order => "#{Project.table_name}.lft ASC, #{Issue.table_name}.id ASC",
-          :limit => @max_rows
-        )
-      end
-
-      # Returns a hash of the relations between the issues that are present on the gantt
-      # and that should be displayed, grouped by issue ids.
-      def relations
-        return @relations if @relations
-        if issues.any?
-          issue_ids = issues.map(&:id)
-          @relations = IssueRelation.
-            where(:issue_from_id => issue_ids, :issue_to_id => issue_ids, :relation_type => DRAW_TYPES.keys).
-            group_by(&:issue_from_id)
-        else
-          @relations = {}
-        end
-      end
-
-      # Return all the project nodes that will be displayed
-      def projects
-        return @projects if @projects
-        ids = issues.collect(&:project).uniq.collect(&:id)
-        if ids.any?
-          # All issues projects and their visible ancestors
-          @projects = Project.visible.
-            joins("LEFT JOIN #{Project.table_name} child ON #{Project.table_name}.lft <= child.lft AND #{Project.table_name}.rgt >= child.rgt").
-            where("child.id IN (?)", ids).
-            order("#{Project.table_name}.lft ASC").
-            uniq.
-            all
-        else
-          @projects = []
-        end
-      end
-
-      # Returns the issues that belong to +project+
-      def project_issues(project)
-        @issues_by_project ||= issues.group_by(&:project)
-        @issues_by_project[project] || []
-      end
-
-      # Returns the distinct versions of the issues that belong to +project+
-      def project_versions(project)
-        project_issues(project).collect(&:fixed_version).compact.uniq
-      end
-
-      # Returns the issues that belong to +project+ and are assigned to +version+
-      def version_issues(project, version)
-        project_issues(project).select {|issue| issue.fixed_version == version}
-      end
-
-      def render(options={})
-        options = {:top => 0, :top_increment => 20,
-                   :indent_increment => 20, :render => :subject,
-                   :format => :html}.merge(options)
-        indent = options[:indent] || 4
-        @subjects = '' unless options[:only] == :lines
-        @lines = '' unless options[:only] == :subjects
-        @number_of_rows = 0
-        Project.project_tree(projects) do |project, level|
-          options[:indent] = indent + level * options[:indent_increment]
-          render_project(project, options)
-          break if abort?
-        end
-        @subjects_rendered = true unless options[:only] == :lines
-        @lines_rendered = true unless options[:only] == :subjects
-        render_end(options)
-      end
-
-      def render_project(project, options={})
-        subject_for_project(project, options) unless options[:only] == :lines
-        line_for_project(project, options) unless options[:only] == :subjects
-        options[:top] += options[:top_increment]
-        options[:indent] += options[:indent_increment]
-        @number_of_rows += 1
-        return if abort?
-        issues = project_issues(project).select {|i| i.fixed_version.nil?}
-        self.class.sort_issues!(issues)
-        if issues
-          render_issues(issues, options)
-          return if abort?
-        end
-        versions = project_versions(project)
-        self.class.sort_versions!(versions)
-        versions.each do |version|
-          render_version(project, version, options)
-        end
-        # Remove indent to hit the next sibling
-        options[:indent] -= options[:indent_increment]
-      end
-
-      def render_issues(issues, options={})
-        @issue_ancestors = []
-        issues.each do |i|
-          subject_for_issue(i, options) unless options[:only] == :lines
-          line_for_issue(i, options) unless options[:only] == :subjects
-          options[:top] += options[:top_increment]
-          @number_of_rows += 1
-          break if abort?
-        end
-        options[:indent] -= (options[:indent_increment] * @issue_ancestors.size)
-      end
-
-      def render_version(project, version, options={})
-        # Version header
-        subject_for_version(version, options) unless options[:only] == :lines
-        line_for_version(version, options) unless options[:only] == :subjects
-        options[:top] += options[:top_increment]
-        @number_of_rows += 1
-        return if abort?
-        issues = version_issues(project, version)
-        if issues
-          self.class.sort_issues!(issues)
-          # Indent issues
-          options[:indent] += options[:indent_increment]
-          render_issues(issues, options)
-          options[:indent] -= options[:indent_increment]
-        end
-      end
-
-      def render_end(options={})
-        case options[:format]
-        when :pdf
-          options[:pdf].Line(15, options[:top], PDF::TotalWidth, options[:top])
-        end
-      end
-
-      def subject_for_project(project, options)
-        case options[:format]
-        when :html
-          html_class = ""
-          html_class << 'icon icon-projects '
-          html_class << (project.overdue? ? 'project-overdue' : '')
-          s = view.link_to_project(project).html_safe
-          subject = view.content_tag(:span, s,
-                                     :class => html_class).html_safe
-          html_subject(options, subject, :css => "project-name")
-        when :image
-          image_subject(options, project.name)
-        when :pdf
-          pdf_new_page?(options)
-          pdf_subject(options, project.name)
-        end
-      end
-
-      def line_for_project(project, options)
-        # Skip versions that don't have a start_date or due date
-        if project.is_a?(Project) && project.start_date && project.due_date
-          options[:zoom] ||= 1
-          options[:g_width] ||= (self.date_to - self.date_from + 1) * options[:zoom]
-          coords = coordinates(project.start_date, project.due_date, nil, options[:zoom])
-          label = h(project)
-          case options[:format]
-          when :html
-            html_task(options, coords, :css => "project task", :label => label, :markers => true)
-          when :image
-            image_task(options, coords, :label => label, :markers => true, :height => 3)
-          when :pdf
-            pdf_task(options, coords, :label => label, :markers => true, :height => 0.8)
-          end
-        else
-          ''
-        end
-      end
-
-      def subject_for_version(version, options)
-        case options[:format]
-        when :html
-          html_class = ""
-          html_class << 'icon icon-package '
-          html_class << (version.behind_schedule? ? 'version-behind-schedule' : '') << " "
-          html_class << (version.overdue? ? 'version-overdue' : '')
-          html_class << ' version-closed' unless version.open?
-          if version.start_date && version.due_date && version.completed_pourcent
-            progress_date = calc_progress_date(version.start_date,
-                                               version.due_date, version.completed_pourcent)
-            html_class << ' behind-start-date' if progress_date < self.date_from
-            html_class << ' over-end-date' if progress_date > self.date_to
-          end
-          s = view.link_to_version(version).html_safe
-          subject = view.content_tag(:span, s,
-                                     :class => html_class).html_safe
-          html_subject(options, subject, :css => "version-name",
-                       :id => "version-#{version.id}")
-        when :image
-          image_subject(options, version.to_s_with_project)
-        when :pdf
-          pdf_new_page?(options)
-          pdf_subject(options, version.to_s_with_project)
-        end
-      end
-
-      def line_for_version(version, options)
-        # Skip versions that don't have a start_date
-        if version.is_a?(Version) && version.due_date && version.start_date
-          options[:zoom] ||= 1
-          options[:g_width] ||= (self.date_to - self.date_from + 1) * options[:zoom]
-          coords = coordinates(version.start_date,
-                               version.due_date, version.completed_percent,
-                               options[:zoom])
-          label = "#{h version} #{h version.completed_percent.to_i.to_s}%"
-          label = h("#{version.project} -") + label unless @project && @project == version.project
-          case options[:format]
-          when :html
-            html_task(options, coords, :css => "version task",
-                      :label => label, :markers => true, :version => version)
-          when :image
-            image_task(options, coords, :label => label, :markers => true, :height => 3)
-          when :pdf
-            pdf_task(options, coords, :label => label, :markers => true, :height => 0.8)
-          end
-        else
-          ''
-        end
-      end
-
-      def subject_for_issue(issue, options)
-        while @issue_ancestors.any? && !issue.is_descendant_of?(@issue_ancestors.last)
-          @issue_ancestors.pop
-          options[:indent] -= options[:indent_increment]
-        end
-        output = case options[:format]
-        when :html
-          css_classes = ''
-          css_classes << ' issue-overdue' if issue.overdue?
-          css_classes << ' issue-behind-schedule' if issue.behind_schedule?
-          css_classes << ' icon icon-issue' unless Setting.gravatar_enabled? && issue.assigned_to
-          css_classes << ' issue-closed' if issue.closed?
-          if issue.start_date && issue.due_before && issue.done_ratio
-            progress_date = calc_progress_date(issue.start_date,
-                                               issue.due_before, issue.done_ratio)
-            css_classes << ' behind-start-date' if progress_date < self.date_from
-            css_classes << ' over-end-date' if progress_date > self.date_to
-          end
-          s = "".html_safe
-          if issue.assigned_to.present?
-            assigned_string = l(:field_assigned_to) + ": " + issue.assigned_to.name
-            s << view.avatar(issue.assigned_to,
-                             :class => 'gravatar icon-gravatar',
-                             :size => 10,
-                             :title => assigned_string).to_s.html_safe
-          end
-          s << view.link_to_issue(issue).html_safe
-          subject = view.content_tag(:span, s, :class => css_classes).html_safe
-          html_subject(options, subject, :css => "issue-subject",
-                       :title => issue.subject, :id => "issue-#{issue.id}") + "\n"
-        when :image
-          image_subject(options, issue.subject)
-        when :pdf
-          pdf_new_page?(options)
-          pdf_subject(options, issue.subject)
-        end
-        unless issue.leaf?
-          @issue_ancestors << issue
-          options[:indent] += options[:indent_increment]
-        end
-        output
-      end
-
-      def line_for_issue(issue, options)
-        # Skip issues that don't have a due_before (due_date or version's due_date)
-        if issue.is_a?(Issue) && issue.due_before
-          coords = coordinates(issue.start_date, issue.due_before, issue.done_ratio, options[:zoom])
-          label = "#{issue.status.name} #{issue.done_ratio}%"
-          case options[:format]
-          when :html
-            html_task(options, coords,
-                      :css => "task " + (issue.leaf? ? 'leaf' : 'parent'),
-                      :label => label, :issue => issue,
-                      :markers => !issue.leaf?)
-          when :image
-            image_task(options, coords, :label => label)
-          when :pdf
-            pdf_task(options, coords, :label => label)
-        end
-        else
-          ''
-        end
-      end
-
-      # Generates a gantt image
-      # Only defined if RMagick is avalaible
-      def to_image(format='PNG')
-        date_to = (@date_from >> @months) - 1
-        show_weeks = @zoom > 1
-        show_days = @zoom > 2
-        subject_width = 400
-        header_height = 18
-        # width of one day in pixels
-        zoom = @zoom * 2
-        g_width = (@date_to - @date_from + 1) * zoom
-        g_height = 20 * number_of_rows + 30
-        headers_height = (show_weeks ? 2 * header_height : header_height)
-        height = g_height + headers_height
-        imgl = Magick::ImageList.new
-        imgl.new_image(subject_width + g_width + 1, height)
-        gc = Magick::Draw.new
-        gc.font = Redmine::Configuration['rmagick_font_path'] || ""
-        # Subjects
-        gc.stroke('transparent')
-        subjects(:image => gc, :top => (headers_height + 20), :indent => 4, :format => :image)
-        # Months headers
-        month_f = @date_from
-        left = subject_width
-        @months.times do
-          width = ((month_f >> 1) - month_f) * zoom
-          gc.fill('white')
-          gc.stroke('grey')
-          gc.stroke_width(1)
-          gc.rectangle(left, 0, left + width, height)
-          gc.fill('black')
-          gc.stroke('transparent')
-          gc.stroke_width(1)
-          gc.text(left.round + 8, 14, "#{month_f.year}-#{month_f.month}")
-          left = left + width
-          month_f = month_f >> 1
-        end
-        # Weeks headers
-        if show_weeks
-          left = subject_width
-          height = header_height
-          if @date_from.cwday == 1
-            # date_from is monday
-            week_f = date_from
-          else
-            # find next monday after date_from
-            week_f = @date_from + (7 - @date_from.cwday + 1)
-            width = (7 - @date_from.cwday + 1) * zoom
-            gc.fill('white')
-            gc.stroke('grey')
-            gc.stroke_width(1)
-            gc.rectangle(left, header_height, left + width, 2 * header_height + g_height - 1)
-            left = left + width
-          end
-          while week_f <= date_to
-            width = (week_f + 6 <= date_to) ? 7 * zoom : (date_to - week_f + 1) * zoom
-            gc.fill('white')
-            gc.stroke('grey')
-            gc.stroke_width(1)
-            gc.rectangle(left.round, header_height, left.round + width, 2 * header_height + g_height - 1)
-            gc.fill('black')
-            gc.stroke('transparent')
-            gc.stroke_width(1)
-            gc.text(left.round + 2, header_height + 14, week_f.cweek.to_s)
-            left = left + width
-            week_f = week_f + 7
-          end
-        end
-        # Days details (week-end in grey)
-        if show_days
-          left = subject_width
-          height = g_height + header_height - 1
-          wday = @date_from.cwday
-          (date_to - @date_from + 1).to_i.times do
-            width =  zoom
-            gc.fill(non_working_week_days.include?(wday) ? '#eee' : 'white')
-            gc.stroke('#ddd')
-            gc.stroke_width(1)
-            gc.rectangle(left, 2 * header_height, left + width, 2 * header_height + g_height - 1)
-            left = left + width
-            wday = wday + 1
-            wday = 1 if wday > 7
-          end
-        end
-        # border
-        gc.fill('transparent')
-        gc.stroke('grey')
-        gc.stroke_width(1)
-        gc.rectangle(0, 0, subject_width + g_width, headers_height)
-        gc.stroke('black')
-        gc.rectangle(0, 0, subject_width + g_width, g_height + headers_height - 1)
-        # content
-        top = headers_height + 20
-        gc.stroke('transparent')
-        lines(:image => gc, :top => top, :zoom => zoom,
-              :subject_width => subject_width, :format => :image)
-        # today red line
-        if Date.today >= @date_from and Date.today <= date_to
-          gc.stroke('red')
-          x = (Date.today - @date_from + 1) * zoom + subject_width
-          gc.line(x, headers_height, x, headers_height + g_height - 1)
-        end
-        gc.draw(imgl)
-        imgl.format = format
-        imgl.to_blob
-      end if Object.const_defined?(:Magick)
-
-      def to_pdf
-        pdf = ::Redmine::Export::PDF::ITCPDF.new(current_language)
-        pdf.SetTitle("#{l(:label_gantt)} #{project}")
-        pdf.alias_nb_pages
-        pdf.footer_date = format_date(Date.today)
-        pdf.AddPage("L")
-        pdf.SetFontStyle('B', 12)
-        pdf.SetX(15)
-        pdf.RDMCell(PDF::LeftPaneWidth, 20, project.to_s)
-        pdf.Ln
-        pdf.SetFontStyle('B', 9)
-        subject_width = PDF::LeftPaneWidth
-        header_height = 5
-        headers_height = header_height
-        show_weeks = false
-        show_days = false
-        if self.months < 7
-          show_weeks = true
-          headers_height = 2 * header_height
-          if self.months < 3
-            show_days = true
-            headers_height = 3 * header_height
-          end
-        end
-        g_width = PDF.right_pane_width
-        zoom = (g_width) / (self.date_to - self.date_from + 1)
-        g_height = 120
-        t_height = g_height + headers_height
-        y_start = pdf.GetY
-        # Months headers
-        month_f = self.date_from
-        left = subject_width
-        height = header_height
-        self.months.times do
-          width = ((month_f >> 1) - month_f) * zoom
-          pdf.SetY(y_start)
-          pdf.SetX(left)
-          pdf.RDMCell(width, height, "#{month_f.year}-#{month_f.month}", "LTR", 0, "C")
-          left = left + width
-          month_f = month_f >> 1
-        end
-        # Weeks headers
-        if show_weeks
-          left = subject_width
-          height = header_height
-          if self.date_from.cwday == 1
-            # self.date_from is monday
-            week_f = self.date_from
-          else
-            # find next monday after self.date_from
-            week_f = self.date_from + (7 - self.date_from.cwday + 1)
-            width = (7 - self.date_from.cwday + 1) * zoom-1
-            pdf.SetY(y_start + header_height)
-            pdf.SetX(left)
-            pdf.RDMCell(width + 1, height, "", "LTR")
-            left = left + width + 1
-          end
-          while week_f <= self.date_to
-            width = (week_f + 6 <= self.date_to) ? 7 * zoom : (self.date_to - week_f + 1) * zoom
-            pdf.SetY(y_start + header_height)
-            pdf.SetX(left)
-            pdf.RDMCell(width, height, (width >= 5 ? week_f.cweek.to_s : ""), "LTR", 0, "C")
-            left = left + width
-            week_f = week_f + 7
-          end
-        end
-        # Days headers
-        if show_days
-          left = subject_width
-          height = header_height
-          wday = self.date_from.cwday
-          pdf.SetFontStyle('B', 7)
-          (self.date_to - self.date_from + 1).to_i.times do
-            width = zoom
-            pdf.SetY(y_start + 2 * header_height)
-            pdf.SetX(left)
-            pdf.RDMCell(width, height, day_name(wday).first, "LTR", 0, "C")
-            left = left + width
-            wday = wday + 1
-            wday = 1 if wday > 7
-          end
-        end
-        pdf.SetY(y_start)
-        pdf.SetX(15)
-        pdf.RDMCell(subject_width + g_width - 15, headers_height, "", 1)
-        # Tasks
-        top = headers_height + y_start
-        options = {
-          :top => top,
-          :zoom => zoom,
-          :subject_width => subject_width,
-          :g_width => g_width,
-          :indent => 0,
-          :indent_increment => 5,
-          :top_increment => 5,
-          :format => :pdf,
-          :pdf => pdf
-        }
-        render(options)
-        pdf.Output
-      end
-
-      private
-
-      def coordinates(start_date, end_date, progress, zoom=nil)
-        zoom ||= @zoom
-        coords = {}
-        if start_date && end_date && start_date < self.date_to && end_date > self.date_from
-          if start_date > self.date_from
-            coords[:start] = start_date - self.date_from
-            coords[:bar_start] = start_date - self.date_from
-          else
-            coords[:bar_start] = 0
-          end
-          if end_date < self.date_to
-            coords[:end] = end_date - self.date_from
-            coords[:bar_end] = end_date - self.date_from + 1
-          else
-            coords[:bar_end] = self.date_to - self.date_from + 1
-          end
-          if progress
-            progress_date = calc_progress_date(start_date, end_date, progress)
-            if progress_date > self.date_from && progress_date > start_date
-              if progress_date < self.date_to
-                coords[:bar_progress_end] = progress_date - self.date_from
-              else
-                coords[:bar_progress_end] = self.date_to - self.date_from + 1
-              end
-            end
-            if progress_date < Date.today
-              late_date = [Date.today, end_date].min
-              if late_date > self.date_from && late_date > start_date
-                if late_date < self.date_to
-                  coords[:bar_late_end] = late_date - self.date_from + 1
-                else
-                  coords[:bar_late_end] = self.date_to - self.date_from + 1
-                end
-              end
-            end
-          end
-        end
-        # Transforms dates into pixels witdh
-        coords.keys.each do |key|
-          coords[key] = (coords[key] * zoom).floor
-        end
-        coords
-      end
-
-      def calc_progress_date(start_date, end_date, progress)
-        start_date + (end_date - start_date + 1) * (progress / 100.0)
-      end
-
-      def self.sort_issues!(issues)
-        issues.sort! {|a, b| sort_issue_logic(a) <=> sort_issue_logic(b)}
-      end
-
-      def self.sort_issue_logic(issue)
-        julian_date = Date.new()
-        ancesters_start_date = []
-        current_issue = issue
-        begin
-          ancesters_start_date.unshift([current_issue.start_date || julian_date, current_issue.id])
-          current_issue = current_issue.parent
-        end while (current_issue)
-        ancesters_start_date
-      end
-
-      def self.sort_versions!(versions)
-        versions.sort!
-      end
-
-      def current_limit
-        if @max_rows
-          @max_rows - @number_of_rows
-        else
-          nil
-        end
-      end
-
-      def abort?
-        if @max_rows && @number_of_rows >= @max_rows
-          @truncated = true
-        end
-      end
-
-      def pdf_new_page?(options)
-        if options[:top] > 180
-          options[:pdf].Line(15, options[:top], PDF::TotalWidth, options[:top])
-          options[:pdf].AddPage("L")
-          options[:top] = 15
-          options[:pdf].Line(15, options[:top] - 0.1, PDF::TotalWidth, options[:top] - 0.1)
-        end
-      end
-
-      def html_subject(params, subject, options={})
-        style = "position: absolute;top:#{params[:top]}px;left:#{params[:indent]}px;"
-        style << "width:#{params[:subject_width] - params[:indent]}px;" if params[:subject_width]
-        output = view.content_tag(:div, subject,
-                                  :class => options[:css], :style => style,
-                                  :title => options[:title],
-                                  :id => options[:id])
-        @subjects << output
-        output
-      end
-
-      def pdf_subject(params, subject, options={})
-        params[:pdf].SetY(params[:top])
-        params[:pdf].SetX(15)
-        char_limit = PDF::MaxCharactorsForSubject - params[:indent]
-        params[:pdf].RDMCell(params[:subject_width] - 15, 5,
-                             (" " * params[:indent]) +
-                               subject.to_s.sub(/^(.{#{char_limit}}[^\s]*\s).*$/, '\1 (...)'),
-                              "LR")
-        params[:pdf].SetY(params[:top])
-        params[:pdf].SetX(params[:subject_width])
-        params[:pdf].RDMCell(params[:g_width], 5, "", "LR")
-      end
-
-      def image_subject(params, subject, options={})
-        params[:image].fill('black')
-        params[:image].stroke('transparent')
-        params[:image].stroke_width(1)
-        params[:image].text(params[:indent], params[:top] + 2, subject)
-      end
-
-      def issue_relations(issue)
-        rels = {}
-        if relations[issue.id]
-          relations[issue.id].each do |relation|
-            (rels[relation.relation_type] ||= []) << relation.issue_to_id
-          end
-        end
-        rels
-      end
-
-      def html_task(params, coords, options={})
-        output = ''
-        # Renders the task bar, with progress and late
-        if coords[:bar_start] && coords[:bar_end]
-          width = coords[:bar_end] - coords[:bar_start] - 2
-          style = ""
-          style << "top:#{params[:top]}px;"
-          style << "left:#{coords[:bar_start]}px;"
-          style << "width:#{width}px;"
-          html_id = "task-todo-issue-#{options[:issue].id}" if options[:issue]
-          html_id = "task-todo-version-#{options[:version].id}" if options[:version]
-          content_opt = {:style => style,
-                         :class => "#{options[:css]} task_todo",
-                         :id => html_id}
-          if options[:issue]
-            rels = issue_relations(options[:issue])
-            if rels.present?
-              content_opt[:data] = {"rels" => rels.to_json}
-            end
-          end
-          output << view.content_tag(:div, '&nbsp;'.html_safe, content_opt)
-          if coords[:bar_late_end]
-            width = coords[:bar_late_end] - coords[:bar_start] - 2
-            style = ""
-            style << "top:#{params[:top]}px;"
-            style << "left:#{coords[:bar_start]}px;"
-            style << "width:#{width}px;"
-            output << view.content_tag(:div, '&nbsp;'.html_safe,
-                                       :style => style,
-                                       :class => "#{options[:css]} task_late")
-          end
-          if coords[:bar_progress_end]
-            width = coords[:bar_progress_end] - coords[:bar_start] - 2
-            style = ""
-            style << "top:#{params[:top]}px;"
-            style << "left:#{coords[:bar_start]}px;"
-            style << "width:#{width}px;"
-            html_id = "task-done-issue-#{options[:issue].id}" if options[:issue]
-            html_id = "task-done-version-#{options[:version].id}" if options[:version]
-            output << view.content_tag(:div, '&nbsp;'.html_safe,
-                                       :style => style,
-                                       :class => "#{options[:css]} task_done",
-                                       :id => html_id)
-          end
-        end
-        # Renders the markers
-        if options[:markers]
-          if coords[:start]
-            style = ""
-            style << "top:#{params[:top]}px;"
-            style << "left:#{coords[:start]}px;"
-            style << "width:15px;"
-            output << view.content_tag(:div, '&nbsp;'.html_safe,
-                                       :style => style,
-                                       :class => "#{options[:css]} marker starting")
-          end
-          if coords[:end]
-            style = ""
-            style << "top:#{params[:top]}px;"
-            style << "left:#{coords[:end] + params[:zoom]}px;"
-            style << "width:15px;"
-            output << view.content_tag(:div, '&nbsp;'.html_safe,
-                                       :style => style,
-                                       :class => "#{options[:css]} marker ending")
-          end
-        end
-        # Renders the label on the right
-        if options[:label]
-          style = ""
-          style << "top:#{params[:top]}px;"
-          style << "left:#{(coords[:bar_end] || 0) + 8}px;"
-          style << "width:15px;"
-          output << view.content_tag(:div, options[:label],
-                                     :style => style,
-                                     :class => "#{options[:css]} label")
-        end
-        # Renders the tooltip
-        if options[:issue] && coords[:bar_start] && coords[:bar_end]
-          s = view.content_tag(:span,
-                               view.render_issue_tooltip(options[:issue]).html_safe,
-                               :class => "tip")
-          style = ""
-          style << "position: absolute;"
-          style << "top:#{params[:top]}px;"
-          style << "left:#{coords[:bar_start]}px;"
-          style << "width:#{coords[:bar_end] - coords[:bar_start]}px;"
-          style << "height:12px;"
-          output << view.content_tag(:div, s.html_safe,
-                                     :style => style,
-                                     :class => "tooltip")
-        end
-        @lines << output
-        output
-      end
-
-      def pdf_task(params, coords, options={})
-        height = options[:height] || 2
-        # Renders the task bar, with progress and late
-        if coords[:bar_start] && coords[:bar_end]
-          params[:pdf].SetY(params[:top] + 1.5)
-          params[:pdf].SetX(params[:subject_width] + coords[:bar_start])
-          params[:pdf].SetFillColor(200, 200, 200)
-          params[:pdf].RDMCell(coords[:bar_end] - coords[:bar_start], height, "", 0, 0, "", 1)
-          if coords[:bar_late_end]
-            params[:pdf].SetY(params[:top] + 1.5)
-            params[:pdf].SetX(params[:subject_width] + coords[:bar_start])
-            params[:pdf].SetFillColor(255, 100, 100)
-            params[:pdf].RDMCell(coords[:bar_late_end] - coords[:bar_start], height, "", 0, 0, "", 1)
-          end
-          if coords[:bar_progress_end]
-            params[:pdf].SetY(params[:top] + 1.5)
-            params[:pdf].SetX(params[:subject_width] + coords[:bar_start])
-            params[:pdf].SetFillColor(90, 200, 90)
-            params[:pdf].RDMCell(coords[:bar_progress_end] - coords[:bar_start], height, "", 0, 0, "", 1)
-          end
-        end
-        # Renders the markers
-        if options[:markers]
-          if coords[:start]
-            params[:pdf].SetY(params[:top] + 1)
-            params[:pdf].SetX(params[:subject_width] + coords[:start] - 1)
-            params[:pdf].SetFillColor(50, 50, 200)
-            params[:pdf].RDMCell(2, 2, "", 0, 0, "", 1)
-          end
-          if coords[:end]
-            params[:pdf].SetY(params[:top] + 1)
-            params[:pdf].SetX(params[:subject_width] + coords[:end] - 1)
-            params[:pdf].SetFillColor(50, 50, 200)
-            params[:pdf].RDMCell(2, 2, "", 0, 0, "", 1)
-          end
-        end
-        # Renders the label on the right
-        if options[:label]
-          params[:pdf].SetX(params[:subject_width] + (coords[:bar_end] || 0) + 5)
-          params[:pdf].RDMCell(30, 2, options[:label])
-        end
-      end
-
-      def image_task(params, coords, options={})
-        height = options[:height] || 6
-        # Renders the task bar, with progress and late
-        if coords[:bar_start] && coords[:bar_end]
-          params[:image].fill('#aaa')
-          params[:image].rectangle(params[:subject_width] + coords[:bar_start],
-                                   params[:top],
-                                   params[:subject_width] + coords[:bar_end],
-                                   params[:top] - height)
-          if coords[:bar_late_end]
-            params[:image].fill('#f66')
-            params[:image].rectangle(params[:subject_width] + coords[:bar_start],
-                                     params[:top],
-                                     params[:subject_width] + coords[:bar_late_end],
-                                     params[:top] - height)
-          end
-          if coords[:bar_progress_end]
-            params[:image].fill('#00c600')
-            params[:image].rectangle(params[:subject_width] + coords[:bar_start],
-                                     params[:top],
-                                     params[:subject_width] + coords[:bar_progress_end],
-                                     params[:top] - height)
-          end
-        end
-        # Renders the markers
-        if options[:markers]
-          if coords[:start]
-            x = params[:subject_width] + coords[:start]
-            y = params[:top] - height / 2
-            params[:image].fill('blue')
-            params[:image].polygon(x - 4, y, x, y - 4, x + 4, y, x, y + 4)
-          end
-          if coords[:end]
-            x = params[:subject_width] + coords[:end] + params[:zoom]
-            y = params[:top] - height / 2
-            params[:image].fill('blue')
-            params[:image].polygon(x - 4, y, x, y - 4, x + 4, y, x, y + 4)
-          end
-        end
-        # Renders the label on the right
-        if options[:label]
-          params[:image].fill('black')
-          params[:image].text(params[:subject_width] + (coords[:bar_end] || 0) + 5,
-                              params[:top] + 1,
-                              options[:label])
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/63/634ac7c9412839a15f45fce185c715e696a25baa.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,482 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class UsersControllerTest < ActionController::TestCase
-  include Redmine::I18n
-
-  fixtures :users, :projects, :members, :member_roles, :roles,
-           :custom_fields, :custom_values, :groups_users,
-           :auth_sources
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 1 # admin
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:users)
-    # active users only
-    assert_nil assigns(:users).detect {|u| !u.active?}
-  end
-
-  def test_index_with_status_filter
-    get :index, :status => 3
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:users)
-    assert_equal [3], assigns(:users).map(&:status).uniq
-  end
-
-  def test_index_with_name_filter
-    get :index, :name => 'john'
-    assert_response :success
-    assert_template 'index'
-    users = assigns(:users)
-    assert_not_nil users
-    assert_equal 1, users.size
-    assert_equal 'John', users.first.firstname
-  end
-
-  def test_index_with_group_filter
-    get :index, :group_id => '10'
-    assert_response :success
-    assert_template 'index'
-    users = assigns(:users)
-    assert users.any?
-    assert_equal([], (users - Group.find(10).users))
-    assert_select 'select[name=group_id]' do
-      assert_select 'option[value=10][selected=selected]'
-    end
-  end
-
-  def test_show
-    @request.session[:user_id] = nil
-    get :show, :id => 2
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:user)
-
-    assert_tag 'li', :content => /Phone number/
-  end
-
-  def test_show_should_not_display_hidden_custom_fields
-    @request.session[:user_id] = nil
-    UserCustomField.find_by_name('Phone number').update_attribute :visible, false
-    get :show, :id => 2
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:user)
-
-    assert_no_tag 'li', :content => /Phone number/
-  end
-
-  def test_show_should_not_fail_when_custom_values_are_nil
-    user = User.find(2)
-
-    # Create a custom field to illustrate the issue
-    custom_field = CustomField.create!(:name => 'Testing', :field_format => 'text')
-    custom_value = user.custom_values.build(:custom_field => custom_field).save!
-
-    get :show, :id => 2
-    assert_response :success
-  end
-
-  def test_show_inactive
-    @request.session[:user_id] = nil
-    get :show, :id => 5
-    assert_response 404
-  end
-
-  def test_show_should_not_reveal_users_with_no_visible_activity_or_project
-    @request.session[:user_id] = nil
-    get :show, :id => 9
-    assert_response 404
-  end
-
-  def test_show_inactive_by_admin
-    @request.session[:user_id] = 1
-    get :show, :id => 5
-    assert_response 200
-    assert_not_nil assigns(:user)
-  end
-
-  def test_show_displays_memberships_based_on_project_visibility
-    @request.session[:user_id] = 1
-    get :show, :id => 2
-    assert_response :success
-    memberships = assigns(:memberships)
-    assert_not_nil memberships
-    project_ids = memberships.map(&:project_id)
-    assert project_ids.include?(2) #private project admin can see
-  end
-
-  def test_show_current_should_require_authentication
-    @request.session[:user_id] = nil
-    get :show, :id => 'current'
-    assert_response 302
-  end
-
-  def test_show_current
-    @request.session[:user_id] = 2
-    get :show, :id => 'current'
-    assert_response :success
-    assert_template 'show'
-    assert_equal User.find(2), assigns(:user)
-  end
-
-  def test_new
-    get :new
-    assert_response :success
-    assert_template :new
-    assert assigns(:user)
-  end
-
-  def test_create
-    Setting.bcc_recipients = '1'
-
-    assert_difference 'User.count' do
-      assert_difference 'ActionMailer::Base.deliveries.size' do
-        post :create,
-          :user => {
-            :firstname => 'John',
-            :lastname => 'Doe',
-            :login => 'jdoe',
-            :password => 'secret123',
-            :password_confirmation => 'secret123',
-            :mail => 'jdoe@gmail.com',
-            :mail_notification => 'none'
-          },
-          :send_information => '1'
-      end
-    end
-
-    user = User.first(:order => 'id DESC')
-    assert_redirected_to :controller => 'users', :action => 'edit', :id => user.id
-
-    assert_equal 'John', user.firstname
-    assert_equal 'Doe', user.lastname
-    assert_equal 'jdoe', user.login
-    assert_equal 'jdoe@gmail.com', user.mail
-    assert_equal 'none', user.mail_notification
-    assert user.check_password?('secret123')
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert_equal [user.mail], mail.bcc
-    assert_mail_body_match 'secret', mail
-  end
-
-  def test_create_with_preferences
-    assert_difference 'User.count' do
-      post :create,
-        :user => {
-          :firstname => 'John',
-          :lastname => 'Doe',
-          :login => 'jdoe',
-          :password => 'secret123',
-          :password_confirmation => 'secret123',
-          :mail => 'jdoe@gmail.com',
-          :mail_notification => 'none'
-        },
-        :pref => {
-          'hide_mail' => '1',
-          'time_zone' => 'Paris',
-          'comments_sorting' => 'desc',
-          'warn_on_leaving_unsaved' => '0'
-        }
-    end
-    user = User.first(:order => 'id DESC')
-    assert_equal 'jdoe', user.login
-    assert_equal true, user.pref.hide_mail
-    assert_equal 'Paris', user.pref.time_zone
-    assert_equal 'desc', user.pref[:comments_sorting]
-    assert_equal '0', user.pref[:warn_on_leaving_unsaved]
-  end
-
-  def test_create_with_generate_password_should_email_the_password
-    assert_difference 'User.count' do
-      post :create, :user => {
-        :login => 'randompass',
-        :firstname => 'Random',
-        :lastname => 'Pass',
-        :mail => 'randompass@example.net',
-        :language => 'en',
-        :generate_password => '1',
-        :password => '',
-        :password_confirmation => ''
-      }, :send_information => 1
-    end
-    user = User.order('id DESC').first
-    assert_equal 'randompass', user.login
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    m = mail_body(mail).match(/Password: ([a-zA-Z0-9]+)/)
-    assert m
-    password = m[1]
-    assert user.check_password?(password)
-  end
-
-  def test_create_with_failure
-    assert_no_difference 'User.count' do
-      post :create, :user => {}
-    end
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_edit
-    get :edit, :id => 2
-    assert_response :success
-    assert_template 'edit'
-    assert_equal User.find(2), assigns(:user)
-  end
-
-  def test_update
-    ActionMailer::Base.deliveries.clear
-    put :update, :id => 2,
-        :user => {:firstname => 'Changed', :mail_notification => 'only_assigned'},
-        :pref => {:hide_mail => '1', :comments_sorting => 'desc'}
-    user = User.find(2)
-    assert_equal 'Changed', user.firstname
-    assert_equal 'only_assigned', user.mail_notification
-    assert_equal true, user.pref[:hide_mail]
-    assert_equal 'desc', user.pref[:comments_sorting]
-    assert ActionMailer::Base.deliveries.empty?
-  end
-
-  def test_update_with_failure
-    assert_no_difference 'User.count' do
-      put :update, :id => 2, :user => {:firstname => ''}
-    end
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_update_with_group_ids_should_assign_groups
-    put :update, :id => 2, :user => {:group_ids => ['10']}
-    user = User.find(2)
-    assert_equal [10], user.group_ids
-  end
-
-  def test_update_with_activation_should_send_a_notification
-    u = User.new(:firstname => 'Foo', :lastname => 'Bar', :mail => 'foo.bar@somenet.foo', :language => 'fr')
-    u.login = 'foo'
-    u.status = User::STATUS_REGISTERED
-    u.save!
-    ActionMailer::Base.deliveries.clear
-    Setting.bcc_recipients = '1'
-
-    put :update, :id => u.id, :user => {:status => User::STATUS_ACTIVE}
-    assert u.reload.active?
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert_equal ['foo.bar@somenet.foo'], mail.bcc
-    assert_mail_body_match ll('fr', :notice_account_activated), mail
-  end
-
-  def test_update_with_password_change_should_send_a_notification
-    ActionMailer::Base.deliveries.clear
-    Setting.bcc_recipients = '1'
-
-    put :update, :id => 2, :user => {:password => 'newpass123', :password_confirmation => 'newpass123'}, :send_information => '1'
-    u = User.find(2)
-    assert u.check_password?('newpass123')
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert_equal [u.mail], mail.bcc
-    assert_mail_body_match 'newpass123', mail
-  end
-
-  def test_update_with_generate_password_should_email_the_password
-    ActionMailer::Base.deliveries.clear
-    Setting.bcc_recipients = '1'
-
-    put :update, :id => 2, :user => {
-      :generate_password => '1',
-      :password => '',
-      :password_confirmation => ''
-    }, :send_information => '1'
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    m = mail_body(mail).match(/Password: ([a-zA-Z0-9]+)/)
-    assert m
-    password = m[1]
-    assert User.find(2).check_password?(password)
-  end
-
-  def test_update_without_generate_password_should_not_change_password
-    put :update, :id => 2, :user => {
-      :firstname => 'changed',
-      :generate_password => '0',
-      :password => '',
-      :password_confirmation => ''
-    }, :send_information => '1'
-
-    user = User.find(2)
-    assert_equal 'changed', user.firstname
-    assert user.check_password?('jsmith')
-  end
-
-  def test_update_user_switchin_from_auth_source_to_password_authentication
-    # Configure as auth source
-    u = User.find(2)
-    u.auth_source = AuthSource.find(1)
-    u.save!
-
-    put :update, :id => u.id, :user => {:auth_source_id => '', :password => 'newpass123', :password_confirmation => 'newpass123'}
-
-    assert_equal nil, u.reload.auth_source
-    assert u.check_password?('newpass123')
-  end
-
-  def test_update_notified_project
-    get :edit, :id => 2
-    assert_response :success
-    assert_template 'edit'
-    u = User.find(2)
-    assert_equal [1, 2, 5], u.projects.collect{|p| p.id}.sort
-    assert_equal [1, 2, 5], u.notified_projects_ids.sort
-    assert_select 'input[name=?][value=?]', 'user[notified_project_ids][]', '1'
-    assert_equal 'all', u.mail_notification
-    put :update, :id => 2,
-        :user => {
-          :mail_notification => 'selected',
-          :notified_project_ids => [1, 2]
-        }
-    u = User.find(2)
-    assert_equal 'selected', u.mail_notification
-    assert_equal [1, 2], u.notified_projects_ids.sort
-  end
-
-  def test_update_status_should_not_update_attributes
-    user = User.find(2)
-    user.pref[:no_self_notified] = '1'
-    user.pref.save
-
-    put :update, :id => 2, :user => {:status => 3}
-    assert_response 302
-    user = User.find(2)
-    assert_equal 3, user.status
-    assert_equal '1', user.pref[:no_self_notified]
-  end
-
-  def test_destroy
-    assert_difference 'User.count', -1 do
-      delete :destroy, :id => 2
-    end
-    assert_redirected_to '/users'
-    assert_nil User.find_by_id(2)
-  end
-
-  def test_destroy_should_be_denied_for_non_admin_users
-    @request.session[:user_id] = 3
-
-    assert_no_difference 'User.count' do
-      get :destroy, :id => 2
-    end
-    assert_response 403
-  end
-
-  def test_destroy_should_redirect_to_back_url_param
-    assert_difference 'User.count', -1 do
-      delete :destroy, :id => 2, :back_url => '/users?name=foo'
-    end
-    assert_redirected_to '/users?name=foo'
-  end
-
-  def test_create_membership
-    assert_difference 'Member.count' do
-      post :edit_membership, :id => 7, :membership => { :project_id => 3, :role_ids => [2]}
-    end
-    assert_redirected_to :action => 'edit', :id => '7', :tab => 'memberships'
-    member = Member.first(:order => 'id DESC')
-    assert_equal User.find(7), member.principal
-    assert_equal [2], member.role_ids
-    assert_equal 3, member.project_id
-  end
-
-  def test_create_membership_js_format
-    assert_difference 'Member.count' do
-      post :edit_membership, :id => 7, :membership => {:project_id => 3, :role_ids => [2]}, :format => 'js'
-      assert_response :success
-      assert_template 'edit_membership'
-      assert_equal 'text/javascript', response.content_type
-    end
-    member = Member.first(:order => 'id DESC')
-    assert_equal User.find(7), member.principal
-    assert_equal [2], member.role_ids
-    assert_equal 3, member.project_id
-    assert_include 'tab-content-memberships', response.body
-  end
-
-  def test_create_membership_js_format_with_failure
-    assert_no_difference 'Member.count' do
-      post :edit_membership, :id => 7, :membership => {:project_id => 3}, :format => 'js'
-      assert_response :success
-      assert_template 'edit_membership'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_include 'alert', response.body, "Alert message not sent"
-    assert_include 'Role can\\\'t be empty', response.body, "Error message not sent"
-  end
-
-  def test_update_membership
-    assert_no_difference 'Member.count' do
-      put :edit_membership, :id => 2, :membership_id => 1, :membership => { :role_ids => [2]}
-      assert_redirected_to :action => 'edit', :id => '2', :tab => 'memberships'
-    end
-    assert_equal [2], Member.find(1).role_ids
-  end
-
-  def test_update_membership_js_format
-    assert_no_difference 'Member.count' do
-      put :edit_membership, :id => 2, :membership_id => 1, :membership => {:role_ids => [2]}, :format => 'js'
-      assert_response :success
-      assert_template 'edit_membership'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_equal [2], Member.find(1).role_ids
-    assert_include 'tab-content-memberships', response.body
-  end
-
-  def test_destroy_membership
-    assert_difference 'Member.count', -1 do
-      delete :destroy_membership, :id => 2, :membership_id => 1
-    end
-    assert_redirected_to :action => 'edit', :id => '2', :tab => 'memberships'
-    assert_nil Member.find_by_id(1)
-  end
-
-  def test_destroy_membership_js_format
-    assert_difference 'Member.count', -1 do
-      delete :destroy_membership, :id => 2, :membership_id => 1, :format => 'js'
-      assert_response :success
-      assert_template 'destroy_membership'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_nil Member.find_by_id(1)
-    assert_include 'tab-content-memberships', response.body
-  end
-end
--- a/.svn/pristine/63/638ef428af64a93a5a54376e8e444c15761d3973.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class CommentTest < ActiveSupport::TestCase
-  fixtures :users, :news, :comments, :projects, :enabled_modules
-
-  def setup
-    @jsmith = User.find(2)
-    @news = News.find(1)
-  end
-
-  def test_create
-    comment = Comment.new(:commented => @news, :author => @jsmith, :comments => "my comment")
-    assert comment.save
-    @news.reload
-    assert_equal 2, @news.comments_count
-  end
-
-  def test_create_should_send_notification
-    Watcher.create!(:watchable => @news, :user => @jsmith)
-
-    with_settings :notified_events => %w(news_comment_added) do
-      assert_difference 'ActionMailer::Base.deliveries.size' do
-        Comment.create!(:commented => @news, :author => @jsmith, :comments => "my comment")
-      end
-    end
-  end
-
-  def test_validate
-    comment = Comment.new(:commented => @news)
-    assert !comment.save
-    assert_equal 2, comment.errors.count
-  end
-
-  def test_destroy
-    comment = Comment.find(1)
-    assert comment.destroy
-    @news.reload
-    assert_equal 0, @news.comments_count
-  end
-end
--- a/.svn/pristine/63/63f5d9f908a9cb71c1fdf7287c1a8cd3db047d81.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class TrackersControllerTest < ActionController::TestCase
-  fixtures :trackers, :projects, :projects_trackers, :users, :issues, :custom_fields
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 1 # admin
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-  end
-  
-  def test_index_by_anonymous_should_redirect_to_login_form
-    @request.session[:user_id] = nil
-    get :index
-    assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Ftrackers'
-  end
-  
-  def test_index_by_user_should_respond_with_406
-    @request.session[:user_id] = 2
-    get :index
-    assert_response 406
-  end
-
-  def test_new
-    get :new
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_create
-    assert_difference 'Tracker.count' do
-      post :create, :tracker => { :name => 'New tracker', :project_ids => ['1', '', ''], :custom_field_ids => ['1', '6', ''] }
-    end
-    assert_redirected_to :action => 'index'
-    tracker = Tracker.first(:order => 'id DESC')
-    assert_equal 'New tracker', tracker.name
-    assert_equal [1], tracker.project_ids.sort
-    assert_equal Tracker::CORE_FIELDS, tracker.core_fields
-    assert_equal [1, 6], tracker.custom_field_ids.sort
-    assert_equal 0, tracker.workflow_rules.count
-  end
-
-  def create_with_disabled_core_fields
-    assert_difference 'Tracker.count' do
-      post :create, :tracker => { :name => 'New tracker', :core_fields => ['assigned_to_id', 'fixed_version_id', ''] }
-    end
-    assert_redirected_to :action => 'index'
-    tracker = Tracker.first(:order => 'id DESC')
-    assert_equal 'New tracker', tracker.name
-    assert_equal %w(assigned_to_id fixed_version_id), tracker.core_fields
-  end
-
-  def test_create_new_with_workflow_copy
-    assert_difference 'Tracker.count' do
-      post :create, :tracker => { :name => 'New tracker' }, :copy_workflow_from => 1
-    end
-    assert_redirected_to :action => 'index'
-    tracker = Tracker.find_by_name('New tracker')
-    assert_equal 0, tracker.projects.count
-    assert_equal Tracker.find(1).workflow_rules.count, tracker.workflow_rules.count
-  end
-
-  def test_create_with_failure
-    assert_no_difference 'Tracker.count' do
-      post :create, :tracker => { :name => '', :project_ids => ['1', '', ''], :custom_field_ids => ['1', '6', ''] }
-    end
-    assert_response :success
-    assert_template 'new'
-    assert_error_tag :content => /name can&#x27;t be blank/i
-  end
-
-  def test_edit
-    Tracker.find(1).project_ids = [1, 3]
-
-    get :edit, :id => 1
-    assert_response :success
-    assert_template 'edit'
-
-    assert_tag :input, :attributes => { :name => 'tracker[project_ids][]',
-                                        :value => '1',
-                                        :checked => 'checked' }
-
-    assert_tag :input, :attributes => { :name => 'tracker[project_ids][]',
-                                        :value => '2',
-                                        :checked => nil }
-
-    assert_tag :input, :attributes => { :name => 'tracker[project_ids][]',
-                                        :value => '',
-                                        :type => 'hidden'}
-  end
-
-  def test_edit_should_check_core_fields
-    tracker = Tracker.find(1)
-    tracker.core_fields = %w(assigned_to_id fixed_version_id)
-    tracker.save!
-
-    get :edit, :id => 1
-    assert_response :success
-    assert_template 'edit'
-
-    assert_select 'input[name=?][value=assigned_to_id][checked=checked]', 'tracker[core_fields][]'
-    assert_select 'input[name=?][value=fixed_version_id][checked=checked]', 'tracker[core_fields][]'
-
-    assert_select 'input[name=?][value=category_id]', 'tracker[core_fields][]'
-    assert_select 'input[name=?][value=category_id][checked=checked]', 'tracker[core_fields][]', 0
-
-    assert_select 'input[name=?][value=][type=hidden]', 'tracker[core_fields][]'
-  end
-
-  def test_update
-    put :update, :id => 1, :tracker => { :name => 'Renamed',
-                                        :project_ids => ['1', '2', ''] }
-    assert_redirected_to :action => 'index'
-    assert_equal [1, 2], Tracker.find(1).project_ids.sort
-  end
-
-  def test_update_without_projects
-    put :update, :id => 1, :tracker => { :name => 'Renamed',
-                                        :project_ids => [''] }
-    assert_redirected_to :action => 'index'
-    assert Tracker.find(1).project_ids.empty?
-  end
-
-  def test_update_without_core_fields
-    put :update, :id => 1, :tracker => { :name => 'Renamed', :core_fields => [''] }
-    assert_redirected_to :action => 'index'
-    assert Tracker.find(1).core_fields.empty?
-  end
-
-  def test_update_with_failure
-    put :update, :id => 1, :tracker => { :name => '' }
-    assert_response :success
-    assert_template 'edit'
-    assert_error_tag :content => /name can&#x27;t be blank/i
-  end
-
-  def test_move_lower
-   tracker = Tracker.find_by_position(1)
-   put :update, :id => 1, :tracker => { :move_to => 'lower' }
-   assert_equal 2, tracker.reload.position
-  end
-
-  def test_destroy
-    tracker = Tracker.create!(:name => 'Destroyable')
-    assert_difference 'Tracker.count', -1 do
-      delete :destroy, :id => tracker.id
-    end
-    assert_redirected_to :action => 'index'
-    assert_nil flash[:error]
-  end
-
-  def test_destroy_tracker_in_use
-    assert_no_difference 'Tracker.count' do
-      delete :destroy, :id => 1
-    end
-    assert_redirected_to :action => 'index'
-    assert_not_nil flash[:error]
-  end
-
-  def test_get_fields
-    get :fields
-    assert_response :success
-    assert_template 'fields'
-
-    assert_select 'form' do
-      assert_select 'input[type=checkbox][name=?][value=assigned_to_id]', 'trackers[1][core_fields][]'
-      assert_select 'input[type=checkbox][name=?][value=2]', 'trackers[1][custom_field_ids][]'
-
-      assert_select 'input[type=hidden][name=?][value=]', 'trackers[1][core_fields][]'
-      assert_select 'input[type=hidden][name=?][value=]', 'trackers[1][custom_field_ids][]'
-    end
-  end
-
-  def test_post_fields
-    post :fields, :trackers => {
-      '1' => {'core_fields' => ['assigned_to_id', 'due_date', ''], 'custom_field_ids' => ['1', '2']},
-      '2' => {'core_fields' => [''], 'custom_field_ids' => ['']}
-    }
-    assert_redirected_to '/trackers/fields'
-
-    tracker = Tracker.find(1)
-    assert_equal %w(assigned_to_id due_date), tracker.core_fields
-    assert_equal [1, 2], tracker.custom_field_ids.sort
-
-    tracker = Tracker.find(2)
-    assert_equal [], tracker.core_fields
-    assert_equal [], tracker.custom_field_ids.sort
-  end
-end
--- a/.svn/pristine/64/6402c0873c916f8ca24a20adde0b93d3110a6089.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# FileSystem adapter
-# File written by Paul Rivier, at Demotera.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/abstract_adapter'
-require 'find'
-
-module Redmine
-  module Scm
-    module Adapters
-      class FilesystemAdapter < AbstractAdapter
-
-        class << self
-          def client_available
-            true
-          end
-        end
-
-        def initialize(url, root_url=nil, login=nil, password=nil,
-                       path_encoding=nil)
-          @url = with_trailling_slash(url)
-          @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
-        end
-
-        def path_encoding
-          @path_encoding
-        end
-
-        def format_path_ends(path, leading=true, trailling=true)
-          path = leading ? with_leading_slash(path) :
-            without_leading_slash(path)
-          trailling ? with_trailling_slash(path) :
-            without_trailling_slash(path)
-        end
-
-        def info
-          info = Info.new({:root_url => target(),
-                            :lastrev => nil
-                          })
-          info
-        rescue CommandFailed
-          return nil
-        end
-
-        def entries(path="", identifier=nil, options={})
-          entries = Entries.new
-          trgt_utf8 = target(path)
-          trgt = scm_iconv(@path_encoding, 'UTF-8', trgt_utf8)
-          Dir.new(trgt).each do |e1|
-            e_utf8 = scm_iconv('UTF-8', @path_encoding, e1)
-            next if e_utf8.blank?
-            relative_path_utf8 = format_path_ends(
-                (format_path_ends(path,false,true) + e_utf8),false,false)
-            t1_utf8 = target(relative_path_utf8)
-            t1 = scm_iconv(@path_encoding, 'UTF-8', t1_utf8)
-            relative_path = scm_iconv(@path_encoding, 'UTF-8', relative_path_utf8)
-            e1 = scm_iconv(@path_encoding, 'UTF-8', e_utf8)
-            if File.exist?(t1) and # paranoid test
-                  %w{file directory}.include?(File.ftype(t1)) and # avoid special types
-                  not File.basename(e1).match(/^\.+$/) # avoid . and ..
-              p1         = File.readable?(t1) ? relative_path : ""
-              utf_8_path = scm_iconv('UTF-8', @path_encoding, p1)
-              entries <<
-                Entry.new({ :name => scm_iconv('UTF-8', @path_encoding, File.basename(e1)),
-                          # below : list unreadable files, but dont link them.
-                          :path => utf_8_path,
-                          :kind => (File.directory?(t1) ? 'dir' : 'file'),
-                          :size => (File.directory?(t1) ? nil : [File.size(t1)].pack('l').unpack('L').first),
-                          :lastrev =>
-                              Revision.new({:time => (File.mtime(t1)) })
-                        })
-            end
-          end
-          entries.sort_by_name
-        rescue  => err
-          logger.error "scm: filesystem: error: #{err.message}"
-          raise CommandFailed.new(err.message)
-        end
-
-        def cat(path, identifier=nil)
-          p = scm_iconv(@path_encoding, 'UTF-8', target(path))
-          File.new(p, "rb").read
-        rescue  => err
-          logger.error "scm: filesystem: error: #{err.message}"
-          raise CommandFailed.new(err.message)
-        end
-
-        private
-
-        # AbstractAdapter::target is implicitly made to quote paths.
-        # Here we do not shell-out, so we do not want quotes.
-        def target(path=nil)
-          # Prevent the use of ..
-          if path and !path.match(/(^|\/)\.\.(\/|$)/)
-            return "#{self.url}#{without_leading_slash(path)}"
-          end
-          return self.url
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/64/6495ba1b375d76ae48a1a29718388eabb1d9a8c0.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class CustomValue < ActiveRecord::Base
-  belongs_to :custom_field
-  belongs_to :customized, :polymorphic => true
-
-  def initialize(attributes=nil, *args)
-    super
-    if new_record? && custom_field && (customized_type.blank? || (customized && customized.new_record?))
-      self.value ||= custom_field.default_value
-    end
-  end
-
-  # Returns true if the boolean custom value is true
-  def true?
-    self.value == '1'
-  end
-
-  def editable?
-    custom_field.editable?
-  end
-
-  def visible?
-    custom_field.visible?
-  end
-
-  def required?
-    custom_field.is_required?
-  end
-
-  def to_s
-    value.to_s
-  end
-end
--- a/.svn/pristine/64/64c4b3023914b8e9badc4f2743e75346c30f91ab.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/cvs_adapter'
-require 'digest/sha1'
-
-class Repository::Cvs < Repository
-  validates_presence_of :url, :root_url, :log_encoding
-
-  safe_attributes 'root_url',
-    :if => lambda {|repository, user| repository.new_record?}
-
-  def self.human_attribute_name(attribute_key_name, *args)
-    attr_name = attribute_key_name.to_s
-    if attr_name == "root_url"
-      attr_name = "cvsroot"
-    elsif attr_name == "url"
-      attr_name = "cvs_module"
-    end
-    super(attr_name, *args)
-  end
-
-  def self.scm_adapter_class
-    Redmine::Scm::Adapters::CvsAdapter
-  end
-
-  def self.scm_name
-    'CVS'
-  end
-
-  def entry(path=nil, identifier=nil)
-    rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
-    scm.entry(path, rev.nil? ? nil : rev.committed_on)
-  end
-
-  def entries(path=nil, identifier=nil)
-    rev = nil
-    if ! identifier.nil?
-      rev = changesets.find_by_revision(identifier)
-      return nil if rev.nil?
-    end
-    entries = scm.entries(path, rev.nil? ? nil : rev.committed_on)
-    if entries
-      entries.each() do |entry|
-        if ( ! entry.lastrev.nil? ) && ( ! entry.lastrev.revision.nil? )
-          change = filechanges.find_by_revision_and_path(
-                     entry.lastrev.revision,
-                     scm.with_leading_slash(entry.path) )
-          if change
-            entry.lastrev.identifier = change.changeset.revision
-            entry.lastrev.revision   = change.changeset.revision
-            entry.lastrev.author     = change.changeset.committer
-            # entry.lastrev.branch     = change.branch
-          end
-        end
-      end
-    end
-    load_entries_changesets(entries)
-    entries
-  end
-
-  def cat(path, identifier=nil)
-    rev = nil
-    if ! identifier.nil?
-      rev = changesets.find_by_revision(identifier)
-      return nil if rev.nil?
-    end
-    scm.cat(path, rev.nil? ? nil : rev.committed_on)
-  end
-
-  def annotate(path, identifier=nil)
-    rev = nil
-    if ! identifier.nil?
-      rev = changesets.find_by_revision(identifier)
-      return nil if rev.nil?
-    end
-    scm.annotate(path, rev.nil? ? nil : rev.committed_on)
-  end
-
-  def diff(path, rev, rev_to)
-    # convert rev to revision. CVS can't handle changesets here
-    diff=[]
-    changeset_from = changesets.find_by_revision(rev)
-    if rev_to.to_i > 0
-      changeset_to = changesets.find_by_revision(rev_to)
-    end
-    changeset_from.filechanges.each() do |change_from|
-      revision_from = nil
-      revision_to   = nil
-      if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
-        revision_from = change_from.revision
-      end
-      if revision_from
-        if changeset_to
-          changeset_to.filechanges.each() do |change_to|
-            revision_to = change_to.revision if change_to.path == change_from.path
-          end
-        end
-        unless revision_to
-          revision_to = scm.get_previous_revision(revision_from)
-        end
-        file_diff = scm.diff(change_from.path, revision_from, revision_to)
-        diff = diff + file_diff unless file_diff.nil?
-      end
-    end
-    return diff
-  end
-
-  def fetch_changesets
-    # some nifty bits to introduce a commit-id with cvs
-    # natively cvs doesn't provide any kind of changesets,
-    # there is only a revision per file.
-    # we now take a guess using the author, the commitlog and the commit-date.
-
-    # last one is the next step to take. the commit-date is not equal for all
-    # commits in one changeset. cvs update the commit-date when the *,v file was touched. so
-    # we use a small delta here, to merge all changes belonging to _one_ changeset
-    time_delta  = 10.seconds
-    fetch_since = latest_changeset ? latest_changeset.committed_on : nil
-    transaction do
-      tmp_rev_num = 1
-      scm.revisions('', fetch_since, nil, :log_encoding => repo_log_encoding) do |revision|
-        # only add the change to the database, if it doen't exists. the cvs log
-        # is not exclusive at all.
-        tmp_time = revision.time.clone
-        unless filechanges.find_by_path_and_revision(
-	                         scm.with_leading_slash(revision.paths[0][:path]),
-	                         revision.paths[0][:revision]
-	                           )
-          cmt = Changeset.normalize_comments(revision.message, repo_log_encoding)
-          author_utf8 = Changeset.to_utf8(revision.author, repo_log_encoding)
-          cs  = changesets.where(
-                  :committed_on => tmp_time - time_delta .. tmp_time + time_delta,
-                  :committer    => author_utf8,
-                  :comments     => cmt
-                ).first
-          # create a new changeset....
-          unless cs
-            # we use a temporaray revision number here (just for inserting)
-            # later on, we calculate a continous positive number
-            tmp_time2 = tmp_time.clone.gmtime
-            branch    = revision.paths[0][:branch]
-            scmid     = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
-            cs = Changeset.create(:repository   => self,
-                                  :revision     => "tmp#{tmp_rev_num}",
-                                  :scmid        => scmid,
-                                  :committer    => revision.author,
-                                  :committed_on => tmp_time,
-                                  :comments     => revision.message)
-            tmp_rev_num += 1
-          end
-          # convert CVS-File-States to internal Action-abbrevations
-          # default action is (M)odified
-          action = "M"
-          if revision.paths[0][:action] == "Exp" && revision.paths[0][:revision] == "1.1"
-            action = "A" # add-action always at first revision (= 1.1)
-          elsif revision.paths[0][:action] == "dead"
-            action = "D" # dead-state is similar to Delete
-          end
-          Change.create(
-             :changeset => cs,
-             :action    => action,
-             :path      => scm.with_leading_slash(revision.paths[0][:path]),
-             :revision  => revision.paths[0][:revision],
-             :branch    => revision.paths[0][:branch]
-              )
-        end
-      end
-
-      # Renumber new changesets in chronological order
-      Changeset.
-        order('committed_on ASC, id ASC').
-        where("repository_id = ? AND revision LIKE 'tmp%'", id).
-        each do |changeset|
-        changeset.update_attribute :revision, next_revision_number
-      end
-    end # transaction
-    @current_revision_number = nil
-  end
-
-  private
-
-  # Returns the next revision number to assign to a CVS changeset
-  def next_revision_number
-    # Need to retrieve existing revision numbers to sort them as integers
-    sql = "SELECT revision FROM #{Changeset.table_name} "
-    sql << "WHERE repository_id = #{id} AND revision NOT LIKE 'tmp%'"
-    @current_revision_number ||= (connection.select_values(sql).collect(&:to_i).max || 0)
-    @current_revision_number += 1
-  end
-end
--- a/.svn/pristine/65/6522becd35e6716c94ac60c2f3bd1780740bea87.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class DocumentTest < ActiveSupport::TestCase
-  fixtures :projects, :enumerations, :documents, :attachments,
-           :enabled_modules,
-           :users, :members, :member_roles, :roles,
-           :groups_users
-
-  def test_create
-    doc = Document.new(:project => Project.find(1), :title => 'New document', :category => Enumeration.find_by_name('User documentation'))
-    assert doc.save
-  end
-
-  def test_create_should_send_email_notification
-    ActionMailer::Base.deliveries.clear
-    
-    with_settings :notified_events => %w(document_added) do
-      doc = Document.new(:project => Project.find(1), :title => 'New document', :category => Enumeration.find_by_name('User documentation'))
-      assert doc.save
-    end
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_create_with_default_category
-    # Sets a default category
-    e = Enumeration.find_by_name('Technical documentation')
-    e.update_attributes(:is_default => true)
-
-    doc = Document.new(:project => Project.find(1), :title => 'New document')
-    assert_equal e, doc.category
-    assert doc.save
-  end
-
-  def test_updated_on_with_attachments
-    d = Document.find(1)
-    assert d.attachments.any?
-    assert_equal d.attachments.map(&:created_on).max, d.updated_on
-  end
-
-  def test_updated_on_without_attachments
-    d = Document.find(2)
-    assert d.attachments.empty?
-    assert_equal d.created_on, d.updated_on
-  end
-end
--- a/.svn/pristine/65/6548ced1be2ac2971e9540ff4fe8979b3f03573e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingIssueStatusesTest < ActionController::IntegrationTest
-  def test_issue_statuses
-    assert_routing(
-        { :method => 'get', :path => "/issue_statuses" },
-        { :controller => 'issue_statuses', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issue_statuses.xml" },
-        { :controller => 'issue_statuses', :action => 'index', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issue_statuses" },
-        { :controller => 'issue_statuses', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issue_statuses.xml" },
-        { :controller => 'issue_statuses', :action => 'create', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issue_statuses/new" },
-        { :controller => 'issue_statuses', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issue_statuses/new.xml" },
-        { :controller => 'issue_statuses', :action => 'new', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issue_statuses/1/edit" },
-        { :controller => 'issue_statuses', :action => 'edit', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/issue_statuses/1" },
-        { :controller => 'issue_statuses', :action => 'update',
-          :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/issue_statuses/1.xml" },
-        { :controller => 'issue_statuses', :action => 'update',
-          :format => 'xml', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/issue_statuses/1" },
-        { :controller => 'issue_statuses', :action => 'destroy',
-          :id => '1' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/issue_statuses/1.xml" },
-        { :controller => 'issue_statuses', :action => 'destroy',
-          :format => 'xml', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issue_statuses/update_issue_done_ratio" },
-        { :controller => 'issue_statuses', :action => 'update_issue_done_ratio' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issue_statuses/update_issue_done_ratio.xml" },
-        { :controller => 'issue_statuses', :action => 'update_issue_done_ratio',
-          :format => 'xml' }
-      )
-  end
-end
--- a/.svn/pristine/65/65b88641ff8e4579cbf40b69a6bf7f5392a27740.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssuePriorityTest < ActiveSupport::TestCase
-  fixtures :enumerations, :issues
-
-  def test_named_scope
-    assert_equal Enumeration.find_by_name('Normal'), Enumeration.named('normal').first
-  end
-
-  def test_default_should_return_the_default_priority
-    assert_equal Enumeration.find_by_name('Normal'), IssuePriority.default
-  end
-
-  def test_default_should_return_nil_when_no_default_priority
-    IssuePriority.update_all :is_default => false
-    assert_nil IssuePriority.default
-  end
-
-  def test_should_be_an_enumeration
-    assert IssuePriority.ancestors.include?(Enumeration)
-  end
-
-  def test_objects_count
-    # low priority
-    assert_equal 6, IssuePriority.find(4).objects_count
-    # urgent
-    assert_equal 0, IssuePriority.find(7).objects_count
-  end
-
-  def test_option_name
-    assert_equal :enumeration_issue_priorities, IssuePriority.new.option_name
-  end
-
-  def test_should_be_created_at_last_position
-    IssuePriority.delete_all
-
-    priorities = [1, 2, 3].map {|i| IssuePriority.create!(:name => "P#{i}")}
-    assert_equal [1, 2, 3], priorities.map(&:position)
-  end
-
-  def test_reset_positions_in_list_should_set_sequential_positions
-    IssuePriority.delete_all
-
-    priorities = [1, 2, 3].map {|i| IssuePriority.create!(:name => "P#{i}")}
-    priorities[0].update_attribute :position, 4
-    priorities[1].update_attribute :position, 2
-    priorities[2].update_attribute :position, 7
-    assert_equal [4, 2, 7], priorities.map(&:reload).map(&:position)
-
-    priorities[0].reset_positions_in_list
-    assert_equal [2, 1, 3], priorities.map(&:reload).map(&:position)
-  end
-
-  def test_moving_in_list_should_reset_positions
-    priority = IssuePriority.first
-    priority.expects(:reset_positions_in_list).once
-    priority.move_to = 'higher'
-  end
-
-  def test_clear_position_names_should_set_position_names_to_nil
-    IssuePriority.clear_position_names
-    assert IssuePriority.all.all? {|priority| priority.position_name.nil?}
-  end
-
-  def test_compute_position_names_with_default_priority
-    IssuePriority.clear_position_names
-
-    IssuePriority.compute_position_names
-    assert_equal %w(lowest default high3 high2 highest), IssuePriority.active.all.sort.map(&:position_name)
-  end
-
-  def test_compute_position_names_without_default_priority_should_split_priorities
-    IssuePriority.clear_position_names
-    IssuePriority.update_all :is_default => false
-
-    IssuePriority.compute_position_names
-    assert_equal %w(lowest low2 default high2 highest), IssuePriority.active.all.sort.map(&:position_name)
-  end
-
-  def test_adding_a_priority_should_update_position_names
-    priority = IssuePriority.create!(:name => 'New')
-    assert_equal %w(lowest default high4 high3 high2 highest), IssuePriority.active.all.sort.map(&:position_name)
-  end
-
-  def test_destroying_a_priority_should_update_position_names
-    IssuePriority.find_by_position_name('highest').destroy
-    assert_equal %w(lowest default high2 highest), IssuePriority.active.all.sort.map(&:position_name)
-  end
-end
--- a/.svn/pristine/66/662e86180d02fd07ea0b83b2c6615af46feab399.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssueStatus < ActiveRecord::Base
-  before_destroy :check_integrity
-  has_many :workflows, :class_name => 'WorkflowTransition', :foreign_key => "old_status_id"
-  acts_as_list
-
-  before_destroy :delete_workflow_rules
-  after_save     :update_default
-
-  validates_presence_of :name
-  validates_uniqueness_of :name
-  validates_length_of :name, :maximum => 30
-  validates_inclusion_of :default_done_ratio, :in => 0..100, :allow_nil => true
-
-  scope :sorted, lambda { order("#{table_name}.position ASC") }
-  scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
-
-  def update_default
-    IssueStatus.update_all({:is_default => false}, ['id <> ?', id]) if self.is_default?
-  end
-
-  # Returns the default status for new issues
-  def self.default
-    where(:is_default => true).first
-  end
-
-  # Update all the +Issues+ setting their done_ratio to the value of their +IssueStatus+
-  def self.update_issue_done_ratios
-    if Issue.use_status_for_done_ratio?
-      IssueStatus.where("default_done_ratio >= 0").all.each do |status|
-        Issue.update_all({:done_ratio => status.default_done_ratio}, {:status_id => status.id})
-      end
-    end
-
-    return Issue.use_status_for_done_ratio?
-  end
-
-  # Returns an array of all statuses the given role can switch to
-  # Uses association cache when called more than one time
-  def new_statuses_allowed_to(roles, tracker, author=false, assignee=false)
-    if roles && tracker
-      role_ids = roles.collect(&:id)
-      transitions = workflows.select do |w|
-        role_ids.include?(w.role_id) &&
-        w.tracker_id == tracker.id &&
-        ((!w.author && !w.assignee) || (author && w.author) || (assignee && w.assignee))
-      end
-      transitions.map(&:new_status).compact.sort
-    else
-      []
-    end
-  end
-
-  # Same thing as above but uses a database query
-  # More efficient than the previous method if called just once
-  def find_new_statuses_allowed_to(roles, tracker, author=false, assignee=false)
-    if roles.present? && tracker
-      conditions = "(author = :false AND assignee = :false)"
-      conditions << " OR author = :true" if author
-      conditions << " OR assignee = :true" if assignee
-
-      workflows.
-        includes(:new_status).
-        where(["role_id IN (:role_ids) AND tracker_id = :tracker_id AND (#{conditions})",
-          {:role_ids => roles.collect(&:id), :tracker_id => tracker.id, :true => true, :false => false}
-          ]).all.
-        map(&:new_status).compact.sort
-    else
-      []
-    end
-  end
-
-  def <=>(status)
-    position <=> status.position
-  end
-
-  def to_s; name end
-
-  private
-
-  def check_integrity
-    raise "Can't delete status" if Issue.where(:status_id => id).any?
-  end
-
-  # Deletes associated workflows
-  def delete_workflow_rules
-    WorkflowRule.delete_all(["old_status_id = :id OR new_status_id = :id", {:id => id}])
-  end
-end
--- a/.svn/pristine/66/66834a4bdddfd399aac57e87263804a8152e50b5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class TimeEntryQueryTest < ActiveSupport::TestCase
-  fixtures :projects, :users, :enumerations
-
-  def test_activity_filter_should_consider_system_and_project_activities
-    TimeEntry.delete_all
-    system = TimeEntryActivity.create!(:name => 'Foo')
-    override = TimeEntryActivity.create!(:name => 'Foo', :parent_id => system.id, :project_id => 1)
-    other = TimeEntryActivity.create!(:name => 'Bar')
-    TimeEntry.generate!(:activity => system, :hours => 1.0)
-    TimeEntry.generate!(:activity => override, :hours => 2.0)
-    TimeEntry.generate!(:activity => other, :hours => 4.0)
-
-    query = TimeEntryQuery.new(:name => '_')
-    query.add_filter('activity_id', '=', [system.id.to_s])
-    assert_equal 3.0, query.results_scope.sum(:hours)
-
-    query = TimeEntryQuery.new(:name => '_')
-    query.add_filter('activity_id', '!', [system.id.to_s])
-    assert_equal 4.0, query.results_scope.sum(:hours)
-  end
-end
--- a/.svn/pristine/67/67fb9a2c82ee9bb7b43a202b8b3be8deec0d41f4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class SettingsController < ApplicationController
-  layout 'admin'
-  menu_item :plugins, :only => :plugin
-
-  helper :queries
-
-  before_filter :require_admin
-
-  def index
-    edit
-    render :action => 'edit'
-  end
-
-  def edit
-    @notifiables = Redmine::Notifiable.all
-    if request.post? && params[:settings] && params[:settings].is_a?(Hash)
-      settings = (params[:settings] || {}).dup.symbolize_keys
-      settings.each do |name, value|
-        Setting.set_from_params name, value
-      end
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to settings_path(:tab => params[:tab])
-    else
-      @options = {}
-      user_format = User::USER_FORMATS.collect{|key, value| [key, value[:setting_order]]}.sort{|a, b| a[1] <=> b[1]}
-      @options[:user_format] = user_format.collect{|f| [User.current.name(f[0]), f[0].to_s]}
-      @deliveries = ActionMailer::Base.perform_deliveries
-
-      @guessed_host_and_path = request.host_with_port.dup
-      @guessed_host_and_path << ('/'+ Redmine::Utils.relative_url_root.gsub(%r{^\/}, '')) unless Redmine::Utils.relative_url_root.blank?
-
-      @commit_update_keywords = Setting.commit_update_keywords.dup
-      @commit_update_keywords = [{}] unless @commit_update_keywords.is_a?(Array) && @commit_update_keywords.any?
-
-      Redmine::Themes.rescan
-    end
-  end
-
-  def plugin
-    @plugin = Redmine::Plugin.find(params[:id])
-    unless @plugin.configurable?
-      render_404
-      return
-    end
-
-    if request.post?
-      Setting.send "plugin_#{@plugin.id}=", params[:settings]
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to plugin_settings_path(@plugin)
-    else
-      @partial = @plugin.settings[:partial]
-      @settings = Setting.send "plugin_#{@plugin.id}"
-    end
-  rescue Redmine::PluginNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/68/68cec9b340a32b5033a24e6ea73291b5b640c745.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class CommentsController < ApplicationController
-  default_search_scope :news
-  model_object News
-  before_filter :find_model_object
-  before_filter :find_project_from_association
-  before_filter :authorize
-
-  def create
-    raise Unauthorized unless @news.commentable?
-
-    @comment = Comment.new
-    @comment.safe_attributes = params[:comment]
-    @comment.author = User.current
-    if @news.comments << @comment
-      flash[:notice] = l(:label_comment_added)
-    end
-
-    redirect_to news_path(@news)
-  end
-
-  def destroy
-    @news.comments.find(params[:comment_id]).destroy
-    redirect_to news_path(@news)
-  end
-
-  private
-
-  # ApplicationController's find_model_object sets it based on the controller
-  # name so it needs to be overriden and set to @news instead
-  def find_model_object
-    super
-    @news = @object
-    @comment = nil
-    @news
-  end
-end
--- a/.svn/pristine/69/69aad9646672b101f4780577efca970e899cd21a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
-
-  class DarcsAdapterTest < ActiveSupport::TestCase
-    REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s
-
-    if File.directory?(REPOSITORY_PATH)
-      def setup
-        @adapter = Redmine::Scm::Adapters::DarcsAdapter.new(REPOSITORY_PATH)
-      end
-
-      def test_darcsversion
-        to_test = { "1.0.9 (release)\n"  => [1,0,9] ,
-                    "2.2.0 (release)\n"  => [2,2,0] }
-        to_test.each do |s, v|
-          test_darcsversion_for(s, v)
-        end
-      end
-
-      def test_revisions
-        id1 = '20080308225258-98289-761f654d669045eabee90b91b53a21ce5593cadf.gz'
-        revs = @adapter.revisions('', nil, nil, {:with_path => true})
-        assert_equal 6, revs.size
-        assert_equal id1, revs[5].scmid
-        paths = revs[5].paths
-        assert_equal 5, paths.size
-        assert_equal 'A', paths[0][:action]
-        assert_equal '/README', paths[0][:path]
-        assert_equal 'A', paths[1][:action]
-        assert_equal '/images', paths[1][:path]
-      end
-
-      private
-
-      def test_darcsversion_for(darcsversion, version)
-        @adapter.class.expects(:darcs_binary_version_from_command_line).returns(darcsversion)
-        assert_equal version, @adapter.class.darcs_binary_version
-      end
-
-    else
-      puts "Darcs test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
-    end
-  end
-
-rescue LoadError
-  class DarcsMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
-  end
-end
-
--- a/.svn/pristine/6a/6a96b935778cbb8f7a670a2735694f941fa3d694.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Journal < ActiveRecord::Base
-  belongs_to :journalized, :polymorphic => true
-  # added as a quick fix to allow eager loading of the polymorphic association
-  # since always associated to an issue, for now
-  belongs_to :issue, :foreign_key => :journalized_id
-
-  belongs_to :user
-  has_many :details, :class_name => "JournalDetail", :dependent => :delete_all
-  attr_accessor :indice
-
-  acts_as_event :title => Proc.new {|o| status = ((s = o.new_status) ? " (#{s})" : nil); "#{o.issue.tracker} ##{o.issue.id}#{status}: #{o.issue.subject}" },
-                :description => :notes,
-                :author => :user,
-                :group => :issue,
-                :type => Proc.new {|o| (s = o.new_status) ? (s.is_closed? ? 'issue-closed' : 'issue-edit') : 'issue-note' },
-                :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id, :anchor => "change-#{o.id}"}}
-
-  acts_as_activity_provider :type => 'issues',
-                            :author_key => :user_id,
-                            :find_options => {:include => [{:issue => :project}, :details, :user],
-                                              :conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" +
-                                                             " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"}
-
-  before_create :split_private_notes
-  after_create :send_notification
-
-  scope :visible, lambda {|*args|
-    user = args.shift || User.current
-
-    includes(:issue => :project).
-      where(Issue.visible_condition(user, *args)).
-      where("(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(user, :view_private_notes, *args)}))", false)
-  }
-
-  def save(*args)
-    # Do not save an empty journal
-    (details.empty? && notes.blank?) ? false : super
-  end
-
-  # Returns journal details that are visible to user
-  def visible_details(user=User.current)
-    details.select do |detail|
-      if detail.property == 'cf'
-        detail.custom_field && detail.custom_field.visible_by?(project, user)
-      elsif detail.property == 'relation'
-        Issue.find_by_id(detail.value || detail.old_value).try(:visible?, user)
-      else
-        true
-      end
-    end
-  end
-
-  def each_notification(users, &block)
-    if users.any?
-      users_by_details_visibility = users.group_by do |user|
-        visible_details(user)
-      end
-      users_by_details_visibility.each do |visible_details, users|
-        if notes? || visible_details.any?
-          yield(users)
-        end
-      end
-    end
-  end
-
-  # Returns the new status if the journal contains a status change, otherwise nil
-  def new_status
-    c = details.detect {|detail| detail.prop_key == 'status_id'}
-    (c && c.value) ? IssueStatus.find_by_id(c.value.to_i) : nil
-  end
-
-  def new_value_for(prop)
-    c = details.detect {|detail| detail.prop_key == prop}
-    c ? c.value : nil
-  end
-
-  def editable_by?(usr)
-    usr && usr.logged? && (usr.allowed_to?(:edit_issue_notes, project) || (self.user == usr && usr.allowed_to?(:edit_own_issue_notes, project)))
-  end
-
-  def project
-    journalized.respond_to?(:project) ? journalized.project : nil
-  end
-
-  def attachments
-    journalized.respond_to?(:attachments) ? journalized.attachments : nil
-  end
-
-  # Returns a string of css classes
-  def css_classes
-    s = 'journal'
-    s << ' has-notes' unless notes.blank?
-    s << ' has-details' unless details.blank?
-    s << ' private-notes' if private_notes?
-    s
-  end
-
-  def notify?
-    @notify != false
-  end
-
-  def notify=(arg)
-    @notify = arg
-  end
-
-  def notified_users
-    notified = journalized.notified_users
-    if private_notes?
-      notified = notified.select {|user| user.allowed_to?(:view_private_notes, journalized.project)}
-    end
-    notified
-  end
-
-  def recipients
-    notified_users.map(&:mail)
-  end
-
-  def notified_watchers
-    notified = journalized.notified_watchers
-    if private_notes?
-      notified = notified.select {|user| user.allowed_to?(:view_private_notes, journalized.project)}
-    end
-    notified
-  end
-
-  def watcher_recipients
-    notified_watchers.map(&:mail)
-  end
-
-  # Sets @custom_field instance variable on journals details using a single query
-  def self.preload_journals_details_custom_fields(journals)
-    field_ids = journals.map(&:details).flatten.select {|d| d.property == 'cf'}.map(&:prop_key).uniq
-    if field_ids.any?
-      fields_by_id = CustomField.find_all_by_id(field_ids).inject({}) {|h, f| h[f.id] = f; h}
-      journals.each do |journal|
-        journal.details.each do |detail|
-          if detail.property == 'cf'
-            detail.instance_variable_set "@custom_field", fields_by_id[detail.prop_key.to_i]
-          end
-        end
-      end
-    end
-    journals
-  end
-
-  private
-
-  def split_private_notes
-    if private_notes?
-      if notes.present?
-        if details.any?
-          # Split the journal (notes/changes) so we don't have half-private journals
-          journal = Journal.new(:journalized => journalized, :user => user, :notes => nil, :private_notes => false)
-          journal.details = details
-          journal.save
-          self.details = []
-          self.created_on = journal.created_on
-        end
-      else
-        # Blank notes should not be private
-        self.private_notes = false
-      end
-    end
-    true
-  end
-
-  def send_notification
-    if notify? && (Setting.notified_events.include?('issue_updated') ||
-        (Setting.notified_events.include?('issue_note_added') && notes.present?) ||
-        (Setting.notified_events.include?('issue_status_updated') && new_status.present?) ||
-        (Setting.notified_events.include?('issue_priority_updated') && new_value_for('priority_id').present?)
-      )
-      Mailer.deliver_issue_edit(self)
-    end
-  end
-end
--- a/.svn/pristine/6a/6ad28dd349d922a2ada017eb617dd963b5950896.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class SettingsControllerTest < ActionController::TestCase
-  fixtures :users
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 1 # admin
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_get_edit
-    get :edit
-    assert_response :success
-    assert_template 'edit'
-
-    assert_tag 'input', :attributes => {:name => 'settings[enabled_scm][]', :value => ''}
-  end
-
-  def test_get_edit_should_preselect_default_issue_list_columns
-    with_settings :issue_list_default_columns => %w(tracker subject status updated_on) do
-      get :edit
-      assert_response :success
-    end
-
-    assert_select 'select[id=selected_columns][name=?]', 'settings[issue_list_default_columns][]' do
-      assert_select 'option', 4
-      assert_select 'option[value=tracker]', :text => 'Tracker'
-      assert_select 'option[value=subject]', :text => 'Subject'
-      assert_select 'option[value=status]', :text => 'Status'
-      assert_select 'option[value=updated_on]', :text => 'Updated'
-    end
-
-    assert_select 'select[id=available_columns]' do
-      assert_select 'option[value=tracker]', 0
-      assert_select 'option[value=priority]', :text => 'Priority'
-    end
-  end
-
-  def test_get_edit_without_trackers_should_succeed
-    Tracker.delete_all
-
-    get :edit
-    assert_response :success
-  end
-
-  def test_post_edit_notifications
-    post :edit, :settings => {:mail_from => 'functional@test.foo',
-                              :bcc_recipients  => '0',
-                              :notified_events => %w(issue_added issue_updated news_added),
-                              :emails_footer => 'Test footer'
-                              }
-    assert_redirected_to '/settings'
-    assert_equal 'functional@test.foo', Setting.mail_from
-    assert !Setting.bcc_recipients?
-    assert_equal %w(issue_added issue_updated news_added), Setting.notified_events
-    assert_equal 'Test footer', Setting.emails_footer
-    Setting.clear_cache
-  end
-
-  def test_edit_commit_update_keywords
-    with_settings :commit_update_keywords => [
-      {"keywords" => "fixes, resolves", "status_id" => "3"},
-      {"keywords" => "closes", "status_id" => "5", "done_ratio" => "100", "if_tracker_id" => "2"}
-    ] do
-      get :edit
-    end
-    assert_response :success
-    assert_select 'tr.commit-keywords', 2
-    assert_select 'tr.commit-keywords:nth-child(1)' do
-      assert_select 'input[name=?][value=?]', 'settings[commit_update_keywords][keywords][]', 'fixes, resolves'
-      assert_select 'select[name=?]', 'settings[commit_update_keywords][status_id][]' do
-        assert_select 'option[value=3][selected=selected]'
-      end
-    end
-    assert_select 'tr.commit-keywords:nth-child(2)' do
-      assert_select 'input[name=?][value=?]', 'settings[commit_update_keywords][keywords][]', 'closes'
-      assert_select 'select[name=?]', 'settings[commit_update_keywords][status_id][]' do
-        assert_select 'option[value=5][selected=selected]', :text => 'Closed'
-      end
-      assert_select 'select[name=?]', 'settings[commit_update_keywords][done_ratio][]' do
-        assert_select 'option[value=100][selected=selected]', :text => '100 %'
-      end
-      assert_select 'select[name=?]', 'settings[commit_update_keywords][if_tracker_id][]' do
-        assert_select 'option[value=2][selected=selected]', :text => 'Feature request'
-      end
-    end
-  end
-
-  def test_edit_without_commit_update_keywords_should_show_blank_line
-    with_settings :commit_update_keywords => [] do
-      get :edit
-    end
-    assert_response :success
-    assert_select 'tr.commit-keywords', 1 do
-      assert_select 'input[name=?]:not([value])', 'settings[commit_update_keywords][keywords][]'
-    end
-  end
-
-  def test_post_edit_commit_update_keywords
-    post :edit, :settings => {
-      :commit_update_keywords => {
-        :keywords => ["resolves", "closes"],
-        :status_id => ["3", "5"],
-        :done_ratio => ["", "100"],
-        :if_tracker_id => ["", "2"]
-      }
-    }
-    assert_redirected_to '/settings'
-    assert_equal([
-      {"keywords" => "resolves", "status_id" => "3"},
-      {"keywords" => "closes", "status_id" => "5", "done_ratio" => "100", "if_tracker_id" => "2"}
-    ], Setting.commit_update_keywords)
-  end
-
-  def test_get_plugin_settings
-    Setting.stubs(:plugin_foo).returns({'sample_setting' => 'Plugin setting value'})
-    ActionController::Base.append_view_path(File.join(Rails.root, "test/fixtures/plugins"))
-    Redmine::Plugin.register :foo do
-      settings :partial => "foo_plugin/foo_plugin_settings"
-    end
-
-    get :plugin, :id => 'foo'
-    assert_response :success
-    assert_template 'plugin'
-    assert_tag 'form', :attributes => {:action => '/settings/plugin/foo'},
-      :descendant => {:tag => 'input', :attributes => {:name => 'settings[sample_setting]', :value => 'Plugin setting value'}}
-
-    Redmine::Plugin.clear
-  end
-
-  def test_get_invalid_plugin_settings
-    get :plugin, :id => 'none'
-    assert_response 404
-  end
-
-  def test_get_non_configurable_plugin_settings
-    Redmine::Plugin.register(:foo) {}
-
-    get :plugin, :id => 'foo'
-    assert_response 404
-
-    Redmine::Plugin.clear
-  end
-
-  def test_post_plugin_settings
-    Setting.expects(:plugin_foo=).with({'sample_setting' => 'Value'}).returns(true)
-    Redmine::Plugin.register(:foo) do
-      settings :partial => 'not blank' # so that configurable? is true
-    end
-
-    post :plugin, :id => 'foo', :settings => {'sample_setting' => 'Value'}
-    assert_redirected_to '/settings/plugin/foo'
-  end
-
-  def test_post_non_configurable_plugin_settings
-    Redmine::Plugin.register(:foo) {}
-
-    post :plugin, :id => 'foo', :settings => {'sample_setting' => 'Value'}
-    assert_response 404
-
-    Redmine::Plugin.clear
-  end
-end
--- a/.svn/pristine/6b/6b2c4a778dca89a31620a55a65371a0aa4017062.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingBoardsTest < ActionController::IntegrationTest
-  def test_boards
-    assert_routing(
-        { :method => 'get', :path => "/projects/world_domination/boards" },
-        { :controller => 'boards', :action => 'index', :project_id => 'world_domination' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/world_domination/boards/new" },
-        { :controller => 'boards', :action => 'new', :project_id => 'world_domination' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/world_domination/boards/44" },
-        { :controller => 'boards', :action => 'show', :project_id => 'world_domination',
-          :id => '44' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/world_domination/boards/44.atom" },
-        { :controller => 'boards', :action => 'show', :project_id => 'world_domination',
-          :id => '44', :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/world_domination/boards/44/edit" },
-        { :controller => 'boards', :action => 'edit', :project_id => 'world_domination',
-          :id => '44' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/world_domination/boards" },
-        { :controller => 'boards', :action => 'create', :project_id => 'world_domination' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/projects/world_domination/boards/44" },
-        { :controller => 'boards', :action => 'update', :project_id => 'world_domination',
-          :id => '44' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/projects/world_domination/boards/44" },
-        { :controller => 'boards', :action => 'destroy', :project_id => 'world_domination',
-          :id => '44' }
-      )
-  end
-end
--- a/.svn/pristine/6b/6b42e6adb8523e15e9ff195fc3496e5284a69b00.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module ActivitiesHelper
-  def sort_activity_events(events)
-    events_by_group = events.group_by(&:event_group)
-    sorted_events = []
-    events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
-      if group_events = events_by_group.delete(event.event_group)
-        group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
-          sorted_events << [e, i > 0]
-        end
-      end
-    end
-    sorted_events
-  end
-end
--- a/.svn/pristine/6b/6b4c50390f939790cfd61f918f38b017e779b22e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module TrackersHelper
-end
--- a/.svn/pristine/6c/6c32beaaa0775810013dacee7377be5689730569.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,259 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositorySubversionTest < ActiveSupport::TestCase
-  fixtures :projects, :repositories, :enabled_modules, :users, :roles
-
-  include Redmine::I18n
-
-  NUM_REV = 11
-
-  def setup
-    @project = Project.find(3)
-    @repository = Repository::Subversion.create(:project => @project,
-                    :url => self.class.subversion_repository_url)
-    assert @repository
-  end
-
-  def test_invalid_url
-    set_language_if_valid 'en'
-    ['invalid', 'http://', 'svn://', 'svn+ssh://', 'file://'].each do |url|
-      repo = Repository::Subversion.new(
-                            :project      => @project,
-                            :identifier   => 'test',
-                            :url => url
-                          )
-      assert !repo.save
-      assert_equal ["is invalid"], repo.errors[:url]
-    end
-  end
-
-  def test_valid_url
-    ['http://valid', 'svn://valid', 'svn+ssh://valid', 'file://valid'].each do |url|
-      repo = Repository::Subversion.new(
-                            :project      => @project,
-                            :identifier   => 'test',
-                            :url => url
-                          )
-      assert repo.save
-      assert_equal [], repo.errors[:url]
-      assert repo.destroy
-    end
-  end
-
-  if repository_configured?('subversion')
-    def test_fetch_changesets_from_scratch
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_equal 20, @repository.filechanges.count
-      assert_equal 'Initial import.', @repository.changesets.find_by_revision('1').comments
-    end
-
-    def test_fetch_changesets_incremental
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      # Remove changesets with revision > 5
-      @repository.changesets.all.each {|c| c.destroy if c.revision.to_i > 5}
-      @project.reload
-      assert_equal 5, @repository.changesets.count
-
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-    end
-
-    def test_entries
-      entries = @repository.entries
-      assert_kind_of Redmine::Scm::Adapters::Entries, entries
-    end
-
-    def test_entries_for_invalid_path_should_return_nil
-      entries = @repository.entries('invalid_path')
-      assert_nil entries
-    end
-
-    def test_latest_changesets
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      # with limit
-      changesets = @repository.latest_changesets('', nil, 2)
-      assert_equal 2, changesets.size
-      assert_equal @repository.latest_changesets('', nil).slice(0,2), changesets
-
-      # with path
-      changesets = @repository.latest_changesets('subversion_test/folder', nil)
-      assert_equal ["10", "9", "7", "6", "5", "2"], changesets.collect(&:revision)
-
-      # with path and revision
-      changesets = @repository.latest_changesets('subversion_test/folder', 8)
-      assert_equal ["7", "6", "5", "2"], changesets.collect(&:revision)
-    end
-
-    def test_directory_listing_with_square_brackets_in_path
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      entries = @repository.entries('subversion_test/[folder_with_brackets]')
-      assert_not_nil entries, 'Expect to find entries in folder_with_brackets'
-      assert_equal 1, entries.size, 'Expect one entry in folder_with_brackets'
-      assert_equal 'README.txt', entries.first.name
-    end
-
-    def test_directory_listing_with_square_brackets_in_base
-      @project = Project.find(3)
-      @repository = Repository::Subversion.create(
-                          :project => @project,
-                          :url => "file:///#{self.class.repository_path('subversion')}/subversion_test/[folder_with_brackets]")
-
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-
-      assert_equal 1, @repository.changesets.count, 'Expected to see 1 revision'
-      assert_equal 2, @repository.filechanges.count, 'Expected to see 2 changes, dir add and file add'
-
-      entries = @repository.entries('')
-      assert_not_nil entries, 'Expect to find entries'
-      assert_equal 1, entries.size, 'Expect a single entry'
-      assert_equal 'README.txt', entries.first.name
-    end
-
-    def test_identifier
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      c = @repository.changesets.find_by_revision('1')
-      assert_equal c.revision, c.identifier
-    end
-
-    def test_find_changeset_by_empty_name
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['', ' ', nil].each do |r|
-        assert_nil @repository.find_changeset_by_name(r)
-      end
-    end
-
-    def test_identifier_nine_digit
-      c = Changeset.new(:repository => @repository, :committed_on => Time.now,
-                        :revision => '123456789', :comments => 'test')
-      assert_equal c.identifier, c.revision
-    end
-
-    def test_format_identifier
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      c = @repository.changesets.find_by_revision('1')
-      assert_equal c.format_identifier, c.revision
-    end
-
-    def test_format_identifier_nine_digit
-      c = Changeset.new(:repository => @repository, :committed_on => Time.now,
-                        :revision => '123456789', :comments => 'test')
-      assert_equal c.format_identifier, c.revision
-    end
-
-    def test_activities
-      c = Changeset.new(:repository => @repository, :committed_on => Time.now,
-                        :revision => '1', :comments => 'test')
-      assert c.event_title.include?('1:')
-      assert_equal '1', c.event_url[:rev]
-    end
-
-    def test_activities_nine_digit
-      c = Changeset.new(:repository => @repository, :committed_on => Time.now,
-                        :revision => '123456789', :comments => 'test')
-      assert c.event_title.include?('123456789:')
-      assert_equal '123456789', c.event_url[:rev]
-    end
-
-    def test_log_encoding_ignore_setting
-      with_settings :commit_logs_encoding => 'windows-1252' do
-        s1 = "\xC2\x80"
-        s2 = "\xc3\x82\xc2\x80"
-        if s1.respond_to?(:force_encoding)
-          s1.force_encoding('ISO-8859-1')
-          s2.force_encoding('UTF-8')
-          assert_equal s1.encode('UTF-8'), s2
-        end
-        c = Changeset.new(:repository => @repository,
-                          :comments   => s2,
-                          :revision   => '123',
-                          :committed_on => Time.now)
-        assert c.save
-        assert_equal s2, c.comments
-      end
-    end
-
-    def test_previous
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      changeset = @repository.find_changeset_by_name('3')
-      assert_equal @repository.find_changeset_by_name('2'), changeset.previous
-    end
-
-    def test_previous_nil
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      changeset = @repository.find_changeset_by_name('1')
-      assert_nil changeset.previous
-    end
-
-    def test_next
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      changeset = @repository.find_changeset_by_name('2')
-      assert_equal @repository.find_changeset_by_name('3'), changeset.next
-    end
-
-    def test_next_nil
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      changeset = @repository.find_changeset_by_name('11')
-      assert_nil changeset.next
-    end
-  else
-    puts "Subversion test repository NOT FOUND. Skipping unit tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/6d/6d3df7e3002585d4b82d0225bf30bfb49566483a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module NewsHelper
-end
--- a/.svn/pristine/6d/6ddb785f30a0d1233af9e71a8c3b041341c78af5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::TimeEntriesTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :time_entries
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /time_entries.xml should return time entries" do
-    get '/time_entries.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'time_entries',
-      :child => {:tag => 'time_entry', :child => {:tag => 'id', :content => '2'}}
-  end
-
-  test "GET /time_entries.xml with limit should return limited results" do
-    get '/time_entries.xml?limit=2', {}, credentials('jsmith')
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'time_entries',
-      :children => {:count => 2}
-  end
-
-  test "GET /time_entries/:id.xml should return the time entry" do
-    get '/time_entries/2.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'time_entry',
-      :child => {:tag => 'id', :content => '2'}
-  end
-
-  test "POST /time_entries.xml with issue_id should create time entry" do
-    assert_difference 'TimeEntry.count' do
-      post '/time_entries.xml', {:time_entry => {:issue_id => '1', :spent_on => '2010-12-02', :hours => '3.5', :activity_id => '11'}}, credentials('jsmith')
-    end
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-
-    entry = TimeEntry.first(:order => 'id DESC')
-    assert_equal 'jsmith', entry.user.login
-    assert_equal Issue.find(1), entry.issue
-    assert_equal Project.find(1), entry.project
-    assert_equal Date.parse('2010-12-02'), entry.spent_on
-    assert_equal 3.5, entry.hours
-    assert_equal TimeEntryActivity.find(11), entry.activity
-  end
-
-  test "POST /time_entries.xml with issue_id should accept custom fields" do
-    field = TimeEntryCustomField.create!(:name => 'Test', :field_format => 'string')
-
-    assert_difference 'TimeEntry.count' do
-      post '/time_entries.xml', {:time_entry => {
-        :issue_id => '1', :spent_on => '2010-12-02', :hours => '3.5', :activity_id => '11', :custom_fields => [{:id => field.id.to_s, :value => 'accepted'}]
-      }}, credentials('jsmith')
-    end
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-
-    entry = TimeEntry.first(:order => 'id DESC')
-    assert_equal 'accepted', entry.custom_field_value(field)
-  end
-
-  test "POST /time_entries.xml with project_id should create time entry" do
-    assert_difference 'TimeEntry.count' do
-      post '/time_entries.xml', {:time_entry => {:project_id => '1', :spent_on => '2010-12-02', :hours => '3.5', :activity_id => '11'}}, credentials('jsmith')
-    end
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-
-    entry = TimeEntry.first(:order => 'id DESC')
-    assert_equal 'jsmith', entry.user.login
-    assert_nil entry.issue
-    assert_equal Project.find(1), entry.project
-    assert_equal Date.parse('2010-12-02'), entry.spent_on
-    assert_equal 3.5, entry.hours
-    assert_equal TimeEntryActivity.find(11), entry.activity
-  end
-
-  test "POST /time_entries.xml with invalid parameters should return errors" do
-    assert_no_difference 'TimeEntry.count' do
-      post '/time_entries.xml', {:time_entry => {:project_id => '1', :spent_on => '2010-12-02', :activity_id => '11'}}, credentials('jsmith')
-    end
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', @response.content_type
-
-    assert_tag 'errors', :child => {:tag => 'error', :content => "Hours can't be blank"}
-  end
-
-  test "PUT /time_entries/:id.xml with valid parameters should update time entry" do
-    assert_no_difference 'TimeEntry.count' do
-      put '/time_entries/2.xml', {:time_entry => {:comments => 'API Update'}}, credentials('jsmith')
-    end
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_equal 'API Update', TimeEntry.find(2).comments
-  end
-
-  test "PUT /time_entries/:id.xml with invalid parameters should return errors" do
-    assert_no_difference 'TimeEntry.count' do
-      put '/time_entries/2.xml', {:time_entry => {:hours => '', :comments => 'API Update'}}, credentials('jsmith')
-    end
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', @response.content_type
-
-    assert_tag 'errors', :child => {:tag => 'error', :content => "Hours can't be blank"}
-  end
-
-  test "DELETE /time_entries/:id.xml should destroy time entry" do
-    assert_difference 'TimeEntry.count', -1 do
-      delete '/time_entries/2.xml', {}, credentials('jsmith')
-    end
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_nil TimeEntry.find_by_id(2)
-  end
-end
--- a/.svn/pristine/6e/6e61a701e2749bf002d37820f0ff37fbc966f8bd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine #:nodoc:
-  module CoreExtensions #:nodoc:
-    module String #:nodoc:
-      # Custom string inflections
-      module Inflections
-        def with_leading_slash
-          starts_with?('/') ? self : "/#{ self }"
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/6f/6f3de0785368c550e0511d7f874b1261b16e18b8.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssuesTest < ActionController::IntegrationTest
-  fixtures :projects,
-           :users,
-           :roles,
-           :members,
-           :member_roles,
-           :trackers,
-           :projects_trackers,
-           :enabled_modules,
-           :issue_statuses,
-           :issues,
-           :enumerations,
-           :custom_fields,
-           :custom_values,
-           :custom_fields_trackers
-
-  # create an issue
-  def test_add_issue
-    log_user('jsmith', 'jsmith')
-    get 'projects/1/issues/new', :tracker_id => '1'
-    assert_response :success
-    assert_template 'issues/new'
-
-    post 'projects/1/issues', :tracker_id => "1",
-                                 :issue => { :start_date => "2006-12-26",
-                                             :priority_id => "4",
-                                             :subject => "new test issue",
-                                             :category_id => "",
-                                             :description => "new issue",
-                                             :done_ratio => "0",
-                                             :due_date => "",
-                                             :assigned_to_id => "" },
-                                 :custom_fields => {'2' => 'Value for field 2'}
-    # find created issue
-    issue = Issue.find_by_subject("new test issue")
-    assert_kind_of Issue, issue
-
-    # check redirection
-    assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
-    follow_redirect!
-    assert_equal issue, assigns(:issue)
-
-    # check issue attributes
-    assert_equal 'jsmith', issue.author.login
-    assert_equal 1, issue.project.id
-    assert_equal 1, issue.status.id
-  end
-
-  # add then remove 2 attachments to an issue
-  def test_issue_attachments
-    log_user('jsmith', 'jsmith')
-    set_tmp_attachments_directory
-
-    put 'issues/1',
-         :notes => 'Some notes',
-         :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'This is an attachment'}}
-    assert_redirected_to "/issues/1"
-
-    # make sure attachment was saved
-    attachment = Issue.find(1).attachments.find_by_filename("testfile.txt")
-    assert_kind_of Attachment, attachment
-    assert_equal Issue.find(1), attachment.container
-    assert_equal 'This is an attachment', attachment.description
-    # verify the size of the attachment stored in db
-    #assert_equal file_data_1.length, attachment.filesize
-    # verify that the attachment was written to disk
-    assert File.exist?(attachment.diskfile)
-
-    # remove the attachments
-    Issue.find(1).attachments.each(&:destroy)
-    assert_equal 0, Issue.find(1).attachments.length
-  end
-
-  def test_other_formats_links_on_index
-    get '/projects/ecookbook/issues'
-
-    %w(Atom PDF CSV).each do |format|
-      assert_tag :a, :content => format,
-                     :attributes => { :href => "/projects/ecookbook/issues.#{format.downcase}",
-                                      :rel => 'nofollow' }
-    end
-  end
-
-  def test_other_formats_links_on_index_without_project_id_in_url
-    get '/issues', :project_id => 'ecookbook'
-
-    %w(Atom PDF CSV).each do |format|
-      assert_tag :a, :content => format,
-                     :attributes => { :href => "/projects/ecookbook/issues.#{format.downcase}",
-                                      :rel => 'nofollow' }
-    end
-  end
-
-  def test_pagination_links_on_index
-    Setting.per_page_options = '2'
-    get '/projects/ecookbook/issues'
-
-    assert_tag :a, :content => '2',
-                   :attributes => { :href => '/projects/ecookbook/issues?page=2' }
-
-  end
-
-  def test_pagination_links_on_index_without_project_id_in_url
-    Setting.per_page_options = '2'
-    get '/issues', :project_id => 'ecookbook'
-
-    assert_tag :a, :content => '2',
-                   :attributes => { :href => '/projects/ecookbook/issues?page=2' }
-
-  end
-
-  def test_issue_with_user_custom_field
-    @field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true, :trackers => Tracker.all)
-    Role.anonymous.add_permission! :add_issues, :edit_issues
-    users = Project.find(1).users
-    tester = users.first
-
-    # Issue form
-    get '/projects/ecookbook/issues/new'
-    assert_response :success
-    assert_tag :select,
-      :attributes => {:name => "issue[custom_field_values][#{@field.id}]"},
-      :children => {:count => (users.size + 1)}, # +1 for blank value
-      :child => {
-        :tag => 'option',
-        :attributes => {:value => tester.id.to_s},
-        :content => tester.name
-      }
-
-    # Create issue
-    assert_difference 'Issue.count' do
-      post '/projects/ecookbook/issues',
-        :issue => {
-          :tracker_id => '1',
-          :priority_id => '4',
-          :subject => 'Issue with user custom field',
-          :custom_field_values => {@field.id.to_s => users.first.id.to_s}
-        }
-    end
-    issue = Issue.first(:order => 'id DESC')
-    assert_response 302
-
-    # Issue view
-    follow_redirect!
-    assert_tag :th,
-      :content => /Tester/,
-      :sibling => {
-        :tag => 'td',
-        :content => tester.name
-      }
-    assert_tag :select,
-      :attributes => {:name => "issue[custom_field_values][#{@field.id}]"},
-      :children => {:count => (users.size + 1)}, # +1 for blank value
-      :child => {
-        :tag => 'option',
-        :attributes => {:value => tester.id.to_s, :selected => 'selected'},
-        :content => tester.name
-      }
-
-    # Update issue
-    new_tester = users[1]
-    assert_difference 'Journal.count' do
-      put "/issues/#{issue.id}",
-        :notes => 'Updating custom field',
-        :issue => {
-          :custom_field_values => {@field.id.to_s => new_tester.id.to_s}
-        }
-    end
-    assert_response 302
-
-    # Issue view
-    follow_redirect!
-    assert_tag :content => 'Tester',
-      :ancestor => {:tag => 'ul', :attributes => {:class => /details/}},
-      :sibling => {
-        :content => tester.name,
-        :sibling => {
-          :content => new_tester.name
-        }
-      }
-  end
-
-  def test_update_using_invalid_http_verbs
-    subject = 'Updated by an invalid http verb'
-
-    get '/issues/update/1', {:issue => {:subject => subject}}, credentials('jsmith')
-    assert_response 404
-    assert_not_equal subject, Issue.find(1).subject
-
-    post '/issues/1', {:issue => {:subject => subject}}, credentials('jsmith')
-    assert_response 404
-    assert_not_equal subject, Issue.find(1).subject
-  end
-
-  def test_get_watch_should_be_invalid
-    assert_no_difference 'Watcher.count' do
-      get '/watchers/watch?object_type=issue&object_id=1', {}, credentials('jsmith')
-      assert_response 404
-    end
-  end
-end
--- a/.svn/pristine/70/7005c1ac60bfaef4c1c73b8db2692b1b9a732a71.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class CommentsControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :news, :comments
-
-  def setup
-    User.current = nil
-  end
-
-  def test_add_comment
-    @request.session[:user_id] = 2
-    post :create, :id => 1, :comment => { :comments => 'This is a test comment' }
-    assert_redirected_to '/news/1'
-
-    comment = News.find(1).comments.last
-    assert_not_nil comment
-    assert_equal 'This is a test comment', comment.comments
-    assert_equal User.find(2), comment.author
-  end
-
-  def test_empty_comment_should_not_be_added
-    @request.session[:user_id] = 2
-    assert_no_difference 'Comment.count' do
-      post :create, :id => 1, :comment => { :comments => '' }
-      assert_response :redirect
-      assert_redirected_to '/news/1'
-    end
-  end
-
-  def test_create_should_be_denied_if_news_is_not_commentable
-    News.any_instance.stubs(:commentable?).returns(false)
-    @request.session[:user_id] = 2
-    assert_no_difference 'Comment.count' do
-      post :create, :id => 1, :comment => { :comments => 'This is a test comment' }
-      assert_response 403
-    end
-  end
-
-  def test_destroy_comment
-    comments_count = News.find(1).comments.size
-    @request.session[:user_id] = 2
-    delete :destroy, :id => 1, :comment_id => 2
-    assert_redirected_to '/news/1'
-    assert_nil Comment.find_by_id(2)
-    assert_equal comments_count - 1, News.find(1).comments.size
-  end
-end
--- a/.svn/pristine/70/70c517dee606cfef8e0ccb2978ba7929048caf58.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module WatchersHelper
-
-  def watcher_tag(object, user, options={})
-    ActiveSupport::Deprecation.warn "#watcher_tag is deprecated and will be removed in Redmine 3.0. Use #watcher_link instead."
-    watcher_link(object, user)
-  end
-
-  def watcher_link(objects, user)
-    return '' unless user && user.logged?
-    objects = Array.wrap(objects)
-
-    watched = Watcher.any_watched?(objects, user)
-    css = [watcher_css(objects), watched ? 'icon icon-fav' : 'icon icon-fav-off'].join(' ')
-    text = watched ? l(:button_unwatch) : l(:button_watch)
-    url = watch_path(
-      :object_type => objects.first.class.to_s.underscore,
-      :object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
-    )
-    method = watched ? 'delete' : 'post'
-
-    link_to text, url, :remote => true, :method => method, :class => css
-  end
-
-  # Returns the css class used to identify watch links for a given +object+
-  def watcher_css(objects)
-    objects = Array.wrap(objects)
-    id = (objects.size == 1 ? objects.first.id : 'bulk')
-    "#{objects.first.class.to_s.underscore}-#{id}-watcher"
-  end
-
-  # Returns a comma separated list of users watching the given object
-  def watchers_list(object)
-    remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
-    content = ''.html_safe
-    lis = object.watcher_users.collect do |user|
-      s = ''.html_safe
-      s << avatar(user, :size => "16").to_s
-      s << link_to_user(user, :class => 'user')
-      if remove_allowed
-        url = {:controller => 'watchers',
-               :action => 'destroy',
-               :object_type => object.class.to_s.underscore,
-               :object_id => object.id,
-               :user_id => user}
-        s << ' '
-        s << link_to(image_tag('delete.png'), url,
-                     :remote => true, :method => 'delete', :class => "delete")
-      end
-      content << content_tag('li', s, :class => "user-#{user.id}")
-    end
-    content.present? ? content_tag('ul', content, :class => 'watchers') : content
-  end
-
-  def watchers_checkboxes(object, users, checked=nil)
-    users.map do |user|
-      c = checked.nil? ? object.watched_by?(user) : checked
-      tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil
-      content_tag 'label', "#{tag} #{h(user)}".html_safe,
-                  :id => "issue_watcher_user_ids_#{user.id}",
-                  :class => "floating"
-    end.join.html_safe
-  end
-end
--- a/.svn/pristine/70/70e864184fd8408391ed37d61337591c474549c4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module WikiFormatting
-    module Macros
-      module Definitions
-        # Returns true if +name+ is the name of an existing macro
-        def macro_exists?(name)
-          Redmine::WikiFormatting::Macros.available_macros.key?(name.to_sym)
-        end
-
-        def exec_macro(name, obj, args, text)
-          macro_options = Redmine::WikiFormatting::Macros.available_macros[name.to_sym]
-          return unless macro_options
-
-          method_name = "macro_#{name}"
-          unless macro_options[:parse_args] == false
-            args = args.split(',').map(&:strip)
-          end
-
-          begin
-            if self.class.instance_method(method_name).arity == 3
-              send(method_name, obj, args, text)
-            elsif text
-              raise "This macro does not accept a block of text"
-            else
-              send(method_name, obj, args)
-            end
-          rescue => e
-            "<div class=\"flash error\">Error executing the <strong>#{h name}</strong> macro (#{h e.to_s})</div>".html_safe
-          end
-        end
-
-        def extract_macro_options(args, *keys)
-          options = {}
-          while args.last.to_s.strip =~ %r{^(.+?)\=(.+)$} && keys.include?($1.downcase.to_sym)
-            options[$1.downcase.to_sym] = $2
-            args.pop
-          end
-          return [args, options]
-        end
-      end
-
-      @@available_macros = {}
-      mattr_accessor :available_macros
-
-      class << self
-        # Plugins can use this method to define new macros:
-        #
-        #   Redmine::WikiFormatting::Macros.register do
-        #     desc "This is my macro"
-        #     macro :my_macro do |obj, args|
-        #       "My macro output"
-        #     end
-        #   
-        #     desc "This is my macro that accepts a block of text"
-        #     macro :my_macro do |obj, args, text|
-        #       "My macro output"
-        #     end
-        #   end
-        def register(&block)
-          class_eval(&block) if block_given?
-        end
-
-        # Defines a new macro with the given name, options and block.
-        #
-        # Options:
-        # * :desc - A description of the macro
-        # * :parse_args => false - Disables arguments parsing (the whole arguments 
-        #   string is passed to the macro)
-        #
-        # Macro blocks accept 2 or 3 arguments:
-        # * obj: the object that is rendered (eg. an Issue, a WikiContent...)
-        # * args: macro arguments
-        # * text: the block of text given to the macro (should be present only if the
-        #   macro accepts a block of text). text is a String or nil if the macro is
-        #   invoked without a block of text.  
-        #
-        # Examples:
-        # By default, when the macro is invoked, the coma separated list of arguments
-        # is split and passed to the macro block as an array. If no argument is given
-        # the macro will be invoked with an empty array:
-        #
-        #   macro :my_macro do |obj, args|
-        #     # args is an array
-        #     # and this macro do not accept a block of text
-        #   end
-        #
-        # You can disable arguments spliting with the :parse_args => false option. In
-        # this case, the full string of arguments is passed to the macro:
-        #
-        #   macro :my_macro, :parse_args => false do |obj, args|
-        #     # args is a string
-        #   end
-        #
-        # Macro can optionally accept a block of text:
-        #
-        #   macro :my_macro do |obj, args, text|
-        #     # this macro accepts a block of text
-        #   end
-        #
-        # Macros are invoked in formatted text using double curly brackets. Arguments
-        # must be enclosed in parenthesis if any. A new line after the macro name or the
-        # arguments starts the block of text that will be passe to the macro (invoking
-        # a macro that do not accept a block of text with some text will fail).
-        # Examples:
-        #
-        #   No arguments:
-        #   {{my_macro}}
-        #
-        #   With arguments:
-        #   {{my_macro(arg1, arg2)}}
-        #
-        #   With a block of text:
-        #   {{my_macro
-        #   multiple lines
-        #   of text
-        #   }}
-        #
-        #   With arguments and a block of text
-        #   {{my_macro(arg1, arg2)
-        #   multiple lines
-        #   of text
-        #   }}
-        #
-        # If a block of text is given, the closing tag }} must be at the start of a new line.
-        def macro(name, options={}, &block)
-          options.assert_valid_keys(:desc, :parse_args)
-          unless name.to_s.match(/\A\w+\z/)
-            raise "Invalid macro name: #{name} (only 0-9, A-Z, a-z and _ characters are accepted)"
-          end
-          unless block_given?
-            raise "Can not create a macro without a block!"
-          end
-          name = name.to_s.downcase.to_sym
-          available_macros[name] = {:desc => @@desc || ''}.merge(options)
-          @@desc = nil
-          Definitions.send :define_method, "macro_#{name}", &block
-        end
-
-        # Sets description for the next macro to be defined
-        def desc(txt)
-          @@desc = txt
-        end
-      end
-
-      # Builtin macros
-      desc "Sample macro."
-      macro :hello_world do |obj, args, text|
-        h("Hello world! Object: #{obj.class.name}, " + 
-          (args.empty? ? "Called with no argument" : "Arguments: #{args.join(', ')}") +
-          " and " + (text.present? ? "a #{text.size} bytes long block of text." : "no block of text.")
-        )
-      end
-
-      desc "Displays a list of all available macros, including description if available."
-      macro :macro_list do |obj, args|
-        out = ''.html_safe
-        @@available_macros.each do |macro, options|
-          out << content_tag('dt', content_tag('code', macro.to_s))
-          out << content_tag('dd', textilizable(options[:desc]))
-        end
-        content_tag('dl', out)
-      end
-
-      desc "Displays a list of child pages. With no argument, it displays the child pages of the current wiki page. Examples:\n\n" +
-             "  !{{child_pages}} -- can be used from a wiki page only\n" +
-             "  !{{child_pages(depth=2)}} -- display 2 levels nesting only\n"
-             "  !{{child_pages(Foo)}} -- lists all children of page Foo\n" +
-             "  !{{child_pages(Foo, parent=1)}} -- same as above with a link to page Foo"
-      macro :child_pages do |obj, args|
-        args, options = extract_macro_options(args, :parent, :depth)
-        options[:depth] = options[:depth].to_i if options[:depth].present?
-
-        page = nil
-        if args.size > 0
-          page = Wiki.find_page(args.first.to_s, :project => @project)
-        elsif obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)
-          page = obj.page
-        else
-          raise 'With no argument, this macro can be called from wiki pages only.'
-        end
-        raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
-        pages = page.self_and_descendants(options[:depth]).group_by(&:parent_id)
-        render_page_hierarchy(pages, options[:parent] ? page.parent_id : page.id)
-      end
-
-      desc "Include a wiki page. Example:\n\n  !{{include(Foo)}}\n\nor to include a page of a specific project wiki:\n\n  !{{include(projectname:Foo)}}"
-      macro :include do |obj, args|
-        page = Wiki.find_page(args.first.to_s, :project => @project)
-        raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
-        @included_wiki_pages ||= []
-        raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title)
-        @included_wiki_pages << page.title
-        out = textilizable(page.content, :text, :attachments => page.attachments, :headings => false)
-        @included_wiki_pages.pop
-        out
-      end
-
-      desc "Inserts of collapsed block of text. Example:\n\n  {{collapse(View details...)\nThis is a block of text that is collapsed by default.\nIt can be expanded by clicking a link.\n}}"
-      macro :collapse do |obj, args, text|
-        html_id = "collapse-#{Redmine::Utils.random_hex(4)}"
-        show_label = args[0] || l(:button_show)
-        hide_label = args[1] || args[0] || l(:button_hide)
-        js = "$('##{html_id}-show, ##{html_id}-hide').toggle(); $('##{html_id}').fadeToggle(150);"
-        out = ''.html_safe
-        out << link_to_function(show_label, js, :id => "#{html_id}-show", :class => 'collapsible collapsed')
-        out << link_to_function(hide_label, js, :id => "#{html_id}-hide", :class => 'collapsible', :style => 'display:none;')
-        out << content_tag('div', textilizable(text, :object => obj), :id => html_id, :class => 'collapsed-text', :style => 'display:none;')
-        out
-      end
-
-      desc "Displays a clickable thumbnail of an attached image. Examples:\n\n<pre>{{thumbnail(image.png)}}\n{{thumbnail(image.png, size=300, title=Thumbnail)}}</pre>"
-      macro :thumbnail do |obj, args|
-        args, options = extract_macro_options(args, :size, :title)
-        filename = args.first
-        raise 'Filename required' unless filename.present?
-        size = options[:size]
-        raise 'Invalid size parameter' unless size.nil? || size.match(/^\d+$/)
-        size = size.to_i
-        size = nil unless size > 0
-        if obj && obj.respond_to?(:attachments) && attachment = Attachment.latest_attach(obj.attachments, filename)
-          title = options[:title] || attachment.title
-          img = image_tag(url_for(:controller => 'attachments', :action => 'thumbnail', :id => attachment, :size => size), :alt => attachment.filename)
-          link_to(img, url_for(:controller => 'attachments', :action => 'show', :id => attachment), :class => 'thumbnail', :title => title)
-        else
-          raise "Attachment #{filename} not found"
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/71/714859f726ef05e105f7c83270e22457a9138242.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine #:nodoc:
-  module CoreExtensions #:nodoc:
-    module Date #:nodoc:
-      # Custom date calculations
-      module Calculations
-        # Returns difference with specified date in months
-        def months_ago(date = self.class.today)
-          (date.year - self.year)*12 + (date.month - self.month)
-        end
-
-        # Returns difference with specified date in weeks
-        def weeks_ago(date = self.class.today)
-          (date.year - self.year)*52 + (date.cweek - self.cweek)
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/72/72607bd4ab6cb744483458ba6f765737733a7ddf.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'action_view/helpers/form_helper'
-
-class Redmine::Views::LabelledFormBuilder < ActionView::Helpers::FormBuilder
-  include Redmine::I18n
-
-  (field_helpers.map(&:to_s) - %w(radio_button hidden_field fields_for) +
-        %w(date_select)).each do |selector|
-    src = <<-END_SRC
-    def #{selector}(field, options = {})
-      label_for_field(field, options) + super(field, options.except(:label)).html_safe
-    end
-    END_SRC
-    class_eval src, __FILE__, __LINE__
-  end
-
-  def select(field, choices, options = {}, html_options = {})
-    label_for_field(field, options) + super(field, choices, options, html_options.except(:label)).html_safe
-  end
-
-  def time_zone_select(field, priority_zones = nil, options = {}, html_options = {})
-        label_for_field(field, options) + super(field, priority_zones, options, html_options.except(:label)).html_safe
-  end
-
-  # Returns a label tag for the given field
-  def label_for_field(field, options = {})
-      return ''.html_safe if options.delete(:no_label)
-      text = options[:label].is_a?(Symbol) ? l(options[:label]) : options[:label]
-      text ||= l(("field_" + field.to_s.gsub(/\_id$/, "")).to_sym)
-      text += @template.content_tag("span", " *", :class => "required") if options.delete(:required)
-      @template.content_tag("label", text.html_safe,
-                                     :class => (@object && @object.errors[field].present? ? "error" : nil),
-                                     :for => (@object_name.to_s + "_" + field.to_s))
-  end
-end
--- a/.svn/pristine/73/7309716b5db2ba64867602eae0ca0931c23991c4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,225 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
-
-  class BazaarAdapterTest < ActiveSupport::TestCase
-    REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
-    REPOSITORY_PATH.gsub!(/\/+/, '/')
-
-    if File.directory?(REPOSITORY_PATH)
-      def setup
-        @adapter = Redmine::Scm::Adapters::BazaarAdapter.new(
-                                File.join(REPOSITORY_PATH, "trunk")
-                                )
-      end
-
-      def test_scm_version
-        to_test = { "Bazaar (bzr) 2.1.2\n"             => [2,1,2],
-                    "2.1.1\n1.7\n1.8"                  => [2,1,1],
-                    "2.0.1\r\n1.8.1\r\n1.9.1"          => [2,0,1]}
-        to_test.each do |s, v|
-          test_scm_version_for(s, v)
-        end
-      end
-
-      def test_cat
-        cat = @adapter.cat('directory/document.txt')
-        assert cat =~ /Write the contents of a file as of a given revision to standard output/
-      end
-
-      def test_cat_path_invalid
-        assert_nil @adapter.cat('invalid')
-      end
-
-      def test_cat_revision_invalid
-        assert_nil @adapter.cat('doc-mkdir.txt', '12345678')
-      end
-
-      def test_diff
-        diff1 = @adapter.diff('doc-mkdir.txt', 3, 2)
-        assert_equal 21, diff1.size
-        buf =  diff1[14].gsub(/\r\n|\r|\n/, "")
-        assert_equal "-Display more information.", buf
-      end
-
-      def test_diff_path_invalid
-        assert_equal [], @adapter.diff('invalid', 1)
-      end
-
-      def test_diff_revision_invalid
-        assert_equal [], @adapter.diff(nil, 12345678)
-        assert_equal [], @adapter.diff(nil, 12345678, 87654321)
-      end
-
-      def test_annotate
-        annotate = @adapter.annotate('doc-mkdir.txt')
-        assert_equal 17, annotate.lines.size
-        assert_equal '1', annotate.revisions[0].identifier
-        assert_equal 'jsmith@', annotate.revisions[0].author
-        assert_equal 'mkdir', annotate.lines[0]
-      end
-
-      def test_annotate_path_invalid
-        assert_nil @adapter.annotate('invalid')
-      end
-
-      def test_annotate_revision_invalid
-        assert_nil @adapter.annotate('doc-mkdir.txt', '12345678')
-      end
-
-      def test_branch_conf_path
-        p = "c:\\test\\test\\"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-        p = "c:\\test\\test\\.bzr"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-        p = "c:\\test\\test\\.bzr\\"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-        p = "c:\\test\\test"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-        p = "\\\\server\\test\\test\\"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("\\\\server\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-      end
-
-      def test_append_revisions_only_true
-        assert_equal true, @adapter.append_revisions_only
-      end
-
-      def test_append_revisions_only_false
-        adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
-                                File.join(REPOSITORY_PATH, "empty-branch")
-                                )
-        assert_equal false, adpt.append_revisions_only
-      end
-
-      def test_append_revisions_only_shared_repo
-        adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
-                                REPOSITORY_PATH
-                                )
-        assert_equal false, adpt.append_revisions_only
-      end
-
-      def test_info_not_nil
-        assert_not_nil @adapter.info
-      end
-
-      def test_info_nil
-        adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
-                  "/invalid/invalid/"
-                  )
-        assert_nil adpt.info
-      end
-
-      def test_info
-        info = @adapter.info
-        assert_equal 4, info.lastrev.identifier.to_i
-      end
-
-      def test_info_emtpy
-        adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
-                                File.join(REPOSITORY_PATH, "empty-branch")
-                                )
-        assert_equal 0, adpt.info.lastrev.identifier.to_i
-      end
-
-      def test_entries_path_invalid
-        assert_equal [], @adapter.entries('invalid')
-      end
-
-      def test_entries_revision_invalid
-        assert_nil @adapter.entries(nil, 12345678)
-      end
-
-      def test_revisions
-        revisions = @adapter.revisions(nil, 4, 2)
-        assert_equal 3, revisions.size
-        assert_equal 2, revisions[2].identifier
-        assert_equal 'jsmith@foo.bar-20071203175224-v0eog5d5wrgdrshg', revisions[2].scmid
-        assert_equal 4, revisions[0].identifier
-        assert_equal 'jsmith@foo.bar-20071203175422-t40bf8li5zz0c4cg', revisions[0].scmid
-        assert_equal 2, revisions[0].paths.size
-        assert_equal 'D', revisions[0].paths[0][:action]
-        assert_equal '/doc-deleted.txt', revisions[0].paths[0][:path]
-        assert_equal 'docdeleted.txt-20071203175320-iwwj561ojuubs3gt-1', revisions[0].paths[0][:revision]
-        assert_equal 'M', revisions[0].paths[1][:action]
-        assert_equal '/directory/doc-ls.txt', revisions[0].paths[1][:path]
-        assert_equal 'docls.txt-20071203175005-a3hyc3mn0shl7cgu-1', revisions[0].paths[1][:revision]
-      end
-
-      def test_revisions_path_invalid
-        assert_nil @adapter.revisions('invalid')
-      end
-
-      def test_revisions_revision_invalid
-        assert_nil @adapter.revisions(nil, 12345678)
-        assert_nil @adapter.revisions(nil, 12345678, 87654321)
-      end
-
-      def test_entry
-        entry = @adapter.entry()
-        assert_equal "", entry.path
-        assert_equal "dir", entry.kind
-        entry = @adapter.entry('')
-        assert_equal "", entry.path
-        assert_equal "dir", entry.kind
-        assert_nil @adapter.entry('invalid')
-        assert_nil @adapter.entry('/invalid')
-        assert_nil @adapter.entry('/invalid/')
-        assert_nil @adapter.entry('invalid/invalid')
-        assert_nil @adapter.entry('invalid/invalid/')
-        assert_nil @adapter.entry('/invalid/invalid')
-        assert_nil @adapter.entry('/invalid/invalid/')
-        ["doc-ls.txt", "/doc-ls.txt"].each do |path|
-          entry = @adapter.entry(path, 2)
-          assert_equal "doc-ls.txt", entry.path
-          assert_equal "file", entry.kind
-        end
-        ["directory", "/directory", "/directory/"].each do |path|
-          entry = @adapter.entry(path, 2)
-          assert_equal "directory", entry.path
-          assert_equal "dir", entry.kind
-        end
-        ["directory/document.txt", "/directory/document.txt"].each do |path|
-          entry = @adapter.entry(path, 2)
-          assert_equal "directory/document.txt", entry.path
-          assert_equal "file", entry.kind
-        end
-      end
-
-      private
-
-      def test_scm_version_for(scm_command_version, version)
-        @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
-        assert_equal version, @adapter.class.scm_command_version
-      end
-    else
-      puts "Bazaar test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
-    end
-  end
-rescue LoadError
-  class BazaarMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
-  end
-end
--- a/.svn/pristine/73/7324b60def8b61259e4fe88d626f6df74b027500.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,468 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-#require 'shoulda'
-ENV["RAILS_ENV"] = "test"
-require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
-require 'rails/test_help'
-require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
-
-require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
-include ObjectHelpers
-
-class ActiveSupport::TestCase
-  include ActionDispatch::TestProcess
-
-  self.use_transactional_fixtures = true
-  self.use_instantiated_fixtures  = false
-
-  def log_user(login, password)
-    User.anonymous
-    get "/login"
-    assert_equal nil, session[:user_id]
-    assert_response :success
-    assert_template "account/login"
-    post "/login", :username => login, :password => password
-    assert_equal login, User.find(session[:user_id]).login
-  end
-
-  def uploaded_test_file(name, mime)
-    fixture_file_upload("files/#{name}", mime, true)
-  end
-
-  def credentials(user, password=nil)
-    {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
-  end
-
-  # Mock out a file
-  def self.mock_file
-    file = 'a_file.png'
-    file.stubs(:size).returns(32)
-    file.stubs(:original_filename).returns('a_file.png')
-    file.stubs(:content_type).returns('image/png')
-    file.stubs(:read).returns(false)
-    file
-  end
-
-  def mock_file
-    self.class.mock_file
-  end
-
-  def mock_file_with_options(options={})
-    file = ''
-    file.stubs(:size).returns(32)
-    original_filename = options[:original_filename] || nil
-    file.stubs(:original_filename).returns(original_filename)
-    content_type = options[:content_type] || nil
-    file.stubs(:content_type).returns(content_type)
-    file.stubs(:read).returns(false)
-    file
-  end
-
-  # Use a temporary directory for attachment related tests
-  def set_tmp_attachments_directory
-    Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
-    unless File.directory?("#{Rails.root}/tmp/test/attachments")
-      Dir.mkdir "#{Rails.root}/tmp/test/attachments"
-    end
-    Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
-  end
-
-  def set_fixtures_attachments_directory
-    Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
-  end
-
-  def with_settings(options, &block)
-    saved_settings = options.keys.inject({}) do |h, k|
-      h[k] = case Setting[k]
-        when Symbol, false, true, nil
-          Setting[k]
-        else
-          Setting[k].dup
-        end
-      h
-    end
-    options.each {|k, v| Setting[k] = v}
-    yield
-  ensure
-    saved_settings.each {|k, v| Setting[k] = v} if saved_settings
-  end
-
-  # Yields the block with user as the current user
-  def with_current_user(user, &block)
-    saved_user = User.current
-    User.current = user
-    yield
-  ensure
-    User.current = saved_user
-  end
-
-  def change_user_password(login, new_password)
-    user = User.where(:login => login).first
-    user.password, user.password_confirmation = new_password, new_password
-    user.save!
-  end
-
-  def self.ldap_configured?
-    @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
-    return @test_ldap.bind
-  rescue Exception => e
-    # LDAP is not listening
-    return nil
-  end
-
-  def self.convert_installed?
-    Redmine::Thumbnail.convert_available?
-  end
-
-  # Returns the path to the test +vendor+ repository
-  def self.repository_path(vendor)
-    Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
-  end
-
-  # Returns the url of the subversion test repository
-  def self.subversion_repository_url
-    path = repository_path('subversion')
-    path = '/' + path unless path.starts_with?('/')
-    "file://#{path}"
-  end
-
-  # Returns true if the +vendor+ test repository is configured
-  def self.repository_configured?(vendor)
-    File.directory?(repository_path(vendor))
-  end
-
-  def repository_path_hash(arr)
-    hs = {}
-    hs[:path]  = arr.join("/")
-    hs[:param] = arr.join("/")
-    hs
-  end
-
-  def assert_save(object)
-    saved = object.save
-    message = "#{object.class} could not be saved"
-    errors = object.errors.full_messages.map {|m| "- #{m}"}
-    message << ":\n#{errors.join("\n")}" if errors.any?
-    assert_equal true, saved, message
-  end
-
-  def assert_error_tag(options={})
-    assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
-  end
-
-  def assert_include(expected, s, message=nil)
-    assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"")
-  end
-
-  def assert_not_include(expected, s, message=nil)
-    assert !s.include?(expected), (message || "\"#{expected}\" found in \"#{s}\"")
-  end
-
-  def assert_select_in(text, *args, &block)
-    d = HTML::Document.new(CGI::unescapeHTML(String.new(text))).root
-    assert_select(d, *args, &block)
-  end
-
-  def assert_mail_body_match(expected, mail, message=nil)
-    if expected.is_a?(String)
-      assert_include expected, mail_body(mail), message
-    else
-      assert_match expected, mail_body(mail), message
-    end
-  end
-
-  def assert_mail_body_no_match(expected, mail, message=nil)
-    if expected.is_a?(String)
-      assert_not_include expected, mail_body(mail), message
-    else
-      assert_no_match expected, mail_body(mail), message
-    end
-  end
-
-  def mail_body(mail)
-    mail.parts.first.body.encoded
-  end
-end
-
-module Redmine
-  module ApiTest
-    # Base class for API tests
-    class Base < ActionDispatch::IntegrationTest
-      # Test that a request allows the three types of API authentication
-      #
-      # * HTTP Basic with username and password
-      # * HTTP Basic with an api key for the username
-      # * Key based with the key=X parameter
-      #
-      # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
-      # @param [String] url the request url
-      # @param [optional, Hash] parameters additional request parameters
-      # @param [optional, Hash] options additional options
-      # @option options [Symbol] :success_code Successful response code (:success)
-      # @option options [Symbol] :failure_code Failure response code (:unauthorized)
-      def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
-        should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
-        should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
-        should_allow_key_based_auth(http_method, url, parameters, options)
-      end
-    
-      # Test that a request allows the username and password for HTTP BASIC
-      #
-      # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
-      # @param [String] url the request url
-      # @param [optional, Hash] parameters additional request parameters
-      # @param [optional, Hash] options additional options
-      # @option options [Symbol] :success_code Successful response code (:success)
-      # @option options [Symbol] :failure_code Failure response code (:unauthorized)
-      def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
-        success_code = options[:success_code] || :success
-        failure_code = options[:failure_code] || :unauthorized
-    
-        context "should allow http basic auth using a username and password for #{http_method} #{url}" do
-          context "with a valid HTTP authentication" do
-            setup do
-              @user = User.generate! do |user|
-                user.admin = true
-                user.password = 'my_password'
-              end
-              send(http_method, url, parameters, credentials(@user.login, 'my_password'))
-            end
-    
-            should_respond_with success_code
-            should_respond_with_content_type_based_on_url(url)
-            should "login as the user" do
-              assert_equal @user, User.current
-            end
-          end
-    
-          context "with an invalid HTTP authentication" do
-            setup do
-              @user = User.generate!
-              send(http_method, url, parameters, credentials(@user.login, 'wrong_password'))
-            end
-    
-            should_respond_with failure_code
-            should_respond_with_content_type_based_on_url(url)
-            should "not login as the user" do
-              assert_equal User.anonymous, User.current
-            end
-          end
-    
-          context "without credentials" do
-            setup do
-              send(http_method, url, parameters)
-            end
-    
-            should_respond_with failure_code
-            should_respond_with_content_type_based_on_url(url)
-            should "include_www_authenticate_header" do
-              assert @controller.response.headers.has_key?('WWW-Authenticate')
-            end
-          end
-        end
-      end
-    
-      # Test that a request allows the API key with HTTP BASIC
-      #
-      # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
-      # @param [String] url the request url
-      # @param [optional, Hash] parameters additional request parameters
-      # @param [optional, Hash] options additional options
-      # @option options [Symbol] :success_code Successful response code (:success)
-      # @option options [Symbol] :failure_code Failure response code (:unauthorized)
-      def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
-        success_code = options[:success_code] || :success
-        failure_code = options[:failure_code] || :unauthorized
-    
-        context "should allow http basic auth with a key for #{http_method} #{url}" do
-          context "with a valid HTTP authentication using the API token" do
-            setup do
-              @user = User.generate! do |user|
-                user.admin = true
-              end
-              @token = Token.create!(:user => @user, :action => 'api')
-              send(http_method, url, parameters, credentials(@token.value, 'X'))
-            end
-            should_respond_with success_code
-            should_respond_with_content_type_based_on_url(url)
-            should_be_a_valid_response_string_based_on_url(url)
-            should "login as the user" do
-              assert_equal @user, User.current
-            end
-          end
-    
-          context "with an invalid HTTP authentication" do
-            setup do
-              @user = User.generate!
-              @token = Token.create!(:user => @user, :action => 'feeds')
-              send(http_method, url, parameters, credentials(@token.value, 'X'))
-            end
-            should_respond_with failure_code
-            should_respond_with_content_type_based_on_url(url)
-            should "not login as the user" do
-              assert_equal User.anonymous, User.current
-            end
-          end
-        end
-      end
-    
-      # Test that a request allows full key authentication
-      #
-      # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
-      # @param [String] url the request url, without the key=ZXY parameter
-      # @param [optional, Hash] parameters additional request parameters
-      # @param [optional, Hash] options additional options
-      # @option options [Symbol] :success_code Successful response code (:success)
-      # @option options [Symbol] :failure_code Failure response code (:unauthorized)
-      def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
-        success_code = options[:success_code] || :success
-        failure_code = options[:failure_code] || :unauthorized
-    
-        context "should allow key based auth using key=X for #{http_method} #{url}" do
-          context "with a valid api token" do
-            setup do
-              @user = User.generate! do |user|
-                user.admin = true
-              end
-              @token = Token.create!(:user => @user, :action => 'api')
-              # Simple url parse to add on ?key= or &key=
-              request_url = if url.match(/\?/)
-                              url + "&key=#{@token.value}"
-                            else
-                              url + "?key=#{@token.value}"
-                            end
-              send(http_method, request_url, parameters)
-            end
-            should_respond_with success_code
-            should_respond_with_content_type_based_on_url(url)
-            should_be_a_valid_response_string_based_on_url(url)
-            should "login as the user" do
-              assert_equal @user, User.current
-            end
-          end
-    
-          context "with an invalid api token" do
-            setup do
-              @user = User.generate! do |user|
-                user.admin = true
-              end
-              @token = Token.create!(:user => @user, :action => 'feeds')
-              # Simple url parse to add on ?key= or &key=
-              request_url = if url.match(/\?/)
-                              url + "&key=#{@token.value}"
-                            else
-                              url + "?key=#{@token.value}"
-                            end
-              send(http_method, request_url, parameters)
-            end
-            should_respond_with failure_code
-            should_respond_with_content_type_based_on_url(url)
-            should "not login as the user" do
-              assert_equal User.anonymous, User.current
-            end
-          end
-        end
-    
-        context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
-          setup do
-            @user = User.generate! do |user|
-              user.admin = true
-            end
-            @token = Token.create!(:user => @user, :action => 'api')
-            send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
-          end
-          should_respond_with success_code
-          should_respond_with_content_type_based_on_url(url)
-          should_be_a_valid_response_string_based_on_url(url)
-          should "login as the user" do
-            assert_equal @user, User.current
-          end
-        end
-      end
-    
-      # Uses should_respond_with_content_type based on what's in the url:
-      #
-      # '/project/issues.xml' => should_respond_with_content_type :xml
-      # '/project/issues.json' => should_respond_with_content_type :json
-      #
-      # @param [String] url Request
-      def self.should_respond_with_content_type_based_on_url(url)
-        case
-        when url.match(/xml/i)
-          should "respond with XML" do
-            assert_equal 'application/xml', @response.content_type
-          end
-        when url.match(/json/i)
-          should "respond with JSON" do
-            assert_equal 'application/json', @response.content_type
-          end
-        else
-          raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
-        end
-      end
-    
-      # Uses the url to assert which format the response should be in
-      #
-      # '/project/issues.xml' => should_be_a_valid_xml_string
-      # '/project/issues.json' => should_be_a_valid_json_string
-      #
-      # @param [String] url Request
-      def self.should_be_a_valid_response_string_based_on_url(url)
-        case
-        when url.match(/xml/i)
-          should_be_a_valid_xml_string
-        when url.match(/json/i)
-          should_be_a_valid_json_string
-        else
-          raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
-        end
-      end
-    
-      # Checks that the response is a valid JSON string
-      def self.should_be_a_valid_json_string
-        should "be a valid JSON string (or empty)" do
-          assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
-        end
-      end
-    
-      # Checks that the response is a valid XML string
-      def self.should_be_a_valid_xml_string
-        should "be a valid XML string" do
-          assert REXML::Document.new(response.body)
-        end
-      end
-    
-      def self.should_respond_with(status)
-        should "respond with #{status}" do
-          assert_response status
-        end
-      end
-    end
-  end
-end
-
-# URL helpers do not work with config.threadsafe!
-# https://github.com/rspec/rspec-rails/issues/476#issuecomment-4705454
-ActionView::TestCase::TestController.instance_eval do
-  helper Rails.application.routes.url_helpers
-end
-ActionView::TestCase::TestController.class_eval do
-  def _routes
-    Rails.application.routes
-  end
-end
--- a/.svn/pristine/73/73cf79b8d745cac74b4b29d58fecb04843a6f726.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class VersionTest < ActiveSupport::TestCase
-  fixtures :projects, :users, :issues, :issue_statuses, :trackers,
-           :enumerations, :versions, :projects_trackers
-
-  def test_create
-    v = Version.new(:project => Project.find(1), :name => '1.1',
-                    :effective_date => '2011-03-25')
-    assert v.save
-    assert_equal 'open', v.status
-    assert_equal 'none', v.sharing
-  end
-
-  def test_invalid_effective_date_validation
-    v = Version.new(:project => Project.find(1), :name => '1.1',
-                    :effective_date => '99999-01-01')
-    assert !v.valid?
-    v.effective_date = '2012-11-33'
-    assert !v.valid?
-    v.effective_date = '2012-31-11'
-    assert !v.valid?
-    v.effective_date = '-2012-31-11'
-    assert !v.valid?
-    v.effective_date = 'ABC'
-    assert !v.valid?
-    assert_include I18n.translate('activerecord.errors.messages.not_a_date'),
-                   v.errors[:effective_date]
-  end
-
-  def test_progress_should_be_0_with_no_assigned_issues
-    project = Project.find(1)
-    v = Version.create!(:project => project, :name => 'Progress')
-    assert_equal 0, v.completed_percent
-    assert_equal 0, v.closed_percent
-  end
-
-  def test_progress_should_be_0_with_unbegun_assigned_issues
-    project = Project.find(1)
-    v = Version.create!(:project => project, :name => 'Progress')
-    add_issue(v)
-    add_issue(v, :done_ratio => 0)
-    assert_progress_equal 0, v.completed_percent
-    assert_progress_equal 0, v.closed_percent
-  end
-
-  def test_progress_should_be_100_with_closed_assigned_issues
-    project = Project.find(1)
-    status = IssueStatus.where(:is_closed => true).first
-    v = Version.create!(:project => project, :name => 'Progress')
-    add_issue(v, :status => status)
-    add_issue(v, :status => status, :done_ratio => 20)
-    add_issue(v, :status => status, :done_ratio => 70, :estimated_hours => 25)
-    add_issue(v, :status => status, :estimated_hours => 15)
-    assert_progress_equal 100.0, v.completed_percent
-    assert_progress_equal 100.0, v.closed_percent
-  end
-
-  def test_progress_should_consider_done_ratio_of_open_assigned_issues
-    project = Project.find(1)
-    v = Version.create!(:project => project, :name => 'Progress')
-    add_issue(v)
-    add_issue(v, :done_ratio => 20)
-    add_issue(v, :done_ratio => 70)
-    assert_progress_equal (0.0 + 20.0 + 70.0)/3, v.completed_percent
-    assert_progress_equal 0, v.closed_percent
-  end
-
-  def test_progress_should_consider_closed_issues_as_completed
-    project = Project.find(1)
-    v = Version.create!(:project => project, :name => 'Progress')
-    add_issue(v)
-    add_issue(v, :done_ratio => 20)
-    add_issue(v, :status => IssueStatus.where(:is_closed => true).first)
-    assert_progress_equal (0.0 + 20.0 + 100.0)/3, v.completed_percent
-    assert_progress_equal (100.0)/3, v.closed_percent
-  end
-
-  def test_progress_should_consider_estimated_hours_to_weigth_issues
-    project = Project.find(1)
-    v = Version.create!(:project => project, :name => 'Progress')
-    add_issue(v, :estimated_hours => 10)
-    add_issue(v, :estimated_hours => 20, :done_ratio => 30)
-    add_issue(v, :estimated_hours => 40, :done_ratio => 10)
-    add_issue(v, :estimated_hours => 25, :status => IssueStatus.where(:is_closed => true).first)
-    assert_progress_equal (10.0*0 + 20.0*0.3 + 40*0.1 + 25.0*1)/95.0*100, v.completed_percent
-    assert_progress_equal 25.0/95.0*100, v.closed_percent
-  end
-
-  def test_progress_should_consider_average_estimated_hours_to_weigth_unestimated_issues
-    project = Project.find(1)
-    v = Version.create!(:project => project, :name => 'Progress')
-    add_issue(v, :done_ratio => 20)
-    add_issue(v, :status => IssueStatus.where(:is_closed => true).first)
-    add_issue(v, :estimated_hours => 10, :done_ratio => 30)
-    add_issue(v, :estimated_hours => 40, :done_ratio => 10)
-    assert_progress_equal (25.0*0.2 + 25.0*1 + 10.0*0.3 + 40.0*0.1)/100.0*100, v.completed_percent
-    assert_progress_equal 25.0/100.0*100, v.closed_percent
-  end
-
-  def test_should_sort_scheduled_then_unscheduled_versions
-    Version.delete_all
-    v4 = Version.create!(:project_id => 1, :name => 'v4')
-    v3 = Version.create!(:project_id => 1, :name => 'v2', :effective_date => '2012-07-14')
-    v2 = Version.create!(:project_id => 1, :name => 'v1')
-    v1 = Version.create!(:project_id => 1, :name => 'v3', :effective_date => '2012-08-02')
-    v5 = Version.create!(:project_id => 1, :name => 'v5', :effective_date => '2012-07-02')
-
-    assert_equal [v5, v3, v1, v2, v4], [v1, v2, v3, v4, v5].sort
-    assert_equal [v5, v3, v1, v2, v4], Version.sorted.all
-  end
-
-  def test_completed_should_be_false_when_due_today
-    version = Version.create!(:project_id => 1, :effective_date => Date.today, :name => 'Due today')
-    assert_equal false, version.completed?
-  end
-
-  test "#behind_schedule? should be false if there are no issues assigned" do
-    version = Version.generate!(:effective_date => Date.yesterday)
-    assert_equal false, version.behind_schedule?
-  end
-
-  test "#behind_schedule? should be false if there is no effective_date" do
-    version = Version.generate!(:effective_date => nil)
-    assert_equal false, version.behind_schedule?
-  end
-
-  test "#behind_schedule? should be false if all of the issues are ahead of schedule" do
-    version = Version.create!(:project_id => 1, :name => 'test', :effective_date => 7.days.from_now.to_date)
-    add_issue(version, :start_date => 7.days.ago, :done_ratio => 60) # 14 day span, 60% done, 50% time left
-    add_issue(version, :start_date => 7.days.ago, :done_ratio => 60) # 14 day span, 60% done, 50% time left
-    assert_equal 60, version.completed_percent
-    assert_equal false, version.behind_schedule?
-  end
-
-  test "#behind_schedule? should be true if any of the issues are behind schedule" do
-    version = Version.create!(:project_id => 1, :name => 'test', :effective_date => 7.days.from_now.to_date)
-    add_issue(version, :start_date => 7.days.ago, :done_ratio => 60) # 14 day span, 60% done, 50% time left
-    add_issue(version, :start_date => 7.days.ago, :done_ratio => 20) # 14 day span, 20% done, 50% time left
-    assert_equal 40, version.completed_percent
-    assert_equal true, version.behind_schedule?
-  end
-
-  test "#behind_schedule? should be false if all of the issues are complete" do
-    version = Version.create!(:project_id => 1, :name => 'test', :effective_date => 7.days.from_now.to_date)
-    add_issue(version, :start_date => 14.days.ago, :done_ratio => 100, :status => IssueStatus.find(5)) # 7 day span
-    add_issue(version, :start_date => 14.days.ago, :done_ratio => 100, :status => IssueStatus.find(5)) # 7 day span
-    assert_equal 100, version.completed_percent
-    assert_equal false, version.behind_schedule?
-  end
-
-  test "#estimated_hours should return 0 with no assigned issues" do
-    version = Version.generate!
-    assert_equal 0, version.estimated_hours
-  end
-
-  test "#estimated_hours should return 0 with no estimated hours" do
-    version = Version.create!(:project_id => 1, :name => 'test')
-    add_issue(version)
-    assert_equal 0, version.estimated_hours
-  end
-
-  test "#estimated_hours should return return the sum of estimated hours" do
-    version = Version.create!(:project_id => 1, :name => 'test')
-    add_issue(version, :estimated_hours => 2.5)
-    add_issue(version, :estimated_hours => 5)
-    assert_equal 7.5, version.estimated_hours
-  end
-
-  test "#estimated_hours should return the sum of leaves estimated hours" do
-    version = Version.create!(:project_id => 1, :name => 'test')
-    parent = add_issue(version)
-    add_issue(version, :estimated_hours => 2.5, :parent_issue_id => parent.id)
-    add_issue(version, :estimated_hours => 5, :parent_issue_id => parent.id)
-    assert_equal 7.5, version.estimated_hours
-  end
-
-  test "should update all issue's fixed_version associations in case the hierarchy changed XXX" do
-    User.current = User.find(1) # Need the admin's permissions
-
-    @version = Version.find(7)
-    # Separate hierarchy
-    project_1_issue = Issue.find(1)
-    project_1_issue.fixed_version = @version
-    assert project_1_issue.save, project_1_issue.errors.full_messages.to_s
-
-    project_5_issue = Issue.find(6)
-    project_5_issue.fixed_version = @version
-    assert project_5_issue.save
-
-    # Project
-    project_2_issue = Issue.find(4)
-    project_2_issue.fixed_version = @version
-    assert project_2_issue.save
-
-    # Update the sharing
-    @version.sharing = 'none'
-    assert @version.save
-
-    # Project 1 now out of the shared scope
-    project_1_issue.reload
-    assert_equal nil, project_1_issue.fixed_version,
-                "Fixed version is still set after changing the Version's sharing"
-
-    # Project 5 now out of the shared scope
-    project_5_issue.reload
-    assert_equal nil, project_5_issue.fixed_version,
-                "Fixed version is still set after changing the Version's sharing"
-
-    # Project 2 issue remains
-    project_2_issue.reload
-    assert_equal @version, project_2_issue.fixed_version
-  end
-
-  private
-
-  def add_issue(version, attributes={})
-    Issue.create!({:project => version.project,
-                   :fixed_version => version,
-                   :subject => 'Test',
-                   :author => User.first,
-                   :tracker => version.project.trackers.first}.merge(attributes))
-  end
-
-  def assert_progress_equal(expected_float, actual_float, message="")
-    assert_in_delta(expected_float, actual_float, 0.000001, message="")
-  end
-end
--- a/.svn/pristine/74/74bcc529787db769558f2ce1cd97484fa4286471.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class QueriesController < ApplicationController
-  menu_item :issues
-  before_filter :find_query, :except => [:new, :create, :index]
-  before_filter :find_optional_project, :only => [:new, :create]
-
-  accept_api_auth :index
-
-  include QueriesHelper
-
-  def index
-    case params[:format]
-    when 'xml', 'json'
-      @offset, @limit = api_offset_and_limit
-    else
-      @limit = per_page_option
-    end
-
-    @query_count = IssueQuery.visible.count
-    @query_pages = Paginator.new @query_count, @limit, params['page']
-    @queries = IssueQuery.visible.all(:limit => @limit, :offset => @offset, :order => "#{Query.table_name}.name")
-
-    respond_to do |format|
-      format.api
-    end
-  end
-
-  def new
-    @query = IssueQuery.new
-    @query.user = User.current
-    @query.project = @project
-    @query.visibility = IssueQuery::VISIBILITY_PRIVATE unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
-    @query.build_from_params(params)
-  end
-
-  def create
-    @query = IssueQuery.new(params[:query])
-    @query.user = User.current
-    @query.project = params[:query_is_for_all] ? nil : @project
-    @query.visibility = IssueQuery::VISIBILITY_PRIVATE unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
-    @query.build_from_params(params)
-    @query.column_names = nil if params[:default_columns]
-
-    if @query.save
-      flash[:notice] = l(:notice_successful_create)
-      redirect_to_issues(:query_id => @query)
-    else
-      render :action => 'new', :layout => !request.xhr?
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    @query.attributes = params[:query]
-    @query.project = nil if params[:query_is_for_all]
-    @query.visibility = IssueQuery::VISIBILITY_PRIVATE unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
-    @query.build_from_params(params)
-    @query.column_names = nil if params[:default_columns]
-
-    if @query.save
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to_issues(:query_id => @query)
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def destroy
-    @query.destroy
-    redirect_to_issues(:set_filter => 1)
-  end
-
-private
-  def find_query
-    @query = IssueQuery.find(params[:id])
-    @project = @query.project
-    render_403 unless @query.editable_by?(User.current)
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def find_optional_project
-    @project = Project.find(params[:project_id]) if params[:project_id]
-    render_403 unless User.current.allowed_to?(:save_queries, @project, :global => true)
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def redirect_to_issues(options)
-    if params[:gantt]
-      if @project
-        redirect_to project_gantt_path(@project, options)
-      else
-        redirect_to issues_gantt_path(options)
-      end
-    else
-      redirect_to _project_issues_path(@project, options)
-    end
-  end
-end
--- a/.svn/pristine/75/75cbf5c4f829621de0ddf156af2f88bad5bed475.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class VersionsControllerTest < ActionController::TestCase
-  fixtures :projects, :versions, :issues, :users, :roles, :members,
-           :member_roles, :enabled_modules, :issue_statuses,
-           :issue_categories
-
-  def setup
-    User.current = nil
-  end
-
-  def test_index
-    get :index, :project_id => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:versions)
-    # Version with no date set appears
-    assert assigns(:versions).include?(Version.find(3))
-    # Completed version doesn't appear
-    assert !assigns(:versions).include?(Version.find(1))
-    # Context menu on issues
-    assert_select "script", :text => Regexp.new(Regexp.escape("contextMenuInit('/issues/context_menu')"))
-    assert_select "div#sidebar" do
-      # Links to versions anchors
-      assert_select 'a[href=?]', '#2.0'
-      # Links to completed versions in the sidebar
-      assert_select 'a[href=?]', '/versions/1'
-    end
-  end
-
-  def test_index_with_completed_versions
-    get :index, :project_id => 1, :completed => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:versions)
-    # Version with no date set appears
-    assert assigns(:versions).include?(Version.find(3))
-    # Completed version appears
-    assert assigns(:versions).include?(Version.find(1))
-  end
-
-  def test_index_with_tracker_ids
-    get :index, :project_id => 1, :tracker_ids => [1, 3]
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues_by_version)
-    assert_nil assigns(:issues_by_version).values.flatten.detect {|issue| issue.tracker_id == 2}
-  end
-
-  def test_index_showing_subprojects_versions
-    @subproject_version = Version.create!(:project => Project.find(3), :name => "Subproject version")
-    get :index, :project_id => 1, :with_subprojects => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:versions)
-
-    assert assigns(:versions).include?(Version.find(4)), "Shared version not found"
-    assert assigns(:versions).include?(@subproject_version), "Subproject version not found"
-  end
-
-  def test_index_should_prepend_shared_versions
-    get :index, :project_id => 1
-    assert_response :success
-
-    assert_select '#sidebar' do
-      assert_select 'a[href=?]', '#2.0', :text => '2.0'
-      assert_select 'a[href=?]', '#subproject1-2.0', :text => 'eCookbook Subproject 1 - 2.0'
-    end
-    assert_select '#content' do
-      assert_select 'a[name=?]', '2.0', :text => '2.0'
-      assert_select 'a[name=?]', 'subproject1-2.0', :text => 'eCookbook Subproject 1 - 2.0'
-    end
-  end
-
-  def test_show
-    get :show, :id => 2
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:version)
-
-    assert_tag :tag => 'h2', :content => /1.0/
-  end
-
-  def test_show_should_display_nil_counts
-    with_settings :default_language => 'en' do
-      get :show, :id => 2, :status_by => 'category'
-      assert_response :success
-      assert_select 'div#status_by' do
-        assert_select 'select[name=status_by]' do
-          assert_select 'option[value=category][selected=selected]'
-        end
-        assert_select 'a', :text => 'none'
-      end
-    end
-  end
-
-  def test_new
-    @request.session[:user_id] = 2
-    get :new, :project_id => '1'
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_new_from_issue_form
-    @request.session[:user_id] = 2
-    xhr :get, :new, :project_id => '1'
-    assert_response :success
-    assert_template 'new'
-    assert_equal 'text/javascript', response.content_type
-  end
-
-  def test_create
-    @request.session[:user_id] = 2 # manager
-    assert_difference 'Version.count' do
-      post :create, :project_id => '1', :version => {:name => 'test_add_version'}
-    end
-    assert_redirected_to '/projects/ecookbook/settings/versions'
-    version = Version.find_by_name('test_add_version')
-    assert_not_nil version
-    assert_equal 1, version.project_id
-  end
-
-  def test_create_from_issue_form
-    @request.session[:user_id] = 2
-    assert_difference 'Version.count' do
-      xhr :post, :create, :project_id => '1', :version => {:name => 'test_add_version_from_issue_form'}
-    end
-    version = Version.find_by_name('test_add_version_from_issue_form')
-    assert_not_nil version
-    assert_equal 1, version.project_id
-
-    assert_response :success
-    assert_template 'create'
-    assert_equal 'text/javascript', response.content_type
-    assert_include 'test_add_version_from_issue_form', response.body
-  end
-
-  def test_create_from_issue_form_with_failure
-    @request.session[:user_id] = 2
-    assert_no_difference 'Version.count' do
-      xhr :post, :create, :project_id => '1', :version => {:name => ''}
-    end
-    assert_response :success
-    assert_template 'new'
-    assert_equal 'text/javascript', response.content_type
-  end
-
-  def test_get_edit
-    @request.session[:user_id] = 2
-    get :edit, :id => 2
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_close_completed
-    Version.update_all("status = 'open'")
-    @request.session[:user_id] = 2
-    put :close_completed, :project_id => 'ecookbook'
-    assert_redirected_to :controller => 'projects', :action => 'settings',
-                         :tab => 'versions', :id => 'ecookbook'
-    assert_not_nil Version.find_by_status('closed')
-  end
-
-  def test_post_update
-    @request.session[:user_id] = 2
-    put :update, :id => 2,
-                :version => {:name => 'New version name',
-                             :effective_date => Date.today.strftime("%Y-%m-%d")}
-    assert_redirected_to :controller => 'projects', :action => 'settings',
-                         :tab => 'versions', :id => 'ecookbook'
-    version = Version.find(2)
-    assert_equal 'New version name', version.name
-    assert_equal Date.today, version.effective_date
-  end
-
-  def test_post_update_with_validation_failure
-    @request.session[:user_id] = 2
-    put :update, :id => 2,
-                 :version => { :name => '',
-                               :effective_date => Date.today.strftime("%Y-%m-%d")}
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_destroy
-    @request.session[:user_id] = 2
-    assert_difference 'Version.count', -1 do
-      delete :destroy, :id => 3
-    end
-    assert_redirected_to :controller => 'projects', :action => 'settings',
-                         :tab => 'versions', :id => 'ecookbook'
-    assert_nil Version.find_by_id(3)
-  end
-
-  def test_destroy_version_in_use_should_fail
-    @request.session[:user_id] = 2
-    assert_no_difference 'Version.count' do
-      delete :destroy, :id => 2
-    end
-    assert_redirected_to :controller => 'projects', :action => 'settings',
-                         :tab => 'versions', :id => 'ecookbook'
-    assert flash[:error].match(/Unable to delete version/)
-    assert Version.find_by_id(2)
-  end
-
-  def test_issue_status_by
-    xhr :get, :status_by, :id => 2
-    assert_response :success
-    assert_template 'status_by'
-    assert_template '_issue_counts'
-  end
-
-  def test_issue_status_by_status
-    xhr :get, :status_by, :id => 2, :status_by => 'status'
-    assert_response :success
-    assert_template 'status_by'
-    assert_template '_issue_counts'
-    assert_include 'Assigned', response.body
-    assert_include 'Closed', response.body
-  end
-end
--- a/.svn/pristine/76/760034b00a77f0a73cc21094aabb292a6e6e29ae.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,869 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class MailHandlerTest < ActiveSupport::TestCase
-  fixtures :users, :projects, :enabled_modules, :roles,
-           :members, :member_roles, :users,
-           :issues, :issue_statuses,
-           :workflows, :trackers, :projects_trackers,
-           :versions, :enumerations, :issue_categories,
-           :custom_fields, :custom_fields_trackers, :custom_fields_projects,
-           :boards, :messages
-
-  FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
-
-  def setup
-    ActionMailer::Base.deliveries.clear
-    Setting.notified_events = Redmine::Notifiable.all.collect(&:name)
-  end
-
-  def teardown
-    Setting.clear_cache
-  end
-
-  def test_add_issue
-    ActionMailer::Base.deliveries.clear
-    # This email contains: 'Project: onlinestore'
-    issue = submit_email('ticket_on_given_project.eml')
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal Project.find(2), issue.project
-    assert_equal issue.project.trackers.first, issue.tracker
-    assert_equal 'New ticket on a given project', issue.subject
-    assert_equal User.find_by_login('jsmith'), issue.author
-    assert_equal IssueStatus.find_by_name('Resolved'), issue.status
-    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
-    assert_equal '2010-01-01', issue.start_date.to_s
-    assert_equal '2010-12-31', issue.due_date.to_s
-    assert_equal User.find_by_login('jsmith'), issue.assigned_to
-    assert_equal Version.find_by_name('Alpha'), issue.fixed_version
-    assert_equal 2.5, issue.estimated_hours
-    assert_equal 30, issue.done_ratio
-    assert_equal [issue.id, 1, 2], [issue.root_id, issue.lft, issue.rgt]
-    # keywords should be removed from the email body
-    assert !issue.description.match(/^Project:/i)
-    assert !issue.description.match(/^Status:/i)
-    assert !issue.description.match(/^Start Date:/i)
-    # Email notification should be sent
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert mail.subject.include?('New ticket on a given project')
-  end
-
-  def test_add_issue_with_default_tracker
-    # This email contains: 'Project: onlinestore'
-    issue = submit_email(
-              'ticket_on_given_project.eml',
-              :issue => {:tracker => 'Support request'}
-            )
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal 'Support request', issue.tracker.name
-  end
-
-  def test_add_issue_with_status
-    # This email contains: 'Project: onlinestore' and 'Status: Resolved'
-    issue = submit_email('ticket_on_given_project.eml')
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal Project.find(2), issue.project
-    assert_equal IssueStatus.find_by_name("Resolved"), issue.status
-  end
-
-  def test_add_issue_with_attributes_override
-    issue = submit_email(
-              'ticket_with_attributes.eml',
-              :allow_override => 'tracker,category,priority'
-            )
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal 'New ticket on a given project', issue.subject
-    assert_equal User.find_by_login('jsmith'), issue.author
-    assert_equal Project.find(2), issue.project
-    assert_equal 'Feature request', issue.tracker.to_s
-    assert_equal 'Stock management', issue.category.to_s
-    assert_equal 'Urgent', issue.priority.to_s
-    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
-  end
-
-  def test_add_issue_with_group_assignment
-    with_settings :issue_group_assignment => '1' do
-      issue = submit_email('ticket_on_given_project.eml') do |email|
-        email.gsub!('Assigned to: John Smith', 'Assigned to: B Team')
-      end
-      assert issue.is_a?(Issue)
-      assert !issue.new_record?
-      issue.reload
-      assert_equal Group.find(11), issue.assigned_to
-    end
-  end
-
-  def test_add_issue_with_partial_attributes_override
-    issue = submit_email(
-              'ticket_with_attributes.eml',
-              :issue => {:priority => 'High'},
-              :allow_override => ['tracker']
-            )
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal 'New ticket on a given project', issue.subject
-    assert_equal User.find_by_login('jsmith'), issue.author
-    assert_equal Project.find(2), issue.project
-    assert_equal 'Feature request', issue.tracker.to_s
-    assert_nil issue.category
-    assert_equal 'High', issue.priority.to_s
-    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
-  end
-
-  def test_add_issue_with_spaces_between_attribute_and_separator
-    issue = submit_email(
-              'ticket_with_spaces_between_attribute_and_separator.eml',
-              :allow_override => 'tracker,category,priority'
-            )
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal 'New ticket on a given project', issue.subject
-    assert_equal User.find_by_login('jsmith'), issue.author
-    assert_equal Project.find(2), issue.project
-    assert_equal 'Feature request', issue.tracker.to_s
-    assert_equal 'Stock management', issue.category.to_s
-    assert_equal 'Urgent', issue.priority.to_s
-    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
-  end
-
-  def test_add_issue_with_attachment_to_specific_project
-    issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal 'Ticket created by email with attachment', issue.subject
-    assert_equal User.find_by_login('jsmith'), issue.author
-    assert_equal Project.find(2), issue.project
-    assert_equal 'This is  a new ticket with attachments', issue.description
-    # Attachment properties
-    assert_equal 1, issue.attachments.size
-    assert_equal 'Paella.jpg', issue.attachments.first.filename
-    assert_equal 'image/jpeg', issue.attachments.first.content_type
-    assert_equal 10790, issue.attachments.first.filesize
-  end
-
-  def test_add_issue_with_custom_fields
-    issue = submit_email('ticket_with_custom_fields.eml', :issue => {:project => 'onlinestore'})
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal 'New ticket with custom field values', issue.subject
-    assert_equal 'PostgreSQL', issue.custom_field_value(1)
-    assert_equal 'Value for a custom field', issue.custom_field_value(2)
-    assert !issue.description.match(/^searchable field:/i)
-  end
-
-  def test_add_issue_with_version_custom_fields
-    field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3])
-
-    issue = submit_email('ticket_with_custom_fields.eml', :issue => {:project => 'ecookbook'}) do |email|
-      email << "Affected version: 1.0\n"
-    end
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal '2', issue.custom_field_value(field)
-  end
-
-  def test_add_issue_should_match_assignee_on_display_name
-    user = User.generate!(:firstname => 'Foo Bar', :lastname => 'Foo Baz')
-    User.add_to_project(user, Project.find(2))
-    issue = submit_email('ticket_on_given_project.eml') do |email|
-      email.sub!(/^Assigned to.*$/, 'Assigned to: Foo Bar Foo baz')
-    end
-    assert issue.is_a?(Issue)
-    assert_equal user, issue.assigned_to
-  end
-
-  def test_add_issue_with_cc
-    issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
-    assert_equal 1, issue.watcher_user_ids.size
-  end
-
-  def test_add_issue_by_unknown_user
-    assert_no_difference 'User.count' do
-      assert_equal false,
-                   submit_email(
-                     'ticket_by_unknown_user.eml',
-                     :issue => {:project => 'ecookbook'}
-                   )
-    end
-  end
-
-  def test_add_issue_by_anonymous_user
-    Role.anonymous.add_permission!(:add_issues)
-    assert_no_difference 'User.count' do
-      issue = submit_email(
-                'ticket_by_unknown_user.eml',
-                :issue => {:project => 'ecookbook'},
-                :unknown_user => 'accept'
-              )
-      assert issue.is_a?(Issue)
-      assert issue.author.anonymous?
-    end
-  end
-
-  def test_add_issue_by_anonymous_user_with_no_from_address
-    Role.anonymous.add_permission!(:add_issues)
-    assert_no_difference 'User.count' do
-      issue = submit_email(
-                'ticket_by_empty_user.eml',
-                :issue => {:project => 'ecookbook'},
-                :unknown_user => 'accept'
-              )
-      assert issue.is_a?(Issue)
-      assert issue.author.anonymous?
-    end
-  end
-
-  def test_add_issue_by_anonymous_user_on_private_project
-    Role.anonymous.add_permission!(:add_issues)
-    assert_no_difference 'User.count' do
-      assert_no_difference 'Issue.count' do
-        assert_equal false,
-                     submit_email(
-                       'ticket_by_unknown_user.eml',
-                       :issue => {:project => 'onlinestore'},
-                       :unknown_user => 'accept'
-                     )
-      end
-    end
-  end
-
-  def test_add_issue_by_anonymous_user_on_private_project_without_permission_check
-    assert_no_difference 'User.count' do
-      assert_difference 'Issue.count' do
-        issue = submit_email(
-                  'ticket_by_unknown_user.eml',
-                  :issue => {:project => 'onlinestore'},
-                  :no_permission_check => '1',
-                  :unknown_user => 'accept'
-                )
-        assert issue.is_a?(Issue)
-        assert issue.author.anonymous?
-        assert !issue.project.is_public?
-        assert_equal [issue.id, 1, 2], [issue.root_id, issue.lft, issue.rgt]
-      end
-    end
-  end
-
-  def test_add_issue_by_created_user
-    Setting.default_language = 'en'
-    assert_difference 'User.count' do
-      issue = submit_email(
-                'ticket_by_unknown_user.eml',
-                :issue => {:project => 'ecookbook'},
-                :unknown_user => 'create'
-              )
-      assert issue.is_a?(Issue)
-      assert issue.author.active?
-      assert_equal 'john.doe@somenet.foo', issue.author.mail
-      assert_equal 'John', issue.author.firstname
-      assert_equal 'Doe', issue.author.lastname
-
-      # account information
-      email = ActionMailer::Base.deliveries.first
-      assert_not_nil email
-      assert email.subject.include?('account activation')
-      login = mail_body(email).match(/\* Login: (.*)$/)[1].strip
-      password = mail_body(email).match(/\* Password: (.*)$/)[1].strip
-      assert_equal issue.author, User.try_to_login(login, password)
-    end
-  end
-
-  def test_created_user_should_be_added_to_groups
-    group1 = Group.generate!
-    group2 = Group.generate!
-
-    assert_difference 'User.count' do
-      submit_email(
-        'ticket_by_unknown_user.eml',
-        :issue => {:project => 'ecookbook'},
-        :unknown_user => 'create',
-        :default_group => "#{group1.name},#{group2.name}"
-      )
-    end
-    user = User.order('id DESC').first
-    assert_same_elements [group1, group2], user.groups
-  end
-
-  def test_created_user_should_not_receive_account_information_with_no_account_info_option
-    assert_difference 'User.count' do
-      submit_email(
-        'ticket_by_unknown_user.eml',
-        :issue => {:project => 'ecookbook'},
-        :unknown_user => 'create',
-        :no_account_notice => '1'
-      )
-    end
-
-    # only 1 email for the new issue notification
-    assert_equal 1, ActionMailer::Base.deliveries.size
-    email = ActionMailer::Base.deliveries.first
-    assert_include 'Ticket by unknown user', email.subject
-  end
-
-  def test_created_user_should_have_mail_notification_to_none_with_no_notification_option
-    assert_difference 'User.count' do
-      submit_email(
-        'ticket_by_unknown_user.eml',
-        :issue => {:project => 'ecookbook'},
-        :unknown_user => 'create',
-        :no_notification => '1'
-      )
-    end
-    user = User.order('id DESC').first
-    assert_equal 'none', user.mail_notification
-  end
-
-  def test_add_issue_without_from_header
-    Role.anonymous.add_permission!(:add_issues)
-    assert_equal false, submit_email('ticket_without_from_header.eml')
-  end
-
-  def test_add_issue_with_invalid_attributes
-    issue = submit_email(
-              'ticket_with_invalid_attributes.eml',
-              :allow_override => 'tracker,category,priority'
-            )
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_nil issue.assigned_to
-    assert_nil issue.start_date
-    assert_nil issue.due_date
-    assert_equal 0, issue.done_ratio
-    assert_equal 'Normal', issue.priority.to_s
-    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
-  end
-
-  def test_add_issue_with_invalid_project_should_be_assigned_to_default_project
-    issue = submit_email('ticket_on_given_project.eml', :issue => {:project => 'ecookbook'}, :allow_override => 'project') do |email|
-      email.gsub!(/^Project:.+$/, 'Project: invalid')
-    end
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    assert_equal 'ecookbook', issue.project.identifier
-  end
-
-  def test_add_issue_with_localized_attributes
-    User.find_by_mail('jsmith@somenet.foo').update_attribute 'language', 'fr'
-    issue = submit_email(
-              'ticket_with_localized_attributes.eml',
-              :allow_override => 'tracker,category,priority'
-            )
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal 'New ticket on a given project', issue.subject
-    assert_equal User.find_by_login('jsmith'), issue.author
-    assert_equal Project.find(2), issue.project
-    assert_equal 'Feature request', issue.tracker.to_s
-    assert_equal 'Stock management', issue.category.to_s
-    assert_equal 'Urgent', issue.priority.to_s
-    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
-  end
-
-  def test_add_issue_with_japanese_keywords
-    ja_dev = "\xe9\x96\x8b\xe7\x99\xba"
-    ja_dev.force_encoding('UTF-8') if ja_dev.respond_to?(:force_encoding)
-    tracker = Tracker.create!(:name => ja_dev)
-    Project.find(1).trackers << tracker
-    issue = submit_email(
-              'japanese_keywords_iso_2022_jp.eml',
-              :issue => {:project => 'ecookbook'},
-              :allow_override => 'tracker'
-            )
-    assert_kind_of Issue, issue
-    assert_equal tracker, issue.tracker
-  end
-
-  def test_add_issue_from_apple_mail
-    issue = submit_email(
-              'apple_mail_with_attachment.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-    assert_kind_of Issue, issue
-    assert_equal 1, issue.attachments.size
-
-    attachment = issue.attachments.first
-    assert_equal 'paella.jpg', attachment.filename
-    assert_equal 10790, attachment.filesize
-    assert File.exist?(attachment.diskfile)
-    assert_equal 10790, File.size(attachment.diskfile)
-    assert_equal 'caaf384198bcbc9563ab5c058acd73cd', attachment.digest
-  end
-
-  def test_thunderbird_with_attachment_ja
-    issue = submit_email(
-              'thunderbird_with_attachment_ja.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-    assert_kind_of Issue, issue
-    assert_equal 1, issue.attachments.size
-    ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
-    attachment = issue.attachments.first
-    assert_equal ja, attachment.filename
-    assert_equal 5, attachment.filesize
-    assert File.exist?(attachment.diskfile)
-    assert_equal 5, File.size(attachment.diskfile)
-    assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
-  end
-
-  def test_gmail_with_attachment_ja
-    issue = submit_email(
-              'gmail_with_attachment_ja.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-    assert_kind_of Issue, issue
-    assert_equal 1, issue.attachments.size
-    ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
-    attachment = issue.attachments.first
-    assert_equal ja, attachment.filename
-    assert_equal 5, attachment.filesize
-    assert File.exist?(attachment.diskfile)
-    assert_equal 5, File.size(attachment.diskfile)
-    assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
-  end
-
-  def test_thunderbird_with_attachment_latin1
-    issue = submit_email(
-              'thunderbird_with_attachment_iso-8859-1.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-    assert_kind_of Issue, issue
-    assert_equal 1, issue.attachments.size
-    u = ""
-    u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
-    u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
-    u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
-    11.times { u << u1 }
-    attachment = issue.attachments.first
-    assert_equal "#{u}.png", attachment.filename
-    assert_equal 130, attachment.filesize
-    assert File.exist?(attachment.diskfile)
-    assert_equal 130, File.size(attachment.diskfile)
-    assert_equal '4d80e667ac37dddfe05502530f152abb', attachment.digest
-  end
-
-  def test_gmail_with_attachment_latin1
-    issue = submit_email(
-              'gmail_with_attachment_iso-8859-1.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-    assert_kind_of Issue, issue
-    assert_equal 1, issue.attachments.size
-    u = ""
-    u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
-    u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
-    u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
-    11.times { u << u1 }
-    attachment = issue.attachments.first
-    assert_equal "#{u}.txt", attachment.filename
-    assert_equal 5, attachment.filesize
-    assert File.exist?(attachment.diskfile)
-    assert_equal 5, File.size(attachment.diskfile)
-    assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
-  end
-
-  def test_multiple_inline_text_parts_should_be_appended_to_issue_description
-    issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
-    assert_include 'first', issue.description
-    assert_include 'second', issue.description
-    assert_include 'third', issue.description
-  end
-
-  def test_attachment_text_part_should_be_added_as_issue_attachment
-    issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
-    assert_not_include 'Plain text attachment', issue.description
-    attachment = issue.attachments.detect {|a| a.filename == 'textfile.txt'}
-    assert_not_nil attachment
-    assert_include 'Plain text attachment', File.read(attachment.diskfile)
-  end
-
-  def test_add_issue_with_iso_8859_1_subject
-    issue = submit_email(
-              'subject_as_iso-8859-1.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-    str = "Testmail from Webmail: \xc3\xa4 \xc3\xb6 \xc3\xbc..."
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    assert_kind_of Issue, issue
-    assert_equal str, issue.subject
-  end
-
-  def test_add_issue_with_japanese_subject
-    issue = submit_email(
-              'subject_japanese_1.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-    assert_kind_of Issue, issue
-    ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
-    assert_equal ja, issue.subject
-  end
-
-  def test_add_issue_with_no_subject_header
-    issue = submit_email(
-              'no_subject_header.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-    assert_kind_of Issue, issue
-    assert_equal '(no subject)', issue.subject
-  end
-
-  def test_add_issue_with_mixed_japanese_subject
-    issue = submit_email(
-              'subject_japanese_2.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-    assert_kind_of Issue, issue
-    ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
-    assert_equal ja, issue.subject
-  end
-
-  def test_should_ignore_emails_from_locked_users
-    User.find(2).lock!
-
-    MailHandler.any_instance.expects(:dispatch).never
-    assert_no_difference 'Issue.count' do
-      assert_equal false, submit_email('ticket_on_given_project.eml')
-    end
-  end
-
-  def test_should_ignore_emails_from_emission_address
-    Role.anonymous.add_permission!(:add_issues)
-    assert_no_difference 'User.count' do
-      assert_equal false,
-                   submit_email(
-                     'ticket_from_emission_address.eml',
-                     :issue => {:project => 'ecookbook'},
-                     :unknown_user => 'create'
-                   )
-    end
-  end
-
-  def test_should_ignore_auto_replied_emails
-    MailHandler.any_instance.expects(:dispatch).never
-    [
-      "X-Auto-Response-Suppress: OOF",
-      "Auto-Submitted: auto-replied",
-      "Auto-Submitted: Auto-Replied",
-      "Auto-Submitted: auto-generated"
-    ].each do |header|
-      raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
-      raw = header + "\n" + raw
-
-      assert_no_difference 'Issue.count' do
-        assert_equal false, MailHandler.receive(raw), "email with #{header} header was not ignored"
-      end
-    end
-  end
-
-  def test_add_issue_should_send_email_notification
-    Setting.notified_events = ['issue_added']
-    ActionMailer::Base.deliveries.clear
-    # This email contains: 'Project: onlinestore'
-    issue = submit_email('ticket_on_given_project.eml')
-    assert issue.is_a?(Issue)
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_update_issue
-    journal = submit_email('ticket_reply.eml')
-    assert journal.is_a?(Journal)
-    assert_equal User.find_by_login('jsmith'), journal.user
-    assert_equal Issue.find(2), journal.journalized
-    assert_match /This is reply/, journal.notes
-    assert_equal false, journal.private_notes
-    assert_equal 'Feature request', journal.issue.tracker.name
-  end
-
-  def test_update_issue_with_attribute_changes
-    # This email contains: 'Status: Resolved'
-    journal = submit_email('ticket_reply_with_status.eml')
-    assert journal.is_a?(Journal)
-    issue = Issue.find(journal.issue.id)
-    assert_equal User.find_by_login('jsmith'), journal.user
-    assert_equal Issue.find(2), journal.journalized
-    assert_match /This is reply/, journal.notes
-    assert_equal 'Feature request', journal.issue.tracker.name
-    assert_equal IssueStatus.find_by_name("Resolved"), issue.status
-    assert_equal '2010-01-01', issue.start_date.to_s
-    assert_equal '2010-12-31', issue.due_date.to_s
-    assert_equal User.find_by_login('jsmith'), issue.assigned_to
-    assert_equal "52.6", issue.custom_value_for(CustomField.find_by_name('Float field')).value
-    # keywords should be removed from the email body
-    assert !journal.notes.match(/^Status:/i)
-    assert !journal.notes.match(/^Start Date:/i)
-  end
-
-  def test_update_issue_with_attachment
-    assert_difference 'Journal.count' do
-      assert_difference 'JournalDetail.count' do
-        assert_difference 'Attachment.count' do
-          assert_no_difference 'Issue.count' do
-            journal = submit_email('ticket_with_attachment.eml') do |raw|
-              raw.gsub! /^Subject: .*$/, 'Subject: Re: [Cookbook - Feature #2] (New) Add ingredients categories'
-            end
-          end
-        end
-      end
-    end
-    journal = Journal.first(:order => 'id DESC')
-    assert_equal Issue.find(2), journal.journalized
-    assert_equal 1, journal.details.size
-
-    detail = journal.details.first
-    assert_equal 'attachment', detail.property
-    assert_equal 'Paella.jpg', detail.value
-  end
-
-  def test_update_issue_should_send_email_notification
-    ActionMailer::Base.deliveries.clear
-    journal = submit_email('ticket_reply.eml')
-    assert journal.is_a?(Journal)
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_update_issue_should_not_set_defaults
-    journal = submit_email(
-                'ticket_reply.eml',
-                :issue => {:tracker => 'Support request', :priority => 'High'}
-              )
-    assert journal.is_a?(Journal)
-    assert_match /This is reply/, journal.notes
-    assert_equal 'Feature request', journal.issue.tracker.name
-    assert_equal 'Normal', journal.issue.priority.name
-  end
-
-  def test_replying_to_a_private_note_should_add_reply_as_private
-    private_journal = Journal.create!(:notes => 'Private notes', :journalized => Issue.find(1), :private_notes => true, :user_id => 2)
-
-    assert_difference 'Journal.count' do
-      journal = submit_email('ticket_reply.eml') do |email|
-        email.sub! %r{^In-Reply-To:.*$}, "In-Reply-To: <redmine.journal-#{private_journal.id}.20060719210421@osiris>"
-      end
-
-      assert_kind_of Journal, journal
-      assert_match /This is reply/, journal.notes
-      assert_equal true, journal.private_notes
-    end
-  end
-
-  def test_reply_to_a_message
-    m = submit_email('message_reply.eml')
-    assert m.is_a?(Message)
-    assert !m.new_record?
-    m.reload
-    assert_equal 'Reply via email', m.subject
-    # The email replies to message #2 which is part of the thread of message #1
-    assert_equal Message.find(1), m.parent
-  end
-
-  def test_reply_to_a_message_by_subject
-    m = submit_email('message_reply_by_subject.eml')
-    assert m.is_a?(Message)
-    assert !m.new_record?
-    m.reload
-    assert_equal 'Reply to the first post', m.subject
-    assert_equal Message.find(1), m.parent
-  end
-
-  def test_should_strip_tags_of_html_only_emails
-    issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'})
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-    assert_equal 'HTML email', issue.subject
-    assert_equal 'This is a html-only email.', issue.description
-  end
-
-  test "truncate emails with no setting should add the entire email into the issue" do
-    with_settings :mail_handler_body_delimiters => '' do
-      issue = submit_email('ticket_on_given_project.eml')
-      assert_issue_created(issue)
-      assert issue.description.include?('---')
-      assert issue.description.include?('This paragraph is after the delimiter')
-    end
-  end
-
-  test "truncate emails with a single string should truncate the email at the delimiter for the issue" do
-    with_settings :mail_handler_body_delimiters => '---' do
-      issue = submit_email('ticket_on_given_project.eml')
-      assert_issue_created(issue)
-      assert issue.description.include?('This paragraph is before delimiters')
-      assert issue.description.include?('--- This line starts with a delimiter')
-      assert !issue.description.match(/^---$/)
-      assert !issue.description.include?('This paragraph is after the delimiter')
-    end
-  end
-
-  test "truncate emails with a single quoted reply should truncate the email at the delimiter with the quoted reply symbols (>)" do
-    with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
-      journal = submit_email('issue_update_with_quoted_reply_above.eml')
-      assert journal.is_a?(Journal)
-      assert journal.notes.include?('An update to the issue by the sender.')
-      assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
-      assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
-    end
-  end
-
-  test "truncate emails with multiple quoted replies should truncate the email at the delimiter with the quoted reply symbols (>)" do
-    with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
-      journal = submit_email('issue_update_with_multiple_quoted_reply_above.eml')
-      assert journal.is_a?(Journal)
-      assert journal.notes.include?('An update to the issue by the sender.')
-      assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
-      assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
-    end
-  end
-
-  test "truncate emails with multiple strings should truncate the email at the first delimiter found (BREAK)" do
-    with_settings :mail_handler_body_delimiters => "---\nBREAK" do
-      issue = submit_email('ticket_on_given_project.eml')
-      assert_issue_created(issue)
-      assert issue.description.include?('This paragraph is before delimiters')
-      assert !issue.description.include?('BREAK')
-      assert !issue.description.include?('This paragraph is between delimiters')
-      assert !issue.description.match(/^---$/)
-      assert !issue.description.include?('This paragraph is after the delimiter')
-    end
-  end
-
-  def test_attachments_that_match_mail_handler_excluded_filenames_should_be_ignored
-    with_settings :mail_handler_excluded_filenames => '*.vcf, *.jpg' do
-      issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
-      assert issue.is_a?(Issue)
-      assert !issue.new_record?
-      assert_equal 0, issue.reload.attachments.size
-    end
-  end
-
-  def test_attachments_that_do_not_match_mail_handler_excluded_filenames_should_be_attached
-    with_settings :mail_handler_excluded_filenames => '*.vcf, *.gif' do
-      issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
-      assert issue.is_a?(Issue)
-      assert !issue.new_record?
-      assert_equal 1, issue.reload.attachments.size
-    end
-  end
-
-  def test_email_with_long_subject_line
-    issue = submit_email('ticket_with_long_subject.eml')
-    assert issue.is_a?(Issue)
-    assert_equal issue.subject, 'New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say...'[0,255]
-  end
-
-  def test_new_user_from_attributes_should_return_valid_user
-    to_test = {
-      # [address, name] => [login, firstname, lastname]
-      ['jsmith@example.net', nil] => ['jsmith@example.net', 'jsmith', '-'],
-      ['jsmith@example.net', 'John'] => ['jsmith@example.net', 'John', '-'],
-      ['jsmith@example.net', 'John Smith'] => ['jsmith@example.net', 'John', 'Smith'],
-      ['jsmith@example.net', 'John Paul Smith'] => ['jsmith@example.net', 'John', 'Paul Smith'],
-      ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsTheMaximumLength Smith'] => ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsT', 'Smith'],
-      ['jsmith@example.net', 'John AVeryLongLastnameThatExceedsTheMaximumLength'] => ['jsmith@example.net', 'John', 'AVeryLongLastnameThatExceedsTh']
-    }
-
-    to_test.each do |attrs, expected|
-      user = MailHandler.new_user_from_attributes(attrs.first, attrs.last)
-
-      assert user.valid?, user.errors.full_messages.to_s
-      assert_equal attrs.first, user.mail
-      assert_equal expected[0], user.login
-      assert_equal expected[1], user.firstname
-      assert_equal expected[2], user.lastname
-      assert_equal 'only_my_events', user.mail_notification
-    end
-  end
-
-  def test_new_user_from_attributes_should_use_default_login_if_invalid
-    user = MailHandler.new_user_from_attributes('foo+bar@example.net')
-    assert user.valid?
-    assert user.login =~ /^user[a-f0-9]+$/
-    assert_equal 'foo+bar@example.net', user.mail
-  end
-
-  def test_new_user_with_utf8_encoded_fullname_should_be_decoded
-    assert_difference 'User.count' do
-      issue = submit_email(
-                'fullname_of_sender_as_utf8_encoded.eml',
-                :issue => {:project => 'ecookbook'},
-                :unknown_user => 'create'
-              )
-    end
-
-    user = User.first(:order => 'id DESC')
-    assert_equal "foo@example.org", user.mail
-    str1 = "\xc3\x84\xc3\xa4"
-    str2 = "\xc3\x96\xc3\xb6"
-    str1.force_encoding('UTF-8') if str1.respond_to?(:force_encoding)
-    str2.force_encoding('UTF-8') if str2.respond_to?(:force_encoding)
-    assert_equal str1, user.firstname
-    assert_equal str2, user.lastname
-  end
-
-  def test_extract_options_from_env_should_return_options
-    options = MailHandler.extract_options_from_env({
-      'tracker' => 'defect',
-      'project' => 'foo',
-      'unknown_user' => 'create'
-    })
-
-    assert_equal({
-      :issue => {:tracker => 'defect', :project => 'foo'},
-      :unknown_user => 'create'
-    }, options)
-  end
-
-  private
-
-  def submit_email(filename, options={})
-    raw = IO.read(File.join(FIXTURES_PATH, filename))
-    yield raw if block_given?
-    MailHandler.receive(raw, options)
-  end
-
-  def assert_issue_created(issue)
-    assert issue.is_a?(Issue)
-    assert !issue.new_record?
-    issue.reload
-  end
-end
--- a/.svn/pristine/76/7613b919071a0b15c5315d48513bd037d7d92c4b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Helpers
-
-    # Simple class to compute the start and end dates of a calendar
-    class Calendar
-      include Redmine::I18n
-      attr_reader :startdt, :enddt
-
-      def initialize(date, lang = current_language, period = :month)
-        @date = date
-        @events = []
-        @ending_events_by_days = {}
-        @starting_events_by_days = {}
-        set_language_if_valid lang
-        case period
-        when :month
-          @startdt = Date.civil(date.year, date.month, 1)
-          @enddt = (@startdt >> 1)-1
-          # starts from the first day of the week
-          @startdt = @startdt - (@startdt.cwday - first_wday)%7
-          # ends on the last day of the week
-          @enddt = @enddt + (last_wday - @enddt.cwday)%7
-        when :week
-          @startdt = date - (date.cwday - first_wday)%7
-          @enddt = date + (last_wday - date.cwday)%7
-        else
-          raise 'Invalid period'
-        end
-      end
-
-      # Sets calendar events
-      def events=(events)
-        @events = events
-        @ending_events_by_days = @events.group_by {|event| event.due_date}
-        @starting_events_by_days = @events.group_by {|event| event.start_date}
-      end
-
-      # Returns events for the given day
-      def events_on(day)
-        ((@ending_events_by_days[day] || []) + (@starting_events_by_days[day] || [])).uniq
-      end
-
-      # Calendar current month
-      def month
-        @date.month
-      end
-
-      # Return the first day of week
-      # 1 = Monday ... 7 = Sunday
-      def first_wday
-        case Setting.start_of_week.to_i
-        when 1
-          @first_dow ||= (1 - 1)%7 + 1
-        when 6
-          @first_dow ||= (6 - 1)%7 + 1
-        when 7
-          @first_dow ||= (7 - 1)%7 + 1
-        else
-          @first_dow ||= (l(:general_first_day_of_week).to_i - 1)%7 + 1
-        end
-      end
-
-      def last_wday
-        @last_dow ||= (first_wday + 5)%7 + 1
-      end
-    end
-  end
-end
--- a/.svn/pristine/76/76c6293fe37375af70e9b0a4cdcbec2106159b62.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,607 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ProjectsControllerTest < ActionController::TestCase
-  fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
-           :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
-           :attachments, :custom_fields, :custom_values, :time_entries
-
-  def setup
-    @request.session[:user_id] = nil
-    Setting.default_language = 'en'
-  end
-
-  def test_index_by_anonymous_should_not_show_private_projects
-    get :index
-    assert_response :success
-    assert_template 'index'
-    projects = assigns(:projects)
-    assert_not_nil projects
-    assert projects.all?(&:is_public?)
-
-    assert_select 'ul' do
-      assert_select 'li' do
-        assert_select 'a', :text => 'eCookbook'
-        assert_select 'ul' do
-          assert_select 'a', :text => 'Child of private child'
-        end
-      end
-    end
-    assert_select 'a', :text => /Private child of eCookbook/, :count => 0
-  end
-
-  def test_index_atom
-    get :index, :format => 'atom'
-    assert_response :success
-    assert_template 'common/feed'
-    assert_select 'feed>title', :text => 'Redmine: Latest projects'
-    assert_select 'feed>entry', :count => Project.visible(User.current).count
-  end
-
-  test "#index by non-admin user with view_time_entries permission should show overall spent time link" do
-    @request.session[:user_id] = 3
-    get :index
-    assert_template 'index'
-    assert_select 'a[href=?]', '/time_entries'
-  end
-
-  test "#index by non-admin user without view_time_entries permission should not show overall spent time link" do
-    Role.find(2).remove_permission! :view_time_entries
-    Role.non_member.remove_permission! :view_time_entries
-    Role.anonymous.remove_permission! :view_time_entries
-    @request.session[:user_id] = 3
-
-    get :index
-    assert_template 'index'
-    assert_select 'a[href=?]', '/time_entries', 0
-  end
-
-  test "#new by admin user should accept get" do
-    @request.session[:user_id] = 1
-
-    get :new
-    assert_response :success
-    assert_template 'new'
-  end
-
-  test "#new by non-admin user with add_project permission should accept get" do
-    Role.non_member.add_permission! :add_project
-    @request.session[:user_id] = 9
-
-    get :new
-    assert_response :success
-    assert_template 'new'
-    assert_select 'select[name=?]', 'project[parent_id]', 0
-  end
-
-  test "#new by non-admin user with add_subprojects permission should accept get" do
-    Role.find(1).remove_permission! :add_project
-    Role.find(1).add_permission! :add_subprojects
-    @request.session[:user_id] = 2
-
-    get :new, :parent_id => 'ecookbook'
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'select[name=?]', 'project[parent_id]' do
-      # parent project selected
-      assert_select 'option[value=1][selected=selected]'
-      # no empty value
-      assert_select 'option[value=]', 0
-    end
-  end
-
-  test "#create by admin user should create a new project" do
-    @request.session[:user_id] = 1
-
-    post :create,
-      :project => {
-        :name => "blog",
-        :description => "weblog",
-        :homepage => 'http://weblog',
-        :identifier => "blog",
-        :is_public => 1,
-        :custom_field_values => { '3' => 'Beta' },
-        :tracker_ids => ['1', '3'],
-        # an issue custom field that is not for all project
-        :issue_custom_field_ids => ['9'],
-        :enabled_module_names => ['issue_tracking', 'news', 'repository']
-      }
-    assert_redirected_to '/projects/blog/settings'
-
-    project = Project.find_by_name('blog')
-    assert_kind_of Project, project
-    assert project.active?
-    assert_equal 'weblog', project.description
-    assert_equal 'http://weblog', project.homepage
-    assert_equal true, project.is_public?
-    assert_nil project.parent
-    assert_equal 'Beta', project.custom_value_for(3).value
-    assert_equal [1, 3], project.trackers.map(&:id).sort
-    assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
-    assert project.issue_custom_fields.include?(IssueCustomField.find(9))
-  end
-
-  test "#create by admin user should create a new subproject" do
-    @request.session[:user_id] = 1
-
-    assert_difference 'Project.count' do
-      post :create, :project => { :name => "blog",
-                               :description => "weblog",
-                               :identifier => "blog",
-                               :is_public => 1,
-                               :custom_field_values => { '3' => 'Beta' },
-                               :parent_id => 1
-                              }
-      assert_redirected_to '/projects/blog/settings'
-    end
-
-    project = Project.find_by_name('blog')
-    assert_kind_of Project, project
-    assert_equal Project.find(1), project.parent
-  end
-
-  test "#create by admin user should continue" do
-    @request.session[:user_id] = 1
-
-    assert_difference 'Project.count' do
-      post :create, :project => {:name => "blog", :identifier => "blog"}, :continue => 'Create and continue'
-    end
-    assert_redirected_to '/projects/new'
-  end
-
-  test "#create by non-admin user with add_project permission should create a new project" do
-    Role.non_member.add_permission! :add_project
-    @request.session[:user_id] = 9
-
-    post :create, :project => { :name => "blog",
-                             :description => "weblog",
-                             :identifier => "blog",
-                             :is_public => 1,
-                             :custom_field_values => { '3' => 'Beta' },
-                             :tracker_ids => ['1', '3'],
-                             :enabled_module_names => ['issue_tracking', 'news', 'repository']
-                            }
-
-    assert_redirected_to '/projects/blog/settings'
-
-    project = Project.find_by_name('blog')
-    assert_kind_of Project, project
-    assert_equal 'weblog', project.description
-    assert_equal true, project.is_public?
-    assert_equal [1, 3], project.trackers.map(&:id).sort
-    assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
-
-    # User should be added as a project member
-    assert User.find(9).member_of?(project)
-    assert_equal 1, project.members.size
-  end
-
-  test "#create by non-admin user with add_project permission should fail with parent_id" do
-    Role.non_member.add_permission! :add_project
-    @request.session[:user_id] = 9
-
-    assert_no_difference 'Project.count' do
-      post :create, :project => { :name => "blog",
-                               :description => "weblog",
-                               :identifier => "blog",
-                               :is_public => 1,
-                               :custom_field_values => { '3' => 'Beta' },
-                               :parent_id => 1
-                              }
-    end
-    assert_response :success
-    project = assigns(:project)
-    assert_kind_of Project, project
-    assert_not_equal [], project.errors[:parent_id]
-  end
-
-  test "#create by non-admin user with add_subprojects permission should create a project with a parent_id" do
-    Role.find(1).remove_permission! :add_project
-    Role.find(1).add_permission! :add_subprojects
-    @request.session[:user_id] = 2
-
-    post :create, :project => { :name => "blog",
-                             :description => "weblog",
-                             :identifier => "blog",
-                             :is_public => 1,
-                             :custom_field_values => { '3' => 'Beta' },
-                             :parent_id => 1
-                            }
-    assert_redirected_to '/projects/blog/settings'
-    project = Project.find_by_name('blog')
-  end
-
-  test "#create by non-admin user with add_subprojects permission should fail without parent_id" do
-    Role.find(1).remove_permission! :add_project
-    Role.find(1).add_permission! :add_subprojects
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Project.count' do
-      post :create, :project => { :name => "blog",
-                               :description => "weblog",
-                               :identifier => "blog",
-                               :is_public => 1,
-                               :custom_field_values => { '3' => 'Beta' }
-                              }
-    end
-    assert_response :success
-    project = assigns(:project)
-    assert_kind_of Project, project
-    assert_not_equal [], project.errors[:parent_id]
-  end
-
-  test "#create by non-admin user with add_subprojects permission should fail with unauthorized parent_id" do
-    Role.find(1).remove_permission! :add_project
-    Role.find(1).add_permission! :add_subprojects
-    @request.session[:user_id] = 2
-
-    assert !User.find(2).member_of?(Project.find(6))
-    assert_no_difference 'Project.count' do
-      post :create, :project => { :name => "blog",
-                               :description => "weblog",
-                               :identifier => "blog",
-                               :is_public => 1,
-                               :custom_field_values => { '3' => 'Beta' },
-                               :parent_id => 6
-                              }
-    end
-    assert_response :success
-    project = assigns(:project)
-    assert_kind_of Project, project
-    assert_not_equal [], project.errors[:parent_id]
-  end
-
-  def test_create_subproject_with_inherit_members_should_inherit_members
-    Role.find_by_name('Manager').add_permission! :add_subprojects
-    parent = Project.find(1)
-    @request.session[:user_id] = 2
-
-    assert_difference 'Project.count' do
-      post :create, :project => {
-        :name => 'inherited', :identifier => 'inherited', :parent_id => parent.id, :inherit_members => '1'
-      }
-      assert_response 302
-    end
-
-    project = Project.order('id desc').first
-    assert_equal 'inherited', project.name
-    assert_equal parent, project.parent
-    assert project.memberships.count > 0
-    assert_equal parent.memberships.count, project.memberships.count
-  end
-
-  def test_create_should_preserve_modules_on_validation_failure
-    with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
-      @request.session[:user_id] = 1
-      assert_no_difference 'Project.count' do
-        post :create, :project => {
-          :name => "blog",
-          :identifier => "",
-          :enabled_module_names => %w(issue_tracking news)
-        }
-      end
-      assert_response :success
-      project = assigns(:project)
-      assert_equal %w(issue_tracking news), project.enabled_module_names.sort
-    end
-  end
-
-  def test_show_by_id
-    get :show, :id => 1
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:project)
-  end
-
-  def test_show_by_identifier
-    get :show, :id => 'ecookbook'
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:project)
-    assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
-
-    assert_select 'li', :text => /Development status/
-  end
-
-  def test_show_should_not_display_empty_sidebar
-    p = Project.find(1)
-    p.enabled_module_names = []
-    p.save!
-
-    get :show, :id => 'ecookbook'
-    assert_response :success
-    assert_select '#main.nosidebar'
-  end
-
-  def test_show_should_not_display_hidden_custom_fields
-    ProjectCustomField.find_by_name('Development status').update_attribute :visible, false
-    get :show, :id => 'ecookbook'
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:project)
-
-    assert_select 'li', :text => /Development status/, :count => 0
-  end
-
-  def test_show_should_not_fail_when_custom_values_are_nil
-    project = Project.find_by_identifier('ecookbook')
-    project.custom_values.first.update_attribute(:value, nil)
-    get :show, :id => 'ecookbook'
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:project)
-    assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
-  end
-
-  def show_archived_project_should_be_denied
-    project = Project.find_by_identifier('ecookbook')
-    project.archive!
-
-    get :show, :id => 'ecookbook'
-    assert_response 403
-    assert_nil assigns(:project)
-    assert_select 'p', :text => /archived/
-  end
-
-  def test_show_should_not_show_private_subprojects_that_are_not_visible
-    get :show, :id => 'ecookbook'
-    assert_response :success
-    assert_template 'show'
-    assert_select 'a', :text => /Private child/, :count => 0
-  end
-
-  def test_show_should_show_private_subprojects_that_are_visible
-    @request.session[:user_id] = 2 # manager who is a member of the private subproject
-    get :show, :id => 'ecookbook'
-    assert_response :success
-    assert_template 'show'
-    assert_select 'a', :text => /Private child/
-  end
-
-  def test_settings
-    @request.session[:user_id] = 2 # manager
-    get :settings, :id => 1
-    assert_response :success
-    assert_template 'settings'
-  end
-
-  def test_settings_of_subproject
-    @request.session[:user_id] = 2
-    get :settings, :id => 'private-child'
-    assert_response :success
-    assert_template 'settings'
-
-    assert_select 'input[type=checkbox][name=?]', 'project[inherit_members]'
-  end
-
-  def test_settings_should_be_denied_for_member_on_closed_project
-    Project.find(1).close
-    @request.session[:user_id] = 2 # manager
-
-    get :settings, :id => 1
-    assert_response 403
-  end
-
-  def test_settings_should_be_denied_for_anonymous_on_closed_project
-    Project.find(1).close
-
-    get :settings, :id => 1
-    assert_response 302
-  end
-
-  def test_update
-    @request.session[:user_id] = 2 # manager
-    post :update, :id => 1, :project => {:name => 'Test changed name',
-                                       :issue_custom_field_ids => ['']}
-    assert_redirected_to '/projects/ecookbook/settings'
-    project = Project.find(1)
-    assert_equal 'Test changed name', project.name
-  end
-
-  def test_update_with_failure
-    @request.session[:user_id] = 2 # manager
-    post :update, :id => 1, :project => {:name => ''}
-    assert_response :success
-    assert_template 'settings'
-    assert_error_tag :content => /name can&#x27;t be blank/i
-  end
-
-  def test_update_should_be_denied_for_member_on_closed_project
-    Project.find(1).close
-    @request.session[:user_id] = 2 # manager
-
-    post :update, :id => 1, :project => {:name => 'Closed'}
-    assert_response 403
-    assert_equal 'eCookbook', Project.find(1).name
-  end
-
-  def test_update_should_be_denied_for_anonymous_on_closed_project
-    Project.find(1).close
-
-    post :update, :id => 1, :project => {:name => 'Closed'}
-    assert_response 302
-    assert_equal 'eCookbook', Project.find(1).name
-  end
-
-  def test_modules
-    @request.session[:user_id] = 2
-    Project.find(1).enabled_module_names = ['issue_tracking', 'news']
-
-    post :modules, :id => 1, :enabled_module_names => ['issue_tracking', 'repository', 'documents']
-    assert_redirected_to '/projects/ecookbook/settings/modules'
-    assert_equal ['documents', 'issue_tracking', 'repository'], Project.find(1).enabled_module_names.sort
-  end
-
-  def test_destroy_leaf_project_without_confirmation_should_show_confirmation
-    @request.session[:user_id] = 1 # admin
-
-    assert_no_difference 'Project.count' do
-      delete :destroy, :id => 2
-      assert_response :success
-      assert_template 'destroy'
-    end
-  end
-
-  def test_destroy_without_confirmation_should_show_confirmation_with_subprojects
-    @request.session[:user_id] = 1 # admin
-
-    assert_no_difference 'Project.count' do
-      delete :destroy, :id => 1
-      assert_response :success
-      assert_template 'destroy'
-    end
-    assert_select 'strong',
-                  :text => ['Private child of eCookbook',
-                            'Child of private child, eCookbook Subproject 1',
-                            'eCookbook Subproject 2'].join(', ')
-  end
-
-  def test_destroy_with_confirmation_should_destroy_the_project_and_subprojects
-    @request.session[:user_id] = 1 # admin
-
-    assert_difference 'Project.count', -5 do
-      delete :destroy, :id => 1, :confirm => 1
-      assert_redirected_to '/admin/projects'
-    end
-    assert_nil Project.find_by_id(1)
-  end
-
-  def test_archive
-    @request.session[:user_id] = 1 # admin
-    post :archive, :id => 1
-    assert_redirected_to '/admin/projects'
-    assert !Project.find(1).active?
-  end
-
-  def test_archive_with_failure
-    @request.session[:user_id] = 1
-    Project.any_instance.stubs(:archive).returns(false)
-    post :archive, :id => 1
-    assert_redirected_to '/admin/projects'
-    assert_match /project cannot be archived/i, flash[:error]
-  end
-
-  def test_unarchive
-    @request.session[:user_id] = 1 # admin
-    Project.find(1).archive
-    post :unarchive, :id => 1
-    assert_redirected_to '/admin/projects'
-    assert Project.find(1).active?
-  end
-
-  def test_close
-    @request.session[:user_id] = 2
-    post :close, :id => 1
-    assert_redirected_to '/projects/ecookbook'
-    assert_equal Project::STATUS_CLOSED, Project.find(1).status
-  end
-
-  def test_reopen
-    Project.find(1).close
-    @request.session[:user_id] = 2
-    post :reopen, :id => 1
-    assert_redirected_to '/projects/ecookbook'
-    assert Project.find(1).active?
-  end
-
-  def test_project_breadcrumbs_should_be_limited_to_3_ancestors
-    CustomField.delete_all
-    parent = nil
-    6.times do |i|
-      p = Project.generate_with_parent!(parent)
-      get :show, :id => p
-      assert_select '#header h1' do
-        assert_select 'a', :count => [i, 3].min
-      end
-
-      parent = p
-    end
-  end
-
-  def test_get_copy
-    @request.session[:user_id] = 1 # admin
-    get :copy, :id => 1
-    assert_response :success
-    assert_template 'copy'
-    assert assigns(:project)
-    assert_equal Project.find(1).description, assigns(:project).description
-    assert_nil assigns(:project).id
-
-    assert_select 'input[name=?][value=?]', 'project[enabled_module_names][]', 'issue_tracking', 1
-  end
-
-  def test_get_copy_with_invalid_source_should_respond_with_404
-    @request.session[:user_id] = 1
-    get :copy, :id => 99
-    assert_response 404
-  end
-
-  def test_post_copy_should_copy_requested_items
-    @request.session[:user_id] = 1 # admin
-    CustomField.delete_all
-
-    assert_difference 'Project.count' do
-      post :copy, :id => 1,
-        :project => {
-          :name => 'Copy',
-          :identifier => 'unique-copy',
-          :tracker_ids => ['1', '2', '3', ''],
-          :enabled_module_names => %w(issue_tracking time_tracking)
-        },
-        :only => %w(issues versions)
-    end
-    project = Project.find('unique-copy')
-    source = Project.find(1)
-    assert_equal %w(issue_tracking time_tracking), project.enabled_module_names.sort
-
-    assert_equal source.versions.count, project.versions.count, "All versions were not copied"
-    assert_equal source.issues.count, project.issues.count, "All issues were not copied"
-    assert_equal 0, project.members.count
-  end
-
-  def test_post_copy_should_redirect_to_settings_when_successful
-    @request.session[:user_id] = 1 # admin
-    post :copy, :id => 1, :project => {:name => 'Copy', :identifier => 'unique-copy'}
-    assert_response :redirect
-    assert_redirected_to :controller => 'projects', :action => 'settings', :id => 'unique-copy'
-  end
-
-  def test_jump_should_redirect_to_active_tab
-    get :show, :id => 1, :jump => 'issues'
-    assert_redirected_to '/projects/ecookbook/issues'
-  end
-
-  def test_jump_should_not_redirect_to_inactive_tab
-    get :show, :id => 3, :jump => 'documents'
-    assert_response :success
-    assert_template 'show'
-  end
-
-  def test_jump_should_not_redirect_to_unknown_tab
-    get :show, :id => 3, :jump => 'foobar'
-    assert_response :success
-    assert_template 'show'
-  end
-
-  def test_body_should_have_project_css_class
-    get :show, :id => 1
-    assert_select 'body.project-ecookbook'
-  end
-end
--- a/.svn/pristine/76/76f5b1657c4e0eb2717b1dfffe6b49bb8cd094b8.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class VersionCustomField < CustomField
-  def type_name
-    :label_version_plural
-  end
-end
--- a/.svn/pristine/77/771517d2f5d100730b0ffcf7efa80c42ba739a96.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AccountControllerTest < ActionController::TestCase
-  fixtures :users, :roles
-
-  def setup
-    User.current = nil
-  end
-
-  def test_get_login
-    get :login
-    assert_response :success
-    assert_template 'login'
-
-    assert_select 'input[name=username]'
-    assert_select 'input[name=password]'
-  end
-
-  def test_get_login_while_logged_in_should_redirect_to_home
-    @request.session[:user_id] = 2
-
-    get :login
-    assert_redirected_to '/'
-    assert_equal 2, @request.session[:user_id]
-  end
-
-  def test_login_should_redirect_to_back_url_param
-    # request.uri is "test.host" in test environment
-    post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http://test.host/issues/show/1'
-    assert_redirected_to '/issues/show/1'
-  end
-
-  def test_login_should_not_redirect_to_another_host
-    post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http://test.foo/fake'
-    assert_redirected_to '/my/page'
-  end
-
-  def test_login_with_wrong_password
-    post :login, :username => 'admin', :password => 'bad'
-    assert_response :success
-    assert_template 'login'
-
-    assert_select 'div.flash.error', :text => /Invalid user or password/
-    assert_select 'input[name=username][value=admin]'
-    assert_select 'input[name=password]'
-    assert_select 'input[name=password][value]', 0
-  end
-
-  def test_login_with_locked_account_should_fail
-    User.find(2).update_attribute :status, User::STATUS_LOCKED
-
-    post :login, :username => 'jsmith', :password => 'jsmith'
-    assert_redirected_to '/login'
-    assert_include 'locked', flash[:error]
-    assert_nil @request.session[:user_id]
-  end
-
-  def test_login_as_registered_user_with_manual_activation_should_inform_user
-    User.find(2).update_attribute :status, User::STATUS_REGISTERED
-
-    with_settings :self_registration => '2', :default_language => 'en' do
-      post :login, :username => 'jsmith', :password => 'jsmith'
-      assert_redirected_to '/login'
-      assert_include 'pending administrator approval', flash[:error]
-    end
-  end
-
-  def test_login_as_registered_user_with_email_activation_should_propose_new_activation_email
-    User.find(2).update_attribute :status, User::STATUS_REGISTERED
-
-    with_settings :self_registration => '1', :default_language => 'en' do
-      post :login, :username => 'jsmith', :password => 'jsmith'
-      assert_redirected_to '/login'
-      assert_equal 2, @request.session[:registered_user_id]
-      assert_include 'new activation email', flash[:error]
-    end
-  end
-
-  def test_login_should_rescue_auth_source_exception
-    source = AuthSource.create!(:name => 'Test')
-    User.find(2).update_attribute :auth_source_id, source.id
-    AuthSource.any_instance.stubs(:authenticate).raises(AuthSourceException.new("Something wrong"))
-
-    post :login, :username => 'jsmith', :password => 'jsmith'
-    assert_response 500
-    assert_error_tag :content => /Something wrong/
-  end
-
-  def test_login_should_reset_session
-    @controller.expects(:reset_session).once
-
-    post :login, :username => 'jsmith', :password => 'jsmith'
-    assert_response 302
-  end
-
-  def test_get_logout_should_not_logout
-    @request.session[:user_id] = 2
-    get :logout
-    assert_response :success
-    assert_template 'logout'
-
-    assert_equal 2, @request.session[:user_id]
-  end
-
-  def test_get_logout_with_anonymous_should_redirect
-    get :logout
-    assert_redirected_to '/'
-  end
-
-  def test_logout
-    @request.session[:user_id] = 2
-    post :logout
-    assert_redirected_to '/'
-    assert_nil @request.session[:user_id]
-  end
-
-  def test_logout_should_reset_session
-    @controller.expects(:reset_session).once
-
-    @request.session[:user_id] = 2
-    post :logout
-    assert_response 302
-  end
-
-  def test_get_register_with_registration_on
-    with_settings :self_registration => '3' do
-      get :register
-      assert_response :success
-      assert_template 'register'
-      assert_not_nil assigns(:user)
-
-      assert_select 'input[name=?]', 'user[password]'
-      assert_select 'input[name=?]', 'user[password_confirmation]'
-    end
-  end
-
-  def test_get_register_should_detect_user_language
-    with_settings :self_registration => '3' do
-      @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
-      get :register
-      assert_response :success
-      assert_not_nil assigns(:user)
-      assert_equal 'fr', assigns(:user).language
-      assert_select 'select[name=?]', 'user[language]' do
-        assert_select 'option[value=fr][selected=selected]'
-      end
-    end
-  end
-
-  def test_get_register_with_registration_off_should_redirect
-    with_settings :self_registration => '0' do
-      get :register
-      assert_redirected_to '/'
-    end
-  end
-
-  # See integration/account_test.rb for the full test
-  def test_post_register_with_registration_on
-    with_settings :self_registration => '3' do
-      assert_difference 'User.count' do
-        post :register, :user => {
-          :login => 'register',
-          :password => 'secret123',
-          :password_confirmation => 'secret123',
-          :firstname => 'John',
-          :lastname => 'Doe',
-          :mail => 'register@example.com'
-        }
-        assert_redirected_to '/my/account'
-      end
-      user = User.first(:order => 'id DESC')
-      assert_equal 'register', user.login
-      assert_equal 'John', user.firstname
-      assert_equal 'Doe', user.lastname
-      assert_equal 'register@example.com', user.mail
-      assert user.check_password?('secret123')
-      assert user.active?
-    end
-  end
-  
-  def test_post_register_with_registration_off_should_redirect
-    with_settings :self_registration => '0' do
-      assert_no_difference 'User.count' do
-        post :register, :user => {
-          :login => 'register',
-          :password => 'test',
-          :password_confirmation => 'test',
-          :firstname => 'John',
-          :lastname => 'Doe',
-          :mail => 'register@example.com'
-        }
-        assert_redirected_to '/'
-      end
-    end
-  end
-
-  def test_get_lost_password_should_display_lost_password_form
-    get :lost_password
-    assert_response :success
-    assert_select 'input[name=mail]'
-  end
-
-  def test_lost_password_for_active_user_should_create_a_token
-    Token.delete_all
-    ActionMailer::Base.deliveries.clear
-    assert_difference 'ActionMailer::Base.deliveries.size' do
-      assert_difference 'Token.count' do
-        with_settings :host_name => 'mydomain.foo', :protocol => 'http' do
-          post :lost_password, :mail => 'JSmith@somenet.foo'
-          assert_redirected_to '/login'
-        end
-      end
-    end
-
-    token = Token.order('id DESC').first
-    assert_equal User.find(2), token.user
-    assert_equal 'recovery', token.action
-
-    assert_select_email do
-      assert_select "a[href=?]", "http://mydomain.foo/account/lost_password?token=#{token.value}"
-    end
-  end
-
-  def test_lost_password_for_unknown_user_should_fail
-    Token.delete_all
-    assert_no_difference 'Token.count' do
-      post :lost_password, :mail => 'invalid@somenet.foo'
-      assert_response :success
-    end
-  end
-
-  def test_lost_password_for_non_active_user_should_fail
-    Token.delete_all
-    assert User.find(2).lock!
-
-    assert_no_difference 'Token.count' do
-      post :lost_password, :mail => 'JSmith@somenet.foo'
-      assert_redirected_to '/account/lost_password'
-    end
-  end
-
-  def test_lost_password_for_user_who_cannot_change_password_should_fail
-    User.any_instance.stubs(:change_password_allowed?).returns(false)
-
-    assert_no_difference 'Token.count' do
-      post :lost_password, :mail => 'JSmith@somenet.foo'
-      assert_response :success
-    end
-  end
-
-  def test_get_lost_password_with_token_should_display_the_password_recovery_form
-    user = User.find(2)
-    token = Token.create!(:action => 'recovery', :user => user)
-
-    get :lost_password, :token => token.value
-    assert_response :success
-    assert_template 'password_recovery'
-
-    assert_select 'input[type=hidden][name=token][value=?]', token.value
-  end
-
-  def test_get_lost_password_with_invalid_token_should_redirect
-    get :lost_password, :token => "abcdef"
-    assert_redirected_to '/'
-  end
-
-  def test_post_lost_password_with_token_should_change_the_user_password
-    user = User.find(2)
-    token = Token.create!(:action => 'recovery', :user => user)
-
-    post :lost_password, :token => token.value, :new_password => 'newpass123', :new_password_confirmation => 'newpass123'
-    assert_redirected_to '/login'
-    user.reload
-    assert user.check_password?('newpass123')
-    assert_nil Token.find_by_id(token.id), "Token was not deleted"
-  end
-
-  def test_post_lost_password_with_token_for_non_active_user_should_fail
-    user = User.find(2)
-    token = Token.create!(:action => 'recovery', :user => user)
-    user.lock!
-
-    post :lost_password, :token => token.value, :new_password => 'newpass123', :new_password_confirmation => 'newpass123'
-    assert_redirected_to '/'
-    assert ! user.check_password?('newpass123')
-  end
-
-  def test_post_lost_password_with_token_and_password_confirmation_failure_should_redisplay_the_form
-    user = User.find(2)
-    token = Token.create!(:action => 'recovery', :user => user)
-
-    post :lost_password, :token => token.value, :new_password => 'newpass', :new_password_confirmation => 'wrongpass'
-    assert_response :success
-    assert_template 'password_recovery'
-    assert_not_nil Token.find_by_id(token.id), "Token was deleted"
-
-    assert_select 'input[type=hidden][name=token][value=?]', token.value
-  end
-
-  def test_post_lost_password_with_invalid_token_should_redirect
-    post :lost_password, :token => "abcdef", :new_password => 'newpass', :new_password_confirmation => 'newpass'
-    assert_redirected_to '/'
-  end
-
-  def test_activation_email_should_send_an_activation_email
-    User.find(2).update_attribute :status, User::STATUS_REGISTERED
-    @request.session[:registered_user_id] = 2
-
-    with_settings :self_registration => '1' do
-      assert_difference 'ActionMailer::Base.deliveries.size' do
-        get :activation_email
-        assert_redirected_to '/login'
-      end
-    end
-  end
-
-  def test_activation_email_without_session_data_should_fail
-    User.find(2).update_attribute :status, User::STATUS_REGISTERED
-
-    with_settings :self_registration => '1' do
-      assert_no_difference 'ActionMailer::Base.deliveries.size' do
-        get :activation_email
-        assert_redirected_to '/'
-      end
-    end
-  end
-end
--- a/.svn/pristine/77/7727bb04d0abb3e8e4031848fb82a82cb998f0af.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Acts
-    module Attachable
-      def self.included(base)
-        base.extend ClassMethods
-      end
-
-      module ClassMethods
-        def acts_as_attachable(options = {})
-          cattr_accessor :attachable_options
-          self.attachable_options = {}
-          attachable_options[:view_permission] = options.delete(:view_permission) || "view_#{self.name.pluralize.underscore}".to_sym
-          attachable_options[:delete_permission] = options.delete(:delete_permission) || "edit_#{self.name.pluralize.underscore}".to_sym
-
-          has_many :attachments, options.merge(:as => :container,
-                                               :order => "#{Attachment.table_name}.created_on ASC, #{Attachment.table_name}.id ASC",
-                                               :dependent => :destroy)
-          send :include, Redmine::Acts::Attachable::InstanceMethods
-          before_save :attach_saved_attachments
-        end
-      end
-
-      module InstanceMethods
-        def self.included(base)
-          base.extend ClassMethods
-        end
-
-        def attachments_visible?(user=User.current)
-          (respond_to?(:visible?) ? visible?(user) : true) &&
-            user.allowed_to?(self.class.attachable_options[:view_permission], self.project)
-        end
-
-        def attachments_deletable?(user=User.current)
-          (respond_to?(:visible?) ? visible?(user) : true) &&
-            user.allowed_to?(self.class.attachable_options[:delete_permission], self.project)
-        end
-
-        def saved_attachments
-          @saved_attachments ||= []
-        end
-
-        def unsaved_attachments
-          @unsaved_attachments ||= []
-        end
-
-        def save_attachments(attachments, author=User.current)
-          if attachments.is_a?(Hash)
-            attachments = attachments.stringify_keys
-            attachments = attachments.to_a.sort {|a, b|
-              if a.first.to_i > 0 && b.first.to_i > 0
-                a.first.to_i <=> b.first.to_i
-              elsif a.first.to_i > 0
-                1
-              elsif b.first.to_i > 0
-                -1
-              else
-                a.first <=> b.first
-              end
-            }
-            attachments = attachments.map(&:last)
-          end
-          if attachments.is_a?(Array)
-            attachments.each do |attachment|
-              next unless attachment.is_a?(Hash)
-              a = nil
-              if file = attachment['file']
-                next unless file.size > 0
-                a = Attachment.create(:file => file, :author => author)
-              elsif token = attachment['token']
-                a = Attachment.find_by_token(token)
-                next unless a
-                a.filename = attachment['filename'] unless attachment['filename'].blank?
-                a.content_type = attachment['content_type']
-              end
-              next unless a
-              a.description = attachment['description'].to_s.strip
-              if a.new_record?
-                unsaved_attachments << a
-              else
-                saved_attachments << a
-              end
-            end
-          end
-          {:files => saved_attachments, :unsaved => unsaved_attachments}
-        end
-
-        def attach_saved_attachments
-          saved_attachments.each do |attachment|
-            self.attachments << attachment
-          end
-        end
-
-        module ClassMethods
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/77/77b5f4fec79f0d6eb61a76e965e02cb7504641fe.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoryBazaarTest < ActiveSupport::TestCase
-  fixtures :projects
-
-  include Redmine::I18n
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
-  REPOSITORY_PATH_TRUNK = File.join(REPOSITORY_PATH, "trunk")
-  NUM_REV = 4
-
-  REPOSITORY_PATH_NON_ASCII = Rails.root.join(REPOSITORY_PATH + '/' + 'non_ascii').to_s
-
-  # Bazaar core does not support xml output such as Subversion and Mercurial.
-  # "bzr" command output and command line parameter depend on locale.
-  # So, non ASCII path tests cannot run independent locale.
-  #
-  # If you want to run Bazaar non ASCII path tests on Linux *Ruby 1.9*,
-  # you need to set locale character set "ISO-8859-1".
-  # E.g. "LANG=en_US.ISO-8859-1".
-  # On Linux other platforms (e.g. Ruby 1.8, JRuby),
-  # you need to set "RUN_LATIN1_OUTPUT_TEST = true" manually.
-  #
-  # On Windows, because it is too hard to change system locale,
-  # you cannot run Bazaar non ASCII path tests.
-  #
-  RUN_LATIN1_OUTPUT_TEST = (RUBY_PLATFORM != 'java' &&
-                             REPOSITORY_PATH.respond_to?(:force_encoding) &&
-                             Encoding.locale_charmap == "ISO-8859-1")
-
-  CHAR_1_UTF8_HEX   = "\xc3\x9c"
-  CHAR_1_LATIN1_HEX = "\xdc"
-
-  def setup
-    @project = Project.find(3)
-    @repository = Repository::Bazaar.create(
-              :project => @project, :url => REPOSITORY_PATH_TRUNK,
-              :log_encoding => 'UTF-8')
-    assert @repository
-    @char_1_utf8      = CHAR_1_UTF8_HEX.dup
-    @char_1_ascii8bit = CHAR_1_LATIN1_HEX.dup
-    if @char_1_utf8.respond_to?(:force_encoding)
-      @char_1_utf8.force_encoding('UTF-8')
-      @char_1_ascii8bit.force_encoding('ASCII-8BIT')
-    end
-  end
-
-  def test_blank_path_to_repository_error_message
-    set_language_if_valid 'en'
-    repo = Repository::Bazaar.new(
-                          :project      => @project,
-                          :identifier   => 'test',
-                          :log_encoding => 'UTF-8'
-                        )
-    assert !repo.save
-    assert_include "Path to repository can't be blank",
-                   repo.errors.full_messages
-  end
-
-  def test_blank_path_to_repository_error_message_fr
-    set_language_if_valid 'fr'
-    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    repo = Repository::Bazaar.new(
-                          :project      => @project,
-                          :url          => "",
-                          :identifier   => 'test',
-                          :log_encoding => 'UTF-8'
-                        )
-    assert !repo.save
-    assert_include str, repo.errors.full_messages
-  end
-
-  if File.directory?(REPOSITORY_PATH_TRUNK)
-    def test_fetch_changesets_from_scratch
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_equal 9, @repository.filechanges.count
-      assert_equal 'Initial import', @repository.changesets.find_by_revision('1').comments
-    end
-
-    def test_fetch_changesets_incremental
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      # Remove changesets with revision > 5
-      @repository.changesets.all.each {|c| c.destroy if c.revision.to_i > 2}
-      @project.reload
-      assert_equal 2, @repository.changesets.count
-
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-    end
-
-    def test_entries
-      entries = @repository.entries
-      assert_kind_of Redmine::Scm::Adapters::Entries, entries
-      assert_equal 2, entries.size
-
-      assert_equal 'dir', entries[0].kind
-      assert_equal 'directory', entries[0].name
-      assert_equal 'directory', entries[0].path
-
-      assert_equal 'file', entries[1].kind
-      assert_equal 'doc-mkdir.txt', entries[1].name
-      assert_equal 'doc-mkdir.txt', entries[1].path
-    end
-
-    def test_entries_in_subdirectory
-      entries = @repository.entries('directory')
-      assert_equal 3, entries.size
-
-      assert_equal 'file', entries.last.kind
-      assert_equal 'edit.png', entries.last.name
-      assert_equal 'directory/edit.png', entries.last.path
-    end
-
-    def test_previous
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      changeset = @repository.find_changeset_by_name('3')
-      assert_equal @repository.find_changeset_by_name('2'), changeset.previous
-    end
-
-    def test_previous_nil
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      changeset = @repository.find_changeset_by_name('1')
-      assert_nil changeset.previous
-    end
-
-    def test_next
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      changeset = @repository.find_changeset_by_name('2')
-      assert_equal @repository.find_changeset_by_name('3'), changeset.next
-    end
-
-    def test_next_nil
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      changeset = @repository.find_changeset_by_name('4')
-      assert_nil changeset.next
-    end
-
-    if File.directory?(REPOSITORY_PATH_NON_ASCII) && RUN_LATIN1_OUTPUT_TEST
-      def test_cat_latin1_path
-        latin1_repo = create_latin1_repo
-        buf = latin1_repo.cat(
-                 "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-2.txt", 2)
-        assert buf
-        lines = buf.split("\n")
-        assert_equal 2, lines.length
-        assert_equal 'It is written in Python.', lines[1]
-
-        buf = latin1_repo.cat(
-                 "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", 2)
-        assert buf
-        lines = buf.split("\n")
-        assert_equal 1, lines.length
-        assert_equal "test-#{@char_1_ascii8bit}.txt", lines[0]
-      end
-
-      def test_annotate_latin1_path
-        latin1_repo = create_latin1_repo
-        ann1 = latin1_repo.annotate(
-                   "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-2.txt", 2)
-        assert_equal 2, ann1.lines.size
-        assert_equal '2', ann1.revisions[0].identifier
-        assert_equal 'test00@', ann1.revisions[0].author
-        assert_equal 'It is written in Python.', ann1.lines[1]
-        ann2 = latin1_repo.annotate(
-                   "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", 2)
-        assert_equal 1, ann2.lines.size
-        assert_equal '2', ann2.revisions[0].identifier
-        assert_equal 'test00@', ann2.revisions[0].author
-        assert_equal "test-#{@char_1_ascii8bit}.txt", ann2.lines[0]
-      end
-
-      def test_diff_latin1_path
-        latin1_repo = create_latin1_repo
-        diff1 = latin1_repo.diff(
-                  "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", 2, 1)
-        assert_equal 7, diff1.size
-        buf =  diff1[5].gsub(/\r\n|\r|\n/, "")
-        assert_equal "+test-#{@char_1_ascii8bit}.txt", buf
-      end
-
-      def test_entries_latin1_path
-        latin1_repo = create_latin1_repo
-        entries = latin1_repo.entries("test-#{@char_1_utf8}-dir", 2)
-        assert_kind_of Redmine::Scm::Adapters::Entries, entries
-        assert_equal 3, entries.size
-        assert_equal 'file', entries[1].kind
-        assert_equal "test-#{@char_1_utf8}-1.txt", entries[0].name
-        assert_equal "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", entries[0].path
-      end
-
-      def test_entry_latin1_path
-        latin1_repo = create_latin1_repo
-        ["test-#{@char_1_utf8}-dir",
-          "/test-#{@char_1_utf8}-dir",
-          "/test-#{@char_1_utf8}-dir/"
-        ].each do |path|
-          entry = latin1_repo.entry(path, 2)
-          assert_equal "test-#{@char_1_utf8}-dir", entry.path
-          assert_equal "dir", entry.kind
-        end
-        ["test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt",
-          "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt"
-        ].each do |path|
-          entry = latin1_repo.entry(path, 2)
-          assert_equal "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt",
-                       entry.path
-          assert_equal "file", entry.kind
-        end
-      end
-
-      def test_changeset_latin1_path
-        latin1_repo = create_latin1_repo
-        assert_equal 0, latin1_repo.changesets.count
-        latin1_repo.fetch_changesets
-        @project.reload
-        assert_equal 3, latin1_repo.changesets.count
-
-        cs2 = latin1_repo.changesets.find_by_revision('2')
-        assert_not_nil cs2
-        assert_equal "test-#{@char_1_utf8}", cs2.comments
-        c2  = cs2.filechanges.sort_by(&:path)
-        assert_equal 4, c2.size
-        assert_equal 'A', c2[0].action
-        assert_equal "/test-#{@char_1_utf8}-dir/", c2[0].path
-        assert_equal 'A', c2[1].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", c2[1].path
-        assert_equal 'A', c2[2].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-2.txt", c2[2].path
-        assert_equal 'A', c2[3].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}.txt", c2[3].path
-
-        cs3 = latin1_repo.changesets.find_by_revision('3')
-        assert_not_nil cs3
-        assert_equal "modify, move and delete #{@char_1_utf8} files", cs3.comments
-        c3  = cs3.filechanges.sort_by(&:path)
-        assert_equal 3, c3.size
-        assert_equal 'M', c3[0].action
-        assert_equal "/test-#{@char_1_utf8}-1.txt", c3[0].path
-        assert_equal 'D', c3[1].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-2.txt", c3[1].path
-        assert_equal 'M', c3[2].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}.txt", c3[2].path
-      end
-    else
-      msg = "Bazaar non ASCII output test cannot run this environment." + "\n"
-      if msg.respond_to?(:force_encoding)
-        msg += "Encoding.locale_charmap: " + Encoding.locale_charmap + "\n"
-      end
-      puts msg
-    end
-
-    private
-
-    def create_latin1_repo
-      repo = Repository::Bazaar.create(
-                            :project      => @project,
-                            :identifier   => 'latin1',
-                            :url => REPOSITORY_PATH_NON_ASCII,
-                            :log_encoding => 'ISO-8859-1'
-                        )
-      assert repo
-      repo
-    end
-  else
-    puts "Bazaar test repository NOT FOUND. Skipping unit tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/78/78376d3215166c5e884949655b3cf6e5caa6e30e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ActivityTest < ActiveSupport::TestCase
-  fixtures :projects, :versions, :attachments, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
-           :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages, :time_entries,
-           :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
-
-  def setup
-    @project = Project.find(1)
-  end
-
-  def test_activity_without_subprojects
-    events = find_events(User.anonymous, :project => @project)
-    assert_not_nil events
-
-    assert events.include?(Issue.find(1))
-    assert !events.include?(Issue.find(4))
-    # subproject issue
-    assert !events.include?(Issue.find(5))
-  end
-
-  def test_activity_with_subprojects
-    events = find_events(User.anonymous, :project => @project, :with_subprojects => 1)
-    assert_not_nil events
-
-    assert events.include?(Issue.find(1))
-    # subproject issue
-    assert events.include?(Issue.find(5))
-  end
-
-  def test_global_activity_anonymous
-    events = find_events(User.anonymous)
-    assert_not_nil events
-
-    assert events.include?(Issue.find(1))
-    assert events.include?(Message.find(5))
-    # Issue of a private project
-    assert !events.include?(Issue.find(4))
-    # Private issue and comment
-    assert !events.include?(Issue.find(14))
-    assert !events.include?(Journal.find(5))
-  end
-
-  def test_global_activity_logged_user
-    events = find_events(User.find(2)) # manager
-    assert_not_nil events
-
-    assert events.include?(Issue.find(1))
-    # Issue of a private project the user belongs to
-    assert events.include?(Issue.find(4))
-  end
-
-  def test_user_activity
-    user = User.find(2)
-    events = Redmine::Activity::Fetcher.new(User.anonymous, :author => user).events(nil, nil, :limit => 10)
-
-    assert(events.size > 0)
-    assert(events.size <= 10)
-    assert_nil(events.detect {|e| e.event_author != user})
-  end
-
-  def test_files_activity
-    f = Redmine::Activity::Fetcher.new(User.anonymous, :project => Project.find(1))
-    f.scope = ['files']
-    events = f.events
-
-    assert_kind_of Array, events
-    assert events.include?(Attachment.find_by_container_type_and_container_id('Project', 1))
-    assert events.include?(Attachment.find_by_container_type_and_container_id('Version', 1))
-    assert_equal [Attachment], events.collect(&:class).uniq
-    assert_equal %w(Project Version), events.collect(&:container_type).uniq.sort
-  end
-
-  def test_event_group_for_issue
-    issue = Issue.find(1)
-    assert_equal issue, issue.event_group
-  end
-
-  def test_event_group_for_journal
-    issue = Issue.find(1)
-    journal = issue.journals.first
-    assert_equal issue, journal.event_group
-  end
-
-  def test_event_group_for_issue_time_entry
-    time = TimeEntry.where(:issue_id => 1).first
-    assert_equal time.issue, time.event_group
-  end
-
-  def test_event_group_for_project_time_entry
-    time = TimeEntry.where(:issue_id => nil).first
-    assert_equal time, time.event_group
-  end
-
-  def test_event_group_for_message
-    message = Message.find(1)
-    reply = message.children.first
-    assert_equal message, message.event_group
-    assert_equal message, reply.event_group
-  end
-
-  def test_event_group_for_wiki_content_version
-    content = WikiContent::Version.find(1)
-    assert_equal content.page, content.event_group
-  end
-
-  private
-
-  def find_events(user, options={})
-    Redmine::Activity::Fetcher.new(user, options).events(Date.today - 30, Date.today + 1)
-  end
-end
--- a/.svn/pristine/78/7884d1a52f46dcfb203fc57885fb084b78063ba1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,242 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/abstract_adapter'
-require 'rexml/document'
-
-module Redmine
-  module Scm
-    module Adapters
-      class DarcsAdapter < AbstractAdapter
-        # Darcs executable name
-        DARCS_BIN = Redmine::Configuration['scm_darcs_command'] || "darcs"
-
-        class << self
-          def client_command
-            @@bin    ||= DARCS_BIN
-          end
-
-          def sq_bin
-            @@sq_bin ||= shell_quote_command
-          end
-
-          def client_version
-            @@client_version ||= (darcs_binary_version || [])
-          end
-
-          def client_available
-            !client_version.empty?
-          end
-
-          def darcs_binary_version
-            darcsversion = darcs_binary_version_from_command_line.dup
-            if darcsversion.respond_to?(:force_encoding)
-              darcsversion.force_encoding('ASCII-8BIT')
-            end
-            if m = darcsversion.match(%r{\A(.*?)((\d+\.)+\d+)})
-              m[2].scan(%r{\d+}).collect(&:to_i)
-            end
-          end
-
-          def darcs_binary_version_from_command_line
-            shellout("#{sq_bin} --version") { |io| io.read }.to_s
-          end
-        end
-
-        def initialize(url, root_url=nil, login=nil, password=nil,
-                       path_encoding=nil)
-          @url = url
-          @root_url = url
-        end
-
-        def supports_cat?
-          # cat supported in darcs 2.0.0 and higher
-          self.class.client_version_above?([2, 0, 0])
-        end
-
-        # Get info about the darcs repository
-        def info
-          rev = revisions(nil,nil,nil,{:limit => 1})
-          rev ? Info.new({:root_url => @url, :lastrev => rev.last}) : nil
-        end
-
-        # Returns an Entries collection
-        # or nil if the given path doesn't exist in the repository
-        def entries(path=nil, identifier=nil, options={})
-          path_prefix = (path.blank? ? '' : "#{path}/")
-          if path.blank?
-            path = ( self.class.client_version_above?([2, 2, 0]) ? @url : '.' )
-          end
-          entries = Entries.new
-          cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --xml-output"
-          cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier
-          cmd << " #{shell_quote path}"
-          shellout(cmd) do |io|
-            begin
-              doc = REXML::Document.new(io)
-              if doc.root.name == 'directory'
-                doc.elements.each('directory/*') do |element|
-                  next unless ['file', 'directory'].include? element.name
-                  entries << entry_from_xml(element, path_prefix)
-                end
-              elsif doc.root.name == 'file'
-                entries << entry_from_xml(doc.root, path_prefix)
-              end
-            rescue
-            end
-          end
-          return nil if $? && $?.exitstatus != 0
-          entries.compact!
-          entries.sort_by_name
-        end
-
-        def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
-          path = '.' if path.blank?
-          revisions = Revisions.new
-          cmd = "#{self.class.sq_bin} changes --repodir #{shell_quote @url} --xml-output"
-          cmd << " --from-match #{shell_quote("hash #{identifier_from}")}" if identifier_from
-          cmd << " --last #{options[:limit].to_i}" if options[:limit]
-          shellout(cmd) do |io|
-            begin
-              doc = REXML::Document.new(io)
-              doc.elements.each("changelog/patch") do |patch|
-                message = patch.elements['name'].text
-                message << "\n" + patch.elements['comment'].text.gsub(/\*\*\*END OF DESCRIPTION\*\*\*.*\z/m, '') if patch.elements['comment']
-                revisions << Revision.new({:identifier => nil,
-                              :author => patch.attributes['author'],
-                              :scmid => patch.attributes['hash'],
-                              :time => Time.parse(patch.attributes['local_date']),
-                              :message => message,
-                              :paths => (options[:with_path] ? get_paths_for_patch(patch.attributes['hash']) : nil)
-                            })
-              end
-            rescue
-            end
-          end
-          return nil if $? && $?.exitstatus != 0
-          revisions
-        end
-
-        def diff(path, identifier_from, identifier_to=nil)
-          path = '*' if path.blank?
-          cmd = "#{self.class.sq_bin} diff --repodir #{shell_quote @url}"
-          if identifier_to.nil?
-            cmd << " --match #{shell_quote("hash #{identifier_from}")}"
-          else
-            cmd << " --to-match #{shell_quote("hash #{identifier_from}")}"
-            cmd << " --from-match #{shell_quote("hash #{identifier_to}")}"
-          end
-          cmd << " -u #{shell_quote path}"
-          diff = []
-          shellout(cmd) do |io|
-            io.each_line do |line|
-              diff << line
-            end
-          end
-          return nil if $? && $?.exitstatus != 0
-          diff
-        end
-
-        def cat(path, identifier=nil)
-          cmd = "#{self.class.sq_bin} show content --repodir #{shell_quote @url}"
-          cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier
-          cmd << " #{shell_quote path}"
-          cat = nil
-          shellout(cmd) do |io|
-            io.binmode
-            cat = io.read
-          end
-          return nil if $? && $?.exitstatus != 0
-          cat
-        end
-
-        private
-
-        # Returns an Entry from the given XML element
-        # or nil if the entry was deleted
-        def entry_from_xml(element, path_prefix)
-          modified_element = element.elements['modified']
-          if modified_element.elements['modified_how'].text.match(/removed/)
-            return nil
-          end
-
-          Entry.new({:name => element.attributes['name'],
-                     :path => path_prefix + element.attributes['name'],
-                     :kind => element.name == 'file' ? 'file' : 'dir',
-                     :size => nil,
-                     :lastrev => Revision.new({
-                       :identifier => nil,
-                       :scmid => modified_element.elements['patch'].attributes['hash']
-                       })
-                     })
-        end
-
-        def get_paths_for_patch(hash)
-          paths = get_paths_for_patch_raw(hash)
-          if self.class.client_version_above?([2, 4])
-            orig_paths = paths
-            paths = []
-            add_paths = []
-            add_paths_name = []
-            mod_paths = []
-            other_paths = []
-            orig_paths.each do |path|
-              if path[:action] == 'A'
-                add_paths << path
-                add_paths_name << path[:path]
-              elsif path[:action] == 'M'
-                mod_paths << path
-              else
-                other_paths << path
-              end
-            end
-            add_paths_name.each do |add_path|
-              mod_paths.delete_if { |m| m[:path] == add_path }
-            end
-            paths.concat add_paths
-            paths.concat mod_paths
-            paths.concat other_paths
-          end
-          paths
-        end
-
-        # Retrieve changed paths for a single patch
-        def get_paths_for_patch_raw(hash)
-          cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --summary --xml-output"
-          cmd << " --match #{shell_quote("hash #{hash}")} "
-          paths = []
-          shellout(cmd) do |io|
-            begin
-              # Darcs xml output has multiple root elements in this case (tested with darcs 1.0.7)
-              # A root element is added so that REXML doesn't raise an error
-              doc = REXML::Document.new("<fake_root>" + io.read + "</fake_root>")
-              doc.elements.each('fake_root/summary/*') do |modif|
-                paths << {:action => modif.name[0,1].upcase,
-                          :path => "/" + modif.text.chomp.gsub(/^\s*/, '')
-                         }
-              end
-            rescue
-            end
-          end
-          paths
-        rescue CommandFailed
-          paths
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/78/788c80634e0b1d20f293008ce93f6cb1d4ce218a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class JournalDetail < ActiveRecord::Base
-  belongs_to :journal
-  before_save :normalize_values
-
-  def custom_field
-    if property == 'cf'
-      @custom_field ||= CustomField.find_by_id(prop_key)
-    end
-  end
-
-  private
-
-  def normalize_values
-    self.value = normalize(value)
-    self.old_value = normalize(old_value)
-  end
-
-  def normalize(v)
-    case v
-    when true
-      "1"
-    when false
-      "0"
-    when Date
-      v.strftime("%Y-%m-%d")
-    else
-      v
-    end
-  end
-end
--- a/.svn/pristine/78/78d4b11a09b045fdd7cd2b6a434ac47f6be2b36b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingContextMenusTest < ActionController::IntegrationTest
-  def test_context_menus_time_entries
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/time_entries/context_menu" },
-          { :controller => 'context_menus', :action => 'time_entries' }
-        )
-    end
-  end
-
-  def test_context_menus_issues
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/issues/context_menu" },
-          { :controller => 'context_menus', :action => 'issues' }
-        )
-    end
-  end
-end
--- a/.svn/pristine/79/791795b2319be82f4ccbdcd799aa17c64410dd34.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-namespace :redmine do
-  namespace :attachments do
-    desc 'Removes uploaded files left unattached after one day.'
-    task :prune => :environment do
-      Attachment.prune
-    end
-
-    desc 'Moves attachments stored at the root of the file directory (ie. created before Redmine 2.3) to their subdirectories'
-    task :move_to_subdirectories => :environment do
-      Attachment.move_from_root_to_target_directory
-    end
-  end
-
-  namespace :tokens do
-    desc 'Removes expired tokens.'
-    task :prune => :environment do
-      Token.destroy_expired
-    end
-  end
-
-  namespace :watchers do
-    desc 'Removes watchers from what they can no longer view.'
-    task :prune => :environment do
-      Watcher.prune
-    end
-  end
-
-  desc 'Fetch changesets from the repositories'
-  task :fetch_changesets => :environment do
-    Repository.fetch_changesets
-  end
-
-  desc 'Migrates and copies plugins assets.'
-  task :plugins do
-    Rake::Task["redmine:plugins:migrate"].invoke
-    Rake::Task["redmine:plugins:assets"].invoke
-  end
-
-  namespace :plugins do
-    desc 'Migrates installed plugins.'
-    task :migrate => :environment do
-      name = ENV['NAME']
-      version = nil
-      version_string = ENV['VERSION']
-      if version_string
-        if version_string =~ /^\d+$/
-          version = version_string.to_i
-          if name.nil?
-            abort "The VERSION argument requires a plugin NAME."
-          end
-        else
-          abort "Invalid VERSION #{version_string} given."
-        end
-      end
-
-      begin
-        Redmine::Plugin.migrate(name, version)
-      rescue Redmine::PluginNotFound
-        abort "Plugin #{name} was not found."
-      end
-
-      Rake::Task["db:schema:dump"].invoke
-    end
-
-    desc 'Copies plugins assets into the public directory.'
-    task :assets => :environment do
-      name = ENV['NAME']
-
-      begin
-        Redmine::Plugin.mirror_assets(name)
-      rescue Redmine::PluginNotFound
-        abort "Plugin #{name} was not found."
-      end
-    end
-
-    desc 'Runs the plugins tests.'
-    task :test do
-      Rake::Task["redmine:plugins:test:units"].invoke
-      Rake::Task["redmine:plugins:test:functionals"].invoke
-      Rake::Task["redmine:plugins:test:integration"].invoke
-    end
-
-    namespace :test do
-      desc 'Runs the plugins unit tests.'
-      Rake::TestTask.new :units => "db:test:prepare" do |t|
-        t.libs << "test"
-        t.verbose = true
-        t.pattern = "plugins/#{ENV['NAME'] || '*'}/test/unit/**/*_test.rb"
-      end
-
-      desc 'Runs the plugins functional tests.'
-      Rake::TestTask.new :functionals => "db:test:prepare" do |t|
-        t.libs << "test"
-        t.verbose = true
-        t.pattern = "plugins/#{ENV['NAME'] || '*'}/test/functional/**/*_test.rb"
-      end
-
-      desc 'Runs the plugins integration tests.'
-      Rake::TestTask.new :integration => "db:test:prepare" do |t|
-        t.libs << "test"
-        t.verbose = true
-        t.pattern = "plugins/#{ENV['NAME'] || '*'}/test/integration/**/*_test.rb"
-      end
-    end
-  end
-end
-
-# Load plugins' rake tasks
-Dir[File.join(Rails.root, "plugins/*/lib/tasks/**/*.rake")].sort.each { |ext| load ext }
--- a/.svn/pristine/79/79599156ceffeaaae36ac3fa01857d9ccf943ee2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2642 +0,0 @@
-== Redmine changelog
-
-Redmine - project management software
-Copyright (C) 2006-2013  Jean-Philippe Lang
-http://www.redmine.org/
-
-== 2013-12-23 v2.4.2
-
-* Defect #15398: HTML 5 invalid <center> tag
-* Defect #15523: CSS class for done ratio is not properly generated
-* Defect #15623: Timelog filtering by activity field does not handle project activity overrides
-* Defect #15677: Links for relations in notifications do not include hostname
-* Defect #15684: MailHandler : text/plain attachments are added to description
-* Defect #15714: Notification on loosing assignment does not work
-* Defect #15735: OpenID login fails due to CSRF verification
-* Defect #15741: Multiple scrollbars in project selection tree
-* Patch #9442: Russian wiki syntax help translations
-* Patch #15524: Japanese translation update (r12278)
-* Patch #15601: Turkish translation update
-* Patch #15688: Spanish translation updated
-* Patch #15696: Russian translation update
-
-== 2013-11-23 v2.4.1
-
-* Defect #15401: Wiki syntax "bold italic" is incorrect
-* Defect #15414: Empty sidebar should not be displayed in project overview
-* Defect #15427: REST API POST and PUT broken
-* Patch #15376: Traditional Chinese translation (to r12295)
-* Patch #15395: German "ImageMagick convert available" translation
-* Patch #15400: Czech Wiki syntax traslation
-* Patch #15402: Czech translation for 2.4-stable
-
-== 2013-11-17 v2.4.0
-
-* Defect #1983: statistics get rather cramped with more than 15 or so contributers
-* Defect #7335: Sorting issues in gantt by date, not by id
-* Defect #12681: Treat group assignments as assigned to me
-* Defect #12824: Useless "edit" link in workflow menu
-* Defect #13260: JQuery Datepicker popup is missing multiple month/year modifiers
-* Defect #13537: Filters will show issues with unused custom fields.
-* Defect #13829: Favicon bug in IE8
-* Defect #13949: Handling of attachment uploads when 'Maximum attachment size' is set to 0
-* Defect #13989: Trac and Mantis importers reset global notification settings
-* Defect #13990: Trac importer breaks on exotic filenames and ruby 1.9+
-* Defect #14028: Plugins Gemfiles loading breaks __FILE__
-* Defect #14086: Better handling of issue start date validation
-* Defect #14206: Synchronize the lang attribute of the HTML with the display language
-* Defect #14403: No error message if notification mail could not delivered
-* Defect #14516: Missing Sort Column Label and Center Align on Admin-Enumerations
-* Defect #14517: Missing Html Tile on Admin (Groups, LDAP and Plugins)
-* Defect #14598: Wrong test with logger.info in model mail_handler
-* Defect #14615: Warn me when leaving a page with unsaved text doesn't work when editing an update note
-* Defect #14621: AJAX call on the issue form resets data entered during the request
-* Defect #14657: Wrong German translation for member inheritance
-* Defect #14773: ActiveRecord::Acts::Versioned::ActMethods#next_version Generates ArgumentError
-* Defect #14819: Newlines in attachment filename causes crash
-* Defect #14986: 500 error when viewing a wiki page without WikiContent
-* Defect #14995: Japanese "notice_not_authorized" translation is incorrect
-* Defect #15044: Patch for giving controller_issues_edit_after_save api hook the correct context
-* Defect #15050: redmine:migrate_from_mantis fails to migrate projects with all upper case name
-* Defect #15058: Project authorization EnabledModule N+1 queries
-* Defect #15113: The mail method should return a Mail::Message
-* Defect #15135: Issue#update_nested_set_attributes comparing nil with empty string
-* Defect #15191: HTML 5 validation failures
-* Defect #15227: Custom fields in issue form - splitting is incorrect
-* Defect #15307: HTML 5 deprecates width and align attributes
-* Feature #1005: Add the addition/removal/change of related issues to the history
-* Feature #1019: Role based custom queries
-* Feature #1391: Ability to force user to change password
-* Feature #2199: Ability to clear dates and text fields when bulk editing issues
-* Feature #2427: Document horizontal rule syntax
-* Feature #2795: Add a "Cancel" button to the "Delete" project page when deleting a project.
-* Feature #2865: One click filter in search view
-* Feature #3413: Exclude attachments from incoming emails based on file name
-* Feature #3872: New user password - better functionality
-* Feature #4911: Multiple issue update rules with different keywords in commit messages
-* Feature #5037: Role-based issue custom field visibility
-* Feature #7590: Different commit Keywords for each tracker
-* Feature #7836: Ability to save Gantt query filters
-* Feature #8253: Update CodeRay to 1.1 final
-* Feature #11159: REST API for getting CustomField definitions
-* Feature #12293: Add links to attachments in new issue email notification
-* Feature #12912: Issue-notes Redmine links: append actual note reference to rendered links
-* Feature #13157: Link on "My Page" to view all my spent time
-* Feature #13746: Highlighting of source link target line
-* Feature #13943: Better handling of validation errors when bulk editing issues
-* Feature #13945: Disable autofetching of repository changesets if projects are closed
-* Feature #14024: Default of issue start and due date
-* Feature #14060: Enable configuration of OpenIdAuthentication.store
-* Feature #14228: Registered users should have a way to get a new action email
-* Feature #14614: View hooks for user preferences
-* Feature #14630: wiki_syntax.html per language (wiki help localization mechanism)
-* Feature #15136: Activate Custom Fields on a selection of projects directly from Custom fields page
-* Feature #15182: Return to section anchor after wiki section edit
-* Feature #15218: Update Rails 3.2.15
-* Feature #15311: Add an indication to admin/info whether or not ImageMagick convert is available
-* Patch #6689: Document project-links in parse_redmine_links
-* Patch #13460: All translations: RSS -> Atom
-* Patch #13482: Do not add empty header/footer to notification emails
-* Patch #13528: Traditional Chinese "label_total_time" translation
-* Patch #13551: update Dutch translations - March 2013
-* Patch #13577: Japanese translation improvement ("done ratio")
-* Patch #13646: Fix handling multiple text parts in email
-* Patch #13674: Lithuanian translation
-* Patch #13687: Favicon bug in opera browser
-* Patch #13697: Back-button on diff page is not working when I'm directed from email
-* Patch #13745: Correct translation for member save button
-* Patch #13808: Changed Bulgarian "label_statistics" translation
-* Patch #13825: German translation: jquery.ui.datepicker-de.js
-* Patch #13900: Update URL when changing tab
-* Patch #13931: Error and inconsistencies in Croatian translation
-* Patch #13948: REST API should return user.status
-* Patch #13988: Enhanced Arabic translation
-* Patch #14138: Output changeset comment in html title
-* Patch #14180: Improve pt-BR translation
-* Patch #14222: German translation: grammar + spelling
-* Patch #14223: Fix icon transparency issues
-* Patch #14360: Slovene language translation
-* Patch #14767: More CSS classes on various fields
-* Patch #14901: Slovak translation
-* Patch #14920: Russian numeric translation
-* Patch #14981: Italian translation
-* Patch #15072: Optimization of issues journal custom fields display
-* Patch #15073: list custom fields : multiple select filter wider
-* Patch #15075: Fix typo in the Dutch "label_user_mail_option_all" translation
-* Patch #15277: Accept custom field format added at runtime
-* Patch #15295: Log error messages when moving attachements in sub-directories
-* Patch #15369: Bulgarian translation (r12278)
-
-== 2013-11-17 v2.3.4
-
-* Defect #13348: Repository tree can't handle two loading at once
-* Defect #13632: Empty page attached when exporting PDF
-* Defect #14590: migrate_from_trac.rake does not import Trac users, uses too short password
-* Defect #14656: JRuby: Encoding error when creating issues
-* Defect #14883: Update activerecord-jdbc-adapter
-* Defect #14902: Potential invalid SQL error with invalid group_ids
-* Defect #14931: SCM annotate with non ASCII author
-* Defect #14960: migrate_from_mantis.rake does not import Mantis users, uses too short password
-* Defect #14977: Internal Server Error while uploading file
-* Defect #15190: JS-error while using a global custom query w/ project filter in a project context
-* Defect #15235: Wiki Pages REST API with version returns wrong comments
-* Defect #15344: Default status always inserted to allowed statuses when changing status
-* Feature #14919: Update ruby-openid version above 2.3.0
-* Patch #14592: migrate_from_trac.rake does not properly parse First Name and Last Name
-* Patch #14886: Norweigan - label_copied_to and label_copied_from translated
-* Patch #15185: Simplified Chinese translation for 2.3-stable
-
-== 2013-09-14 v2.3.3
-
-* Defect #13008: Usage of attribute_present? in UserPreference
-* Defect #14340: Autocomplete fields rendering issue with alternate theme
-* Defect #14366: Spent Time report sorting on custom fields causes error
-* Defect #14369: Open/closed issue counts on issues summary are not displayed with SQLServer
-* Defect #14401: Filtering issues on "related to" may ignore other filters
-* Defect #14415: Spent time details and report should ignore 'Setting.display_subprojects_issues?' when 'Subproject' filter is enabled.
-* Defect #14422: CVS root_url not recognized when connection string does not include port
-* Defect #14447: Additional status transitions for assignees do not work if assigned to a group
-* Defect #14511: warning: class variable access from toplevel on Ruby 2.0
-* Defect #14562: diff of CJK (Chinese/Japanese/Korean) is broken on Ruby 1.8
-* Defect #14584: Standard fields disabled for certain trackers still appear in email notifications
-* Defect #14607: rake redmine:load_default_data Error
-* Defect #14697: Wrong Russian translation in close project message
-* Defect #14798: Wrong done_ratio calculation for parent with subtask having estimated_hours=0
-* Patch #14485: Traditional Chinese translation for 2.3-stable
-* Patch #14502: Russian translation for 2.3-stable
-* Patch #14531: Spanish translations for 2.3.x
-* Patch #14686: Portuguese translation for 2.3-stable
-
-== 2013-07-14 v2.3.2
-
-* Defect #9996: configuration.yml in documentation , but redmine ask me to create email.yml
-* Defect #13692: warning: already initialized constant on Ruby 1.8.7
-* Defect #13783: Internal error on time tracking activity enumeration deletion
-* Defect #13821: "obj" parameter is not defined for macros used in description of documents
-* Defect #13850: Unable to set custom fields for versions using the REST API
-* Defect #13910: Values of custom fields are not kept in issues when copying a project
-* Defect #13950: Duplicate Lithuanian "error_attachment_too_big" translation keys
-* Defect #14015: Ruby hangs when adding a subtask
-* Defect #14020: Locking and unlocking a user resets the email notification checkbox
-* Defect #14023: Can't delete relation when Redmine runs in a subpath
-* Defect #14051: Filtering issues with custom field in date format with NULL(empty) value
-* Defect #14178: PDF API broken in version 2.3.1
-* Defect #14186: Project name is not properly escaped in issue filters JSON
-* Defect #14242: Project auto generation fails when projects created in the same time
-* Defect #14245: Gem::InstallError: nokogiri requires Ruby version >= 1.9.2.
-* Defect #14346: Latvian translation for "Log time"
-* Feature #12888: Adding markings to emails generated by Private comments
-* Feature #14419: Include RUBY_PATCHLEVEL and RUBY_RELEASE_DATE in info.rb
-* Patch #14005: Swedish Translation for 2.3-stable
-* Patch #14101: Receive IMAP by uid's
-* Patch #14103: Disconnect and logout from IMAP after mail receive
-* Patch #14145: German translation of x_hours
-* Patch #14182: pt-BR translation for 2.3-stable
-* Patch #14196: Italian translation for 2.3-stable
-* Patch #14221: Translation of x_hours for many languages
-
-== 2013-05-01 v2.3.1
-
-* Defect #12650: Lost text after selection in issue list with IE
-* Defect #12684: Hotkey for Issue-Edit doesn't work as expected
-* Defect #13405: Commit link title is escaped twice when using "commit:" prefix
-* Defect #13541: Can't access SCM when log/production.scm.stderr.log is not writable
-* Defect #13579: Datepicker uses Simplified Chinese in Traditional Chinese locale
-* Defect #13584: Missing Portuguese jQuery UI date picker
-* Defect #13586: Circular loop testing prevents precedes/follows relation between subtasks
-* Defect #13618: CSV export of spent time ignores filters and columns selection
-* Defect #13630: PDF export generates the issue id twice
-* Defect #13644: Diff - Internal Error
-* Defect #13712: Fix email rake tasks to also support no_account_notice and default_group options
-* Defect #13811: Broken javascript in IE7 ; recurrence of #12195
-* Defect #13823: Trailing comma in javascript files
-* Patch #13531: Traditional Chinese translation for 2.3-stable
-* Patch #13552: Dutch translations for 2.3-stable
-* Patch #13678: Lithuanian translation for 2.3-stable
-
-== 2013-03-19 v2.3.0
-
-* Defect #3107: Issue with two digit year on Logtime
-* Defect #3371: Autologin does not work when using openid
-* Defect #3676: www. generates broken link in formatted text
-* Defect #4700: Adding news does not send notification to all project members
-* Defect #5329: Time entries report broken on first week of year
-* Defect #8794: Circular loop when using relations and subtasks
-* Defect #9475: German Translation "My custom queries" and "Custom queries"
-* Defect #9549: Only 100 users are displayed when adding new project members
-* Defect #10277: Redmine wikitext URL-into-link creation with hyphen is wrong
-* Defect #10364: Custom field float separator in CSV export
-* Defect #10930: rake redmine:load_default_data error in 2.0 with SQLServer
-* Defect #10977: Redmine shouldn't require all database gems
-* Defect #12528: Handle temporary failures gracefully in the external mail handler script
-* Defect #12629: Wrong German "label_issues_by" translation
-* Defect #12641: Diff outputs become ??? in some non ASCII words.
-* Defect #12707: Typo in app/models/tracker.rb
-* Defect #12716: Attachment description lost when issue validation fails
-* Defect #12735: Negative duration allowed
-* Defect #12736: Negative start/due dates allowed
-* Defect #12968: Subtasks don't resepect following/precedes
-* Defect #13006: Filter "Assignee's group" doesn't work with group assignments
-* Defect #13022: Image pointing towards /logout signs out user
-* Defect #13059: Custom fields are listed two times in workflow/Fields permission
-* Defect #13076: Project overview page shows trackers from subprojects with disabled issue module
-* Defect #13119: custom_field_values are not reloaded on #reload
-* Defect #13154: After upgrade to 2.2.2 ticket list on some projects fails
-* Defect #13188: Forms are not updated after changing the status field without "Add issues" permission
-* Defect #13251: Adding a "follows" relation may not refresh relations list
-* Defect #13272: translation missing: setting_default_projects_tracker_ids
-* Defect #13328: Copying an issue as a child of itself creates an extra issue
-* Defect #13335: Autologin does not work with custom autologin cookie name
-* Defect #13350: Japanese mistranslation fix
-* Feature #824: Add "closed_on" issue field (storing time of last closing) & add it as a column and filter on the issue list.
-* Feature #1766: Custom fields should become addable to Spent Time list/report
-* Feature #3436: Show relations in Gantt diagram
-* Feature #3957: Ajax file upload with progress bar
-* Feature #5298: Store attachments in sub directories
-* Feature #5605: Subprojects should (optionally) inherit Members from their parent
-* Feature #6727: Add/remove issue watchers via REST API
-* Feature #7159: Bulk watch/unwatch issues from the context menu
-* Feature #8529: Get the API key of the user through REST API
-* Feature #8579: Multiple file upload with HTML5 / Drag-and-Drop
-* Feature #10191: Add Filters For Spent time's Details and Report
-* Feature #10286: Auto-populate fields while creating a new user with LDAP
-* Feature #10352: Preview should already display the freshly attached images
-* Feature #11498: Add --no-account-notice option for the mail handler script
-* Feature #12122: Gantt progress lines (html only)
-* Feature #12228: JRuby 1.7.2 support
-* Feature #12251: Custom fields: 'Multiple values' should be able to be checked and then unchecked
-* Feature #12401: Split "Manage documents" permission into create, edit and delete permissions
-* Feature #12542: Group events in the activity view
-* Feature #12665: Link to a file in a repository branch
-* Feature #12713: Microsoft SQLServer support
-* Feature #12787: Remove "Warning - iconv will be deprecated in the future, use String#encode instead."
-* Feature #12843: Add links to projects in Group projects list
-* Feature #12898: Handle GET /issues/context_menu parameters nicely to prevent returning error 500 to crawlers
-* Feature #12992: Make JSONP support optional and disabled by default
-* Feature #13174: Raise group name maximum length to 255 characters
-* Feature #13175: Possibility to define the default enable trackers when creating a project
-* Feature #13329: Ruby 2.0 support
-* Feature #13337: Split translation "label_total"
-* Feature #13340: Mail handler: option to add created user to default group
-* Feature #13341: Mail handler: --no-notification option to disable notifications to the created user
-* Patch #7202: Polish translation for v1.0.4
-* Patch #7851: Italian translation for 'issue'
-* Patch #9225: Generate project identifier automatically with JavaScript
-* Patch #10916: Optimisation in issues relations display
-* Patch #12485: Don't force english language for default admin account
-* Patch #12499: Use lambda in model scopes
-* Patch #12611: Login link unexpected logs you out
-* Patch #12626: Updated Japanese translations for button_view and permission_commit_access
-* Patch #12640: Russian "about_x_hours" translation change
-* Patch #12645: Russian numeric translation
-* Patch #12660: Consistent German translation for my page
-* Patch #12708: Restructured german translation (Cleanup)
-* Patch #12721: Optimize MenuManager a bit
-* Patch #12725: Change pourcent to percent (#12724)
-* Patch #12754: Updated Japanese translation for notice_account_register_done
-* Patch #12788: Copyright for 2013
-* Patch #12806: Serbian translation change
-* Patch #12810: Swedish Translation change
-* Patch #12910: Plugin settings div should perhaps have 'settings' CSS class
-* Patch #12911: Fix 500 error for requests to the settings path for non-configurable plugins
-* Patch #12926: Bulgarian translation (r11218)
-* Patch #12927: Swedish Translation for r11244
-* Patch #12967: Change Spanish login/logout translations
-* Patch #12988: Russian translation for trunk
-* Patch #13080: German translation of label_in
-* Patch #13098: Small datepicker improvements
-* Patch #13152: Locale file for Azerbaijanian language
-* Patch #13155: Add login to /users/:id API for current user
-* Patch #13173: Put source :rubygems url HTTP secure
-* Patch #13190: Bulgarian translation (r11404)
-* Patch #13198: Traditional Chinese language file (to r11426)
-* Patch #13203: German translation change for follow and precedes is inconsitent
-* Patch #13206: Portuguese translation file
-* Patch #13246: Some german translation patches
-* Patch #13280: German translation (r11478)
-* Patch #13301: Performance: avoid querying all memberships in User#roles_for_project
-* Patch #13309: Add "tracker-[id]" CSS class to issues
-* Patch #13324: fixing some pt-br locales
-* Patch #13339: Complete language Vietnamese file
-* Patch #13391: Czech translation update
-* Patch #13399: Fixed some wrong or confusing translation in Korean locale
-* Patch #13414: Bulgarian translation (r11567)
-* Patch #13420: Korean translation for 2.3 (r11583)
-* Patch #13437: German translation of setting_emails_header
-* Patch #13438: English translation
-* Patch #13447: German translation - some patches
-* Patch #13450: Czech translation
-* Patch #13475: fixing some pt-br locales
-* Patch #13514: fixing some pt-br locales
-
-== 2013-03-19 v2.2.4
-
-* Upgrade to Rails 3.2.13
-* Defect #12243: Ordering forum replies by last reply date is broken
-* Defect #13127: h1 multiple lined titles breaks into main menu
-* Defect #13138: Generating PDF of issue causes UndefinedConversionError with htmlentities gem
-* Defect #13165: rdm-mailhandler.rb: initialize_http_header override basic auth
-* Defect #13232: Link to topic in nonexistent forum causes error 500
-* Patch #13181: Bulgarian translation of jstoolbar-bg.js
-* Patch #13207: Portuguese translation for 2.2-stable
-* Patch #13310: pt-BR label_last_n_weeks translation
-* Patch #13325: pt-BR translation for 2.2-stable
-* Patch #13343: Vietnamese translation for 2.2-stable
-* Patch #13398: Czech translation for 2.2-stable
-
-== 2013-02-12 v2.2.3
-
-* Upgrade to Rails 3.2.12
-* Defect #11987: pdf: Broken new line in table
-* Defect #12930: 404 Error when referencing different project source files in the wiki syntax
-* Defect #12979: Wiki link syntax commit:repo_a:abcd doesn't work
-* Defect #13075: Can't clear custom field value through context menu in the issue list
-* Defect #13097: Project copy fails when wiki module is disabled
-* Defect #13126: Issue view: estimated time vs. spent time
-* Patch #12922: Update Spanish translation
-* Patch #12928: Bulgarian translation for 2.2-stable
-* Patch #12987: Russian translation for 2.2-stable
-
-== 2013-01-20 v2.2.2
-
-* Defect #7510: Link to attachment should return latest attachment
-* Defect #9842: {{toc}} is not replaced by table of content when exporting wiki page to pdf
-* Defect #12749: Plugins cannot route wiki page sub-path
-* Defect #12799: Cannot edit a wiki section which title starts with a tab
-* Defect #12801: Viewing the history of a wiki page with attachments raises an error
-* Defect #12833: Input fields restricted on length should have maxlength parameter set
-* Defect #12838: Blank page when clicking Add with no block selected on my page layout
-* Defect #12851: "Parent task is invalid" while editing child issues by Role with restricted Issues Visibility
-* Patch #12800: Serbian Latin translation patch (sr-YU.yml)
-* Patch #12809: Swedish Translation for r11162
-* Patch #12818: Minor swedish translation fix
-
-== 2013-01-09 v2.2.1
-
-* Upgrade to Rails 3.2.11
-* Defect #12652: "Copy ticket" selects "new ticket"
-* Defect #12691: Textile Homepage Dead?
-* Defect #12711: incorrect fix of lib/SVG/Graph/TimeSeries.rb
-* Defect #12744: Unable to call a macro with a name that contains uppercase letters
-* Defect #12776: Security vulnerability in Rails 3.2.10 (CVE-2013-0156)
-* Patch #12630: Russian "x_hours" translation
-
-== 2012-12-18 v2.2.0
-
-* Defect #4787: Gannt to PNG - CJK (Chinese, Japanese and Korean) characters appear as ?
-* Defect #8106: Issues by Category should show tasks without category
-* Defect #8373: i18n string text_are_you_sure_with_children no longer used
-* Defect #11426: Filtering with Due Date in less than N days should show overdue issues
-* Defect #11834: Bazaar: "???" instead of non ASCII character in paths on non UTF-8 locale
-* Defect #11868: Git and Mercurial diff displays deleted files as /dev/null
-* Defect #11979: No validation errors when entering an invalid "Parent task"
-* Defect #12012: Redmine::VERSION.revision method does not work on Subversion 1.7 working copy
-* Defect #12018: Issue filter select box order changes randomly
-* Defect #12090: email recipients not written to action_mailer log if BCC recipients setting is checked
-* Defect #12092: Issue "start date" validation does not work correctly
-* Defect #12285: Some unit and functional tests miss fixtures and break when run alone
-* Defect #12286: Emails of private notes are sent to watcher users regardless of viewing permissions
-* Defect #12310: Attachments may not be displayed in the order they were selected
-* Defect #12356: Issue "Update" link broken focus
-* Defect #12397: Error in Textile conversion of HTTP links, containing russian letters
-* Defect #12434: Respond with 404 instead of 500 when requesting a wiki diff with invalid versions
-* Feature #1554: Private comments in tickets
-* Feature #2161: Time tracking code should respect weekends as "no work" days
-* Feature #3239: Show related issues on the Issues Listing
-* Feature #3265: Filter on issue relations
-* Feature #3447: Option to display the issue descriptions on the issues list
-* Feature #3511: Ability to sort issues by grouped column
-* Feature #4590: Precede-Follow relation should move following issues when rescheduling issue earlier
-* Feature #5487: Allow subtasks to cross projects
-* Feature #6899: Add a relation between the original and copied issue
-* Feature #7082: Rest API for wiki
-* Feature #9835: REST API - List priorities
-* Feature #10789: Macros {{child_pages}} with depth parameter
-* Feature #10852: Ability to delete a version from a wiki page history
-* Feature #10937: new user format #{lastname}
-* Feature #11502: Expose roles details via REST API
-* Feature #11755: Impersonate user through REST API auth
-* Feature #12085: New user name format: firstname + first letter of lastname
-* Feature #12125: Set filename used to store attachment updloaded via the REST API
-* Feature #12167: Macro for inserting collapsible block of text
-* Feature #12211: Wrap issue description and its contextual menu in a div
-* Feature #12216: Textual CSS class for priorities
-* Feature #12299: Redmine version requirement improvements (in plugins)
-* Feature #12393: Upgrade to Rails 3.2.9
-* Feature #12475: Lazy loading of translation files for faster startup
-* Patch #11846: Fill username when authentification failed
-* Patch #11862: Add "last 2 weeks" preset to time entries reporting
-* Patch #11992: Japanese translation about issue relations improved
-* Patch #12027: Incorrect Spanish "September" month name
-* Patch #12061: Japanese translation improvement (permission names)
-* Patch #12078: User#allowed_to? should return true or false
-* Patch #12117: Change Japanese translation of "admin"
-* Patch #12142: Updated translation in Lithuanian
-* Patch #12232: German translation enhancements
-* Patch #12316: Fix Lithuanian numeral translation
-* Patch #12494: Bulgarian "button_submit" translation change
-* Patch #12514: Updated translation in Lithuanian
-* Patch #12602: Korean translation update for 2.2-stable
-* Patch #12608: Norwegian translation changed
-* Patch #12619: Russian translation change
-
-== 2012-12-18 v2.1.5
-
-* Defect #12400: Validation fails when receiving an email with list custom fields
-* Defect #12451: Macros.rb extract_macro_options should use lazy search
-* Defect #12513: Grouping of issues by custom fields not correct in PDF export
-* Defect #12566: Issue history notes previews are broken
-* Defect #12568: Clicking "edit" on a journal multiple times shows multiple forms
-* Patch #12605: Norwegian translation for 1.4-stable update
-* Patch #12614: Dutch translation
-* Patch #12615: Russian translation
-
-== 2012-11-24 v2.1.4
-
-* Defect #12274: Wiki export from Index by title is truncated
-* Defect #12298: Right-click context menu unable to batch/bulk update (IE8)
-* Defect #12332: Repository identifier does not display on Project/Settings/Repositories
-* Defect #12396: Error when receiving an email without subject header
-* Defect #12399: Non ASCII attachment filename encoding broken (MOJIBAKE) in receiving mail on Ruby 1.8
-* Defect #12409: Git: changesets aren't read after clear_changesets call
-* Defect #12431: Project.rebuild! sorts root projects by id instead of name
-
-== 2012-11-17 v2.1.3
-
-* Defect #12050: :export links to repository files lead to a 404 error
-* Defect #12189: Missing tmp/pdf directory
-* Defect #12195: Javascript error with IE7 / IE8 on new issue form
-* Defect #12196: "Page not found" on OK button in SCM "View all revisions" page
-* Defect #12199: Confirmation message displayed when clicking a disabled delete link in the context menu
-* Defect #12231: Hardcoded "Back" in Repository
-* Defect #12294: Incorrect german translation for "registered" users filter
-* Defect #12349: Watchers auto-complete search on non-latin chars
-* Defect #12358: 'None' grouped issue list section should be translated
-* Defect #12359: Version date field regex validation accepts invalid date
-* Defect #12375: Receiving mail subject encoding broken (MOJIBAKE) in some cases on Ruby 1.8
-* Patch #9732: German translations
-* Patch #12021: Russian locale translations
-* Patch #12188: Simplified Chinese translation with zh.yml file based on Rev:10681
-* Patch #12235: German translation for 2.1-stable
-* Patch #12237: Added German Translation
-
-== 2012-09-30 v2.1.2
-
-* Defect #11929: XSS vulnerability in Redmine 2.1.x
-
-== 2012-09-30 v2.1.1
-
-* Defect #11290: ParseDate missing in Ruby 1.9x
-* Defect #11844: "load_default_data" rake task fails to print the error message if one occurs
-* Defect #11850: Can't create a user from ldap by on-the-fly on the redmine server using URI prefix
-* Defect #11872: Private issue visible to anonymous users after its author is deleted
-* Defect #11885: Filter misses Selectionfield on IE8
-* Defect #11893: New relation form Cancel link is broken with Chrome 21
-* Defect #11905: Potential "can't dup NilClass" error in UserPreference
-* Defect #11909: Autocomplete results not reset after clearing search field
-* Defect #11922: bs.yml and de.yml lead to error by number_to_currency()
-* Defect #11945: rake task prints "can't convert Errno::EACCES into String" in case of no permission of public/plugin_assets
-* Defect #11975: Undefined status transitions allowed in workflow (author of issue changes when selecting a new status)
-* Defect #11982: SCM diff view generates extra parameter for switching mode
-* Patch #11897: Traditional Chinese language file (to r10433)
-
-== 2012-09-16 v2.1.0
-
-* Defect #2071: Reordering priority-enumerations breaks alternate-theme's issue-colouring
-* Defect #2190: Month names not translated to german
-* Defect #8978: LDAP timeout if an LDAP auth provider is unreachable
-* Defect #9839: Gantt abbr of weekday should not be necessarily the first letter of the long day name
-* Defect #10928: Documentation about generating a plugin is not up-to-date
-* Defect #11034: TLS configuration documentation for Rails 3
-* Defect #11073: UserCustomField order_statement returns wrong output
-* Defect #11153: Default sorting for target version is DESC instead of ASC
-* Defect #11207: Issues associated with a locked version are not copied when copying a project
-* Defect #11304: Issue-class: status-1, status-2 etc. refer to status position instead of status id
-* Defect #11331: Openid registration form should not require user to enter password
-* Defect #11345: Context menu should show shared versions when editing issues from different projects
-* Defect #11355: Plain text notification emails content is HTML escaped
-* Defect #11388: Updating a version through rest API returns invalid JSON
-* Defect #11389: Warning in awesome_nested_set.rb
-* Defect #11503: Accessing /projects/:project/wiki/something.png fails with error 500
-* Defect #11506: Versions that are not shared should not be assignable when selecting another project
-* Defect #11508: Projects not ordered alphabetically after renaming project
-* Defect #11540: Roadmap anchor links can be ambigous
-* Defect #11545: Overwriting existing method Issue.open
-* Defect #11552: MailHandler does not match assignee name with spaces
-* Defect #11571: Custom fields of type version not proper handled in receiving e-mails
-* Defect #11577: Can't use non-latin anchor in wiki
-* Defect #11612: Revision graph sometimes broken due to raphael.js error
-* Defect #11621: Redmine MIME Detection Of Javascript Files Non-Standard
-* Defect #11633: Macro arguments should not be parsed by text formatters
-* Defect #11662: Invalid query returned from Issues.visible scope after accessing User#projects_by_role with a role that is not present
-* Defect #11691: 404 response when deleting a user from the edit page
-* Defect #11723: redmine:send_reminders notification misses if assignee is a group
-* Defect #11738: Batch update of issues clears project path
-* Defect #11749: Redmine.pm: HEAD is not considered as a read-only method
-* Defect #11814: Date picker does not respect week start setting
-* Feature #703: Configurable required fields per tracker/status/role
-* Feature #1006: Display thumbnails of attached images
-* Feature #1091: Disabling default ticket fields per tracker
-* Feature #1360: Permission for adding an issue to a version.
-* Feature #3061: Let macros optionally match over multiple lines and ignore single curly braces
-* Feature #3510: Inserting image thumbnails inside the wiki
-* Feature #3521: Permissions for roles to change fields per tracker/status
-* Feature #3640: Freeze / Close Projects
-* Feature #3831: Support for subforums
-* Feature #6597: Configurable session lifetime and timeout
-* Feature #6965: Option to Copy Subtasks when copying an issue
-* Feature #8161: Ability to filter issues on project custom fields
-* Feature #8577: "Private" column and filter on the issue list
-* Feature #8981: REST Api for Groups
-* Feature #9258: Create role by copy
-* Feature #9419: Group/sort the issue list by user/version-format custom fields
-* Feature #10362: Show images in repositories inline when clicking the 'View' link
-* Feature #10419: Upgrade raphael.js (2.1.0)
-* Feature #11068: Ability to set default column order in issue list
-* Feature #11102: Add autocomplete to "Related issue" field on revision
-* Feature #11109: Repository Identifier should be frozen
-* Feature #11181: Additional "Log time" link on project overview
-* Feature #11205: Reversed order of priorities on the issue summary page
-* Feature #11445: Switch from Prototype to JQuery
-* Feature #11469: JSONP support
-* Feature #11475: Redmine.pm: Allow fallback to other Apache auth providers
-* Feature #11494: Don't turn #nnn with leading zeros into links
-* Feature #11539: Display a projects tree instead of a flat list in notification preferences
-* Feature #11578: Option to pass whole arguments to a macro without splitting them
-* Feature #11595: Missing mime type for svg files
-* Feature #11758: Upgrade to Rails 3.2.8
-* Patch #4905: Redmine.pm: add support for Git's smart HTTP protocol
-* Patch #10988: New Korean translation patch
-* Patch #11201: Korean translation special update
-* Patch #11401: Fix Japanese mistranslation for "button_submit"
-* Patch #11402: Japanese translation added for default role names
-* Patch #11411: Fix disordered use of long sound in Japanese "user" translation
-* Patch #11412: Unnatural Japanese message when users failed to login
-* Patch #11419: Fix wrong Japanese "label_attachment" translation
-* Patch #11496: Make labels clickable in Adminstration/Settings
-* Patch #11704: Avoid the use of tag("...", "...", true) in layout
-* Patch #11818: Redmine.pm fails when permissions are NULL
-
-== 2012-09-16 v2.0.4
-
-* Defect #10818: Running rake in test environment causes exception
-* Defect #11209: Wiki diff may generate broken HTML
-* Defect #11217: Project names in drop-down are escaped twice
-* Defect #11262: Link is escaped in wiki added/updated notification email
-* Defect #11307: Can't filter for negative numeric custom fields
-* Defect #11325: Unified diff link broken on specific file/revision diff view
-* Defect #11341: Escaped link in conflict resolution form
-* Defect #11365: Attachment description length is not validated
-* Defect #11511: Confirmation page has broken HTML when a project folding sub project is deleted
-* Defect #11533: rake redmine:plugins:test doesn't run tests in subdirectories
-* Defect #11541: Version sharing is missing in the REST API
-* Defect #11550: Issue reminder doesn't work when using asynchronous delivery
-* Defect #11776: Can't override mailer views inside redmine plugin.
-* Defect #11789: Edit section links broken with h5/h6 headings
-* Feature #11338: Exclude emails with auto-submitted => auto-generated
-* Patch #11299: redmine:plugins:migrate should update db/schema.rb
-* Patch #11328: Fix Japanese mistranslation for 'label_language_based'
-* Patch #11448: Russian translation for 1.4-stable and 2.0-stable
-* Patch #11600: Fix plural form of the abbreviation for hours in Brazilian Portuguese
-
-== 2012-06-18 v2.0.3
-
-* Defect #10688: PDF export from Wiki - Problems with tables
-* Defect #11061: Cannot choose commit versions to view differences in Git/Mercurial repository view
-* Defect #11065: E-Mail submitted tickets: German umlauts in 'Subject' get malformed (ruby 1.8)
-* Defect #11098: Default priorities have the same position and can't be reordered
-* Defect #11105: <% content_for :header_tags do %> doesn't work inside hook
-* Defect #11112: REST API - custom fields in POST/PUT ignored for time_entries
-* Defect #11118: "Maximum file size" displayed on upload forms is incorrect
-* Defect #11124: Link to user is escaped in activity title
-* Defect #11133: Wiki-page section edit link can point to incorrect section
-* Defect #11160: SQL Error on time report if a custom field has multiple values for an entry
-* Defect #11170: Topics sort order is broken in Redmine 2.x
-* Defect #11178: Spent time sorted by date-descending order lists same-date entries in physical order (not-reverse)
-* Defect #11185: Redmine fails to delete a project with parent/child task
-* Feature #11162: Upgrade to Rails 3.2.6
-* Patch #11113: Small glitch in German localization
-
-== 2012-06-05 v2.0.2
-
-* Defect #11032: Project list is not shown when "For any event on the selected projects only..." is selected on user edit panel
-* Defect #11038: "Create and continue" should preserve project, issue and activity when logging time
-* Defect #11046: Redmine.pm does not support "bind as user" ldap authentication
-* Defect #11051: reposman.rb fails in 1.4.2 because of missing require for rubygems
-* Defect #11085: Wiki start page can't be changed
-* Feature #11084: Update Rails to 3.2.5
-
-== 2012-05-28 v2.0.1
-
-* Defect #10923: After creating a new Version Redmine jumps back to "Information"
-* Defect #10932: Links to delete watchers are escaped when gravatars are enabled
-* Defect #10964: Updated column doesn't get updated on issues
-* Defect #10965: rake yard does not work for generating documentation.
-* Defect #10972: Columns selection not displayed on the custom query form
-* Defect #10991: My page > Spent time 'project' column is html-encoded
-* Defect #10996: Time zones lost when upgrading from Redmine 1.4 to 2.0
-* Defect #11013: Fetching Email from IMAP/POP3 - uninitialized constant RAILS_DEFAULT_LOGGER error
-* Defect #11024: redmine_plugin_model generator does not create the migration
-* Defect #11027: Saving new query without name causes escaping of input field
-* Defect #11028: Project identifier can be updated
-
-== 2012-05-15 v2.0.0
-
-* Feature #4796: Rails 3 support
-* Feature #7720: Limit the pagination-limit when max-results is fewer than max-pagination-limit
-* Feature #9034: Add an id to the flash messages
-* Patch #10782: Better translation for Estonian language
-
-== 2012-05-13 v1.4.2
-
-* Defect #10744: rake task redmine:email:test broken
-* Defect #10787: "Allow users to unsubscribe" option is confusing
-* Defect #10827: Cannot access Repositories page and Settings in a Project - Error 500
-* Defect #10829: db:migrate fails 0.8.2 -> 1.4.1
-* Defect #10832: REST Uploads fail with fastcgi
-* Defect #10837: reposman and rdm-mailhandler not working with ruby 1.9.x
-* Defect #10856: can not load translations from hr.yml with ruby1.9.3-p194
-* Defect #10865: Filter reset when deleting locked user
-* Feature #9790: Allow filtering text custom fields on "is null" and "is not null"
-* Feature #10778: svn:ignore for config/additional_environment.rb
-* Feature #10875: Partial Albanian Translations
-* Feature #10888: Bring back List-Id to help aid Gmail filtering
-* Patch #10733: Traditional Chinese language file (to r9502)
-* Patch #10745: Japanese translation update (r9519)
-* Patch #10750: Swedish Translation for r9522
-* Patch #10785: Bulgarian translation (jstoolbar)
-* Patch #10800: Simplified Chinese translation
-
-== 2012-04-20 v1.4.1
-
-* Defect #8574: Time report: date range fields not enabled when using the calendar popup
-* Defect #10642: Nested textile ol/ul lists generate invalid HTML
-* Defect #10668: RSS key is generated twice when user is not reloaded
-* Defect #10669: Token.destroy_expired should not delete API tokens
-* Defect #10675: "Submit and continue" is broken
-* Defect #10711: User cannot change account details with "Login has already been taken" error
-* Feature #10664: Unsubscribe Own User Account
-* Patch #10693: German Translation Update
-
-== 2012-04-14 v1.4.0
-
-* Defect #2719: Increase username length limit from 30 to 60
-* Defect #3087: Revision referring to issues across all projects
-* Defect #4824: Unable to connect (can't convert Net::LDAP::LdapError into String)
-* Defect #5058: reminder mails are not sent when delivery_method is :async_smtp
-* Defect #6859: Moving issues to a tracker with different custom fields should let fill these fields
-* Defect #7398: Error when trying to quick create a version with required custom field
-* Defect #7495: Python multiline comments highlighting problem in Repository browser
-* Defect #7826: bigdecimal-segfault-fix.rb must be removed for Oracle
-* Defect #7920: Attempted to update a stale object when copying a project
-* Defect #8857: Git: Too long in fetching repositories after upgrade from 1.1 or new branch at first time
-* Defect #9472: The git scm module causes an excess amount of DB traffic.
-* Defect #9685: Adding multiple times the same related issue relation is possible
-* Defect #9798: Release 1.3.0 does not detect rubytree under ruby 1.9.3p0 / rails 2.3.14
-* Defect #9978: Japanese "permission_add_issue_watchers" is wrong
-* Defect #10006: Email reminders are sent for closed issues
-* Defect #10150: CSV export and spent time: rounding issue
-* Defect #10168: CSV export breaks custom columns
-* Defect #10181: Issue context menu and bulk edit form show irrelevant statuses
-* Defect #10198: message_id regex in pop3.rb only recognizes Message-ID header (not Message-Id)
-* Defect #10251: Description diff link in note details is relative when received by email
-* Defect #10272: Ruby 1.9.3: "incompatible character encoding" with LDAP auth
-* Defect #10275: Message object not passed to wiki macros for head topic and in preview edit mode
-* Defect #10334: Full name is not unquoted when creating users from emails
-* Defect #10410: [Localization] Grammar issue of Simplified Chinese in zh.yml
-* Defect #10442: Ruby 1.9.3 Time Zone setting Internal error.
-* Defect #10467: Confusing behavior while moving issue to a project with disabled Issues module
-* Defect #10575: Uploading of attachments which filename contains non-ASCII chars fails with Ruby 1.9
-* Defect #10590: WikiContent::Version#text return string with #<Encoding:ASCII-8BIT> when uncompressed
-* Defect #10593: Error: 'incompatible character encodings: UTF-8 and ASCII-8BIT' (old annoing issue) on ruby-1.9.3
-* Defect #10600: Watchers search generates an Internal error
-* Defect #10605: Bulk edit selected issues does not allow selection of blank values for custom fields
-* Defect #10619: When changing status before tracker, it shows improper status
-* Feature #779: Multiple SCM per project
-* Feature #971: Add "Spent time" column to query
-* Feature #1060: Add a LDAP-filter using external auth sources
-* Feature #1102: Shortcut for assigning an issue to me
-* Feature #1189: Multiselect custom fields
-* Feature #1363: Allow underscores in project identifiers
-* Feature #1913: LDAP - authenticate as user
-* Feature #1972: Attachments for News
-* Feature #2009: Manually add related revisions
-* Feature #2323: Workflow permissions for administrators
-* Feature #2416: {background:color} doesn't work in text formatting
-* Feature #2694: Notification on loosing assignment
-* Feature #2715: "Magic links" to notes
-* Feature #2850: Add next/previous navigation to issue
-* Feature #3055: Option to copy attachments when copying an issue
-* Feature #3108: set parent automatically for new pages
-* Feature #3463: Export all wiki pages to PDF
-* Feature #4050: Ruby 1.9 support
-* Feature #4769: Ability to move an issue to a different project from the update form
-* Feature #4774: Change the hyperlink for file attachment to view and download
-* Feature #5159: Ability to add Non-Member watchers to the watch list
-* Feature #5638: Use Bundler (Gemfile) for gem management
-* Feature #5643: Add X-Redmine-Sender header to email notifications
-* Feature #6296: Bulk-edit custom fields through context menu
-* Feature #6386: Issue mail should render the HTML version of the issue details
-* Feature #6449: Edit a wiki page's parent on the edit page
-* Feature #6555: Double-click on "Submit" and "Save" buttons should not send two requests to server
-* Feature #7361: Highlight active query in the side bar
-* Feature #7420: Rest API for projects members
-* Feature #7603: Please make editing issues more obvious than "Change properties (More)"
-* Feature #8171: Adding attachments through the REST API
-* Feature #8691: Better handling of issue update conflict
-* Feature #9803: Change project through REST API issue update
-* Feature #9923: User type custom fields should be filterable by "Me".
-* Feature #9985: Group time report by the Status field
-* Feature #9995: Time entries insertion, "Create and continue" button
-* Feature #10020: Enable global time logging at /time_entries/new
-* Feature #10042: Bulk change private flag
-* Feature #10126: Add members of subprojects in the assignee and author filters
-* Feature #10131: Include custom fiels in time entries API responses
-* Feature #10207: Git: use default branch from HEAD
-* Feature #10208: Estonian translation
-* Feature #10253: Better handling of attachments when validation fails
-* Feature #10350: Bulk copy should allow for changing the target version
-* Feature #10607: Ignore out-of-office incoming emails
-* Feature #10635: Adding time like "123 Min" is invalid
-* Patch #9998: Make attachement "Optional Description" less wide
-* Patch #10066: i18n not working with russian gem
-* Patch #10128: Disable IE 8 compatibility mode to fix wrong div.autoscroll scroll bar behaviour 
-* Patch #10155: Russian translation changed
-* Patch #10464: Enhanced PDF output for Issues list
-* Patch #10470: Efficiently process new git revisions in a single batch
-* Patch #10513: Dutch translation improvement
-
-== 2012-04-14 v1.3.3
-
-* Defect #10505: Error when exporting to PDF with NoMethodError (undefined method `downcase' for nil:NilClass)
-* Defect #10554: Defect symbols when exporting tasks in pdf
-* Defect #10564: Unable to change locked, sticky flags and board when editing a message
-* Defect #10591: Dutch "label_file_added" translation is wrong
-* Defect #10622: "Default administrator account changed" is always true
-* Patch #10555: rake redmine:send_reminders aborted if issue assigned to group
-* Patch #10611: Simplified Chinese translations for 1.3-stable
-
-== 2012-03-11 v1.3.2
-
-* Defect #8194: {{toc}} uses identical anchors for subsections with the same name
-* Defect #9143: Partial diff comparison should be done on actual code, not on html
-* Defect #9523: {{toc}} does not display headers with @ code markup
-* Defect #9815: Release 1.3.0 does not detect rubytree with rubgems 1.8
-* Defect #10053: undefined method `<=>' for nil:NilClass when accessing the settings of a project
-* Defect #10135: ActionView::TemplateError (can't convert Fixnum into String)
-* Defect #10193: Unappropriate icons in highlighted code block
-* Defect #10199: No wiki section edit when title contains code
-* Defect #10218: Error when creating a project with a version custom field
-* Defect #10241: "get version by ID" fails with "401 not authorized" error when using API access key
-* Defect #10284: Note added by commit from a subproject does not contain project identifier
-* Defect #10374: User list is empty when adding users to project / group if remaining users are added late
-* Defect #10390: Mass assignment security vulnerability
-* Patch #8413: Confirmation message before deleting a relationship
-* Patch #10160: Bulgarian translation (r8777)
-* Patch #10242: Migrate Redmine.pm from Digest::Sha1 to Digest::Sha
-* Patch #10258: Italian translation for 1.3-stable
-
-== 2012-02-06 v1.3.1
-
-* Defect #9775: app/views/repository/_revision_graph.html.erb sets window.onload directly..
-* Defect #9792: Ruby 1.9: [v1.3.0] Error: incompatible character encodings for it translation on Calendar page
-* Defect #9793: Bad spacing between numbered list and heading (recently broken).
-* Defect #9795: Unrelated error message when creating a group with an invalid name
-* Defect #9832: Revision graph height should depend on height of rows in revisions table
-* Defect #9937: Repository settings are not saved when all SCM are disabled
-* Defect #9961: Ukrainian "default_tracker_bug" is wrong
-* Defect #10013: Rest API - Create Version -> Internal server error 500
-* Defect #10115: Javascript error - Can't attach more than 1 file on IE 6 and 7
-* Defect #10130: Broken italic text style in edited comment preview
-* Defect #10152: Attachment diff type is not saved in user preference
-* Feature #9943: Arabic translation
-* Patch #9874: pt-BR translation updates
-* Patch #9922: Spanish translation updated
-* Patch #10137: Korean language file ko.yml updated to Redmine 1.3.0
-
-== 2011-12-10 v1.3.0
-
-* Defect #2109: Context menu is being submitted twice per right click
-* Defect #7717: MailHandler user creation for unknown_user impossible due to diverging length-limits of login and email fields
-* Defect #7917: Creating users via email fails if user real name containes special chars
-* Defect #7966: MailHandler does not include JournalDetail for attached files
-* Defect #8368: Bad decimal separator in time entry CSV
-* Defect #8371: MySQL error when filtering a custom field using the REST api
-* Defect #8549: Export CSV has character encoding error
-* Defect #8573: Do not show inactive Enumerations where not needed
-* Defect #8611: rake/rdoctask is deprecated
-* Defect #8751: Email notification: bug, when number of recipients more then 8
-* Defect #8894: Private issues - make it more obvious in the UI?
-* Defect #8994: Hardcoded French string "anonyme"
-* Defect #9043: Hardcoded string "diff" in Wiki#show and Repositories_Helper
-* Defect #9051: wrong "text_issue_added" in russian translation.
-* Defect #9108: Custom query not saving status filter
-* Defect #9252: Regression: application title escaped 2 times
-* Defect #9264: Bad Portuguese translation
-* Defect #9470: News list is missing Avatars
-* Defect #9471: Inline markup broken in Wiki link labels
-* Defect #9489: Label all input field and control tags
-* Defect #9534: Precedence: bulk email header is non standard and discouraged
-* Defect #9540: Issue filter by assigned_to_role is not project specific
-* Defect #9619: Time zone ignored when logging time while editing ticket
-* Defect #9638: Inconsistent image filename extensions
-* Defect #9669: Issue list doesn't sort assignees/authors regarding user display format
-* Defect #9672: Message-quoting in forums module broken
-* Defect #9719: Filtering by numeric custom field types broken after update to master
-* Defect #9724: Can't remote add new categories
-* Defect #9738: Setting of cross-project custom query is not remembered inside project
-* Defect #9748: Error about configuration.yml validness should mention file path
-* Feature #69: Textilized description in PDF
-* Feature #401: Add pdf export for WIKI page
-* Feature #1567: Make author column sortable and groupable
-* Feature #2222: Single section edit.
-* Feature #2269: Default issue start date should become configurable.
-* Feature #2371: character encoding for attachment file
-* Feature #2964: Ability to assign issues to groups
-* Feature #3033: Bug Reporting: Using "Create and continue" should show bug id of saved bug
-* Feature #3261: support attachment images in PDF export
-* Feature #4264: Update CodeRay to 1.0 final
-* Feature #4324: Redmine renames my files, it shouldn't.
-* Feature #4729: Add Date-Based Filters for Issues List
-* Feature #4742: CSV export: option to export selected or all columns
-* Feature #4976: Allow rdm-mailhandler to read the API key from a file
-* Feature #5501: Git: Mercurial: Adding visual merge/branch history to repository view
-* Feature #5634: Export issue to PDF does not include Subtasks and Related Issues
-* Feature #5670: Cancel option for file upload
-* Feature #5737: Custom Queries available through the REST Api
-* Feature #6180: Searchable custom fields do not provide adequate operators
-* Feature #6954: Filter from date to date
-* Feature #7180: List of statuses in REST API
-* Feature #7181: List of trackers in REST API
-* Feature #7366: REST API for Issue Relations
-* Feature #7403: REST API for Versions
-* Feature #7671: REST API for reading attachments
-* Feature #7832: Ability to assign issue categories to groups
-* Feature #8420: Consider removing #7013 workaround
-* Feature #9196: Improve logging in MailHandler when user creation fails
-* Feature #9496: Adds an option in mailhandler to disable server certificate verification
-* Feature #9553: CRUD operations for "Issue categories" in REST API
-* Feature #9593: HTML title should be reordered
-* Feature #9600: Wiki links for news and forums
-* Feature #9607: Filter for issues without start date (or any another field based on date type)
-* Feature #9609: Upgrade to Rails 2.3.14
-* Feature #9612: "side by side" and "inline" patch view for attachments
-* Feature #9667: Check attachment size before upload
-* Feature #9690: Link in notification pointing to the actual update
-* Feature #9720: Add note number for single issue's PDF
-* Patch #8617: Indent subject of subtask ticket in exported issues PDF
-* Patch #8778: Traditional Chinese 'issue' translation change
-* Patch #9053: Fix up Russian translation
-* Patch #9129: Improve wording of Git repository note at project setting
-* Patch #9148: Better handling of field_due_date italian translation
-* Patch #9273: Fix typos in russian localization
-* Patch #9484: Limit SCM annotate to text files under the maximum file size for viewing
-* Patch #9659: Indexing rows in auth_sources/index view
-* Patch #9692: Fix Textilized description in PDF for CodeRay
-
-== 2011-12-10 v1.2.3
-
-* Defect #8707: Reposman: wrong constant name
-* Defect #8809: Table in timelog report overflows
-* Defect #9055: Version files in Files module cannot be downloaded if issue tracking is disabled
-* Defect #9137: db:encrypt fails to handle repositories with blank password
-* Defect #9394: Custom date field only validating on regex and not a valid date
-* Defect #9405: Any user with :log_time permission can edit time entries via context menu
-* Defect #9448: The attached images are not shown in documents
-* Defect #9520: Copied private query not visible after project copy
-* Defect #9552: Error when reading ciphered text from the database without cipher key configured
-* Defect #9566: Redmine.pm considers all projects private when login_required is enabled
-* Defect #9567: Redmine.pm potential security issue with cache credential enabled and subversion
-* Defect #9577: Deleting a subtasks doesn't update parent's rgt & lft values
-* Defect #9597: Broken version links in wiki annotate history
-* Defect #9682: Wiki HTML Export only useful when Access history is accessible
-* Defect #9737: Custom values deleted before issue submit
-* Defect #9741: calendar-hr.js (Croatian) is not UTF-8
-* Patch #9558: Simplified Chinese translation for 1.2.2 updated
-* Patch #9695: Bulgarian translation (r7942)
-
-== 2011-11-11 v1.2.2
-
-* Defect #3276: Incorrect handling of anchors in Wiki to HTML export
-* Defect #7215: Wiki formatting mangles links to internal headers
-* Defect #7613: Generated test instances may share the same attribute value object
-* Defect #8411: Can't remove "Project" column on custom query
-* Defect #8615: Custom 'version' fields don't show shared versions
-* Defect #8633: Pagination counts non visible issues
-* Defect #8651: Email attachments are not added to issues any more in v1.2
-* Defect #8825: JRuby + Windows: SCMs do not work on Redmine 1.2
-* Defect #8836: Additional workflow transitions not available when set to both author and assignee
-* Defect #8865: Custom field regular expression is not validated
-* Defect #8880: Error deleting issue with grandchild
-* Defect #8884: Assignee is cleared when updating issue with locked assignee
-* Defect #8892: Unused fonts in rfpdf plugin folder
-* Defect #9161: pt-BR field_warn_on_leaving_unsaved has a small gramatical error
-* Defect #9308: Search fails when a role haven't "view wiki" permission
-* Defect #9465: Mercurial: can't browse named branch below Mercurial 1.5
-
-== 2011-07-11 v1.2.1
-
-* Defect #5089: i18N error on truncated revision diff view
-* Defect #7501: Search options get lost after clicking on a specific result type
-* Defect #8229: "project.xml" response does not include the parent ID
-* Defect #8449: Wiki annotated page does not display author of version 1
-* Defect #8467: Missing german translation - Warn me when leaving a page with unsaved text
-* Defect #8468: No warning when leaving page with unsaved text that has not lost focus
-* Defect #8472: Private checkbox ignored on issue creation with "Set own issues public or private" permission
-* Defect #8510: JRuby: Can't open administrator panel if scm command is not available
-* Defect #8512: Syntax highlighter on Welcome page
-* Defect #8554: Translation missing error on custom field validation
-* Defect #8565: JRuby: Japanese PDF export error
-* Defect #8566: Exported PDF UTF-8 Vietnamese not correct
-* Defect #8569: JRuby: PDF export error with TypeError
-* Defect #8576: Missing german translation - different things
-* Defect #8616: Circular relations
-* Defect #8646: Russian translation "label_follows" and "label_follows" are wrong
-* Defect #8712: False 'Description updated' journal details messages
-* Defect #8729: Not-public queries are not private
-* Defect #8737: Broken line of long issue description on issue PDF.
-* Defect #8738: Missing revision number/id of associated revisions on issue PDF
-* Defect #8739: Workflow copy does not copy advanced workflow settings
-* Defect #8759: Setting issue attributes from mail should be case-insensitive
-* Defect #8777: Mercurial: Not able to Resetting Redmine project respository
-
-== 2011-05-30 v1.2.0
-
-* Defect #61: Broken character encoding in pdf export
-* Defect #1965: Redmine is not Tab Safe
-* Defect #2274: Filesystem Repository path encoding of non UTF-8 characters
-* Defect #2664: Mercurial: Repository path encoding of non UTF-8 characters
-* Defect #3421: Mercurial reads files from working dir instead of changesets
-* Defect #3462: CVS: Repository path encoding of non UTF-8 characters
-* Defect #3715: Login page should not show projects link and search box if authentication is required
-* Defect #3724: Mercurial repositories display revision ID instead of changeset ID
-* Defect #3761: Most recent CVS revisions are missing in "revisions" view
-* Defect #4270: CVS Repository view in Project doesn't show Author, Revision, Comment
-* Defect #5138: Don't use Ajax for pagination
-* Defect #5152: Cannot use certain characters for user and role names.
-* Defect #5251: Git: Repository path encoding of non UTF-8 characters
-* Defect #5373: Translation missing when adding invalid watchers
-* Defect #5817: Shared versions not shown in subproject's gantt chart
-* Defect #6013: git tab,browsing, very slow -- even after first time
-* Defect #6148: Quoting, newlines, and nightmares...
-* Defect #6256: Redmine considers non ASCII and UTF-16 text files as binary in SCM
-* Defect #6476: Subproject's issues are not shown in the subproject's gantt
-* Defect #6496: Remove i18n 0.3.x/0.4.x hack for Rails 2.3.5
-* Defect #6562: Context-menu deletion of issues deletes all subtasks too without explicit prompt
-* Defect #6604: Issues targeted at parent project versions' are not shown on gantt chart
-* Defect #6706: Resolving issues with the commit message produces the wrong comment with CVS
-* Defect #6901: Copy/Move an issue does not give any history of who actually did the action.
-* Defect #6905: Specific heading-content breaks CSS
-* Defect #7000: Project filter not applied on versions in Gantt chart
-* Defect #7097: Starting day of week cannot be set to Saturday
-* Defect #7114: New gantt doesn't display some projects
-* Defect #7146: Git adapter lost commits before 7 days from database latest changeset
-* Defect #7218: Date range error on issue query
-* Defect #7257: "Issues by" version links bad criterias
-* Defect #7279: CSS class ".icon-home" is not used.
-* Defect #7320: circular dependency >2 issues
-* Defect #7352: Filters not working in Gantt charts
-* Defect #7367: Receiving pop3 email should not output debug messages
-* Defect #7373: Error with PDF output and ruby 1.9.2
-* Defect #7379: Remove extraneous hidden_field on wiki history
-* Defect #7516: Redmine does not work with RubyGems 1.5.0
-* Defect #7518: Mercurial diff can be wrong if the previous changeset isn't the parent
-* Defect #7581: Not including a spent time value on the main issue update screen causes silent data loss
-* Defect #7582: hiding form pages from search engines
-* Defect #7597: Subversion and Mercurial log have the possibility to miss encoding
-* Defect #7604: ActionView::TemplateError (undefined method `name' for nil:NilClass)
-* Defect #7605: Using custom queries always redirects to "Issues" tab
-* Defect #7615: CVS diffs do not handle new files properly
-* Defect #7618: SCM diffs do not handle one line new files properly
-* Defect #7639: Some date fields do not have requested format.
-* Defect #7657: Wrong commit range in git log command on Windows
-* Defect #7818: Wiki pages don't use the local timezone to display the "Updated ? hours ago" mouseover
-* Defect #7821: Git "previous" and "next" revisions are incorrect
-* Defect #7827: CVS: Age column on repository view is off by timezone delta
-* Defect #7843: Add a relation between issues = explicit login window ! (basic authentication popup is prompted on AJAX request)
-* Defect #8011: {{toc}} does not display headlines with inline code markup
-* Defect #8029: List of users for adding to a group may be empty if 100 first users have been added
-* Defect #8064: Text custom fields do not wrap on the issue list
-* Defect #8071: Watching a subtask from the context menu updates main issue watch link
-* Defect #8072: Two untranslatable default role names
-* Defect #8075: Some "notifiable" names are not i18n-enabled
-* Defect #8081: GIT: Commits missing when user has the "decorate" git option enabled
-* Defect #8088: Colorful indentation of subprojects must be on right in RTL locales
-* Defect #8239: notes field is not propagated during issue copy
-* Defect #8356: GET /time_entries.xml ignores limit/offset parameters
-* Defect #8432: Private issues information shows up on Activity page for unauthorized users
-* Feature #746: Versioned issue descriptions
-* Feature #1067: Differentiate public/private saved queries in the sidebar
-* Feature #1236: Make destination folder for attachment uploads configurable
-* Feature #1735: Per project repository log encoding setting
-* Feature #1763: Autologin-cookie should be configurable
-* Feature #1981: display mercurial tags
-* Feature #2074: Sending email notifications when comments are added in the news section
-* Feature #2096: Custom fields referencing system tables (users and versions)
-* Feature #2732: Allow additional workflow transitions for author and assignee
-* Feature #2910: Warning on leaving edited issue/wiki page without saving
-* Feature #3396: Git: use --encoding=UTF-8 in "git log"
-* Feature #4273: SCM command availability automatic check in administration panel
-* Feature #4477: Use mime types in downloading from repository
-* Feature #5518: Graceful fallback for "missing translation" needed
-* Feature #5520: Text format buttons and preview link missing when editing comment
-* Feature #5831: Parent Task to Issue Bulk Edit
-* Feature #6887: Upgrade to Rails 2.3.11
-* Feature #7139: Highlight changes inside diff lines
-* Feature #7236: Collapse All for Groups
-* Feature #7246: Handle "named branch" for mercurial
-* Feature #7296: Ability for admin to delete users
-* Feature #7318: Add user agent to Redmine Mailhandler
-* Feature #7408: Add an application configuration file
-* Feature #7409: Cross project Redmine links
-* Feature #7410: Add salt to user passwords
-* Feature #7411: Option to cipher LDAP ans SCM passwords stored in the database
-* Feature #7412: Add an issue visibility level to each role
-* Feature #7414: Private issues
-* Feature #7517: Configurable path of executable for scm adapters
-* Feature #7640: Add "mystery man" gravatar to options
-* Feature #7858: RubyGems 1.6 support
-* Feature #7893: Group filter on the users list
-* Feature #7899: Box for editing comments should open with the formatting toolbar
-* Feature #7921: issues by pulldown should have 'status' option
-* Feature #7996: Bulk edit and context menu for time entries
-* Feature #8006: Right click context menu for Related Issues
-* Feature #8209: I18n YAML files not parsable with psych yaml library
-* Feature #8345: Link to user profile from account page
-* Feature #8365: Git: per project setting to report last commit or not in repository tree
-* Patch #5148: metaKey not handled in issues selection
-* Patch #5629: Wrap text fields properly in PDF
-* Patch #7418: Redmine Persian Translation
-* Patch #8295: Wrap title fields properly in PDF
-* Patch #8310: fixes automatic line break problem with TCPDF
-* Patch #8312: Switch to TCPDF from FPDF for PDF export
-
-== 2011-04-29 v1.1.3
-
-* Defect #5773: Email reminders are sent to locked users
-* Defect #6590: Wrong file list link in email notification on new file upload
-* Defect #7589: Wiki page with backslash in title can not be found
-* Defect #7785: Mailhandler keywords are not removed when updating issues
-* Defect #7794: Internal server error on formatting an issue as a PDF in Japanese
-* Defect #7838: Gantt- Issues does not show up in green when start and end date are the same
-* Defect #7846: Headers (h1, etc.) containing backslash followed by a digit are not displayed correctly
-* Defect #7875: CSV export separators in polish locale (pl.yml)
-* Defect #7890: Internal server error when referencing an issue without project in commit message
-* Defect #7904: Subprojects not properly deleted when deleting a parent project
-* Defect #7939: Simultaneous Wiki Updates Cause Internal Error
-* Defect #7951: Atom links broken on wiki index
-* Defect #7954: IE 9 can not select issues, does not display context menu
-* Defect #7985: Trying to do a bulk edit results in "Internal Error"
-* Defect #8003: Error raised by reposman.rb under Windows server 2003
-* Defect #8012: Wrong selection of modules when adding new project after validation error
-* Defect #8038: Associated Revisions OL/LI items are not styled properly in issue view
-* Defect #8067: CSV exporting in Italian locale
-* Defect #8235: bulk edit issues and copy issues error in es, gl and ca locales
-* Defect #8244: selected modules are not activated when copying a project
-* Patch #7278: Update Simplified Chinese translation to 1.1
-* Patch #7390: Fixes in Czech localization
-* Patch #7963: Reminder email: Link for show all issues does not sort
-
-== 2011-03-07 v1.1.2
-
-* Defect #3132: Bulk editing menu non-functional in Opera browser
-* Defect #6090: Most binary files become corrupted when downloading from CVS repository browser when Redmine is running on a Windows server
-* Defect #7280: Issues subjects wrap in Gantt
-* Defect #7288: Non ASCII filename downloaded from repo is broken on Internet Explorer.
-* Defect #7317: Gantt tab gives internal error due to nil avatar icon
-* Defect #7497: Aptana Studio .project file added to version 1.1.1-stable
-* Defect #7611: Workflow summary shows X icon for workflow with exactly 1 status transition
-* Defect #7625: Syntax highlighting unavailable from board new topic or topic edit preview
-* Defect #7630: Spent time in commits not recognized
-* Defect #7656: MySQL SQL Syntax Error when filtering issues by Assignee's Group
-* Defect #7718: Minutes logged in commit message are converted to hours
-* Defect #7763: Email notification are sent to watchers even if 'No events' setting is chosen
-* Feature #7608: Add "retro" gravatars
-* Patch #7598: Extensible MailHandler
-* Patch #7795: Internal server error at journals#index with custom fields
-
-== 2011-01-30 v1.1.1
-
-* Defect #4899: Redmine fails to list files for darcs repository
-* Defect #7245: Wiki fails to find pages with cyrillic characters using postgresql
-* Defect #7256: redmine/public/.htaccess must be moved for non-fastcgi installs/upgrades
-* Defect #7258: Automatic spent time logging does not work properly with SQLite3
-* Defect #7259: Released 1.1.0 uses "devel" label inside admin information
-* Defect #7265: "Loading..." icon does not disappear after add project member
-* Defect #7266: Test test_due_date_distance_in_words fail due to undefined locale
-* Defect #7274: CSV value separator in dutch locale
-* Defect #7277: Enabling gravatas causes usernames to overlap first name field in user list
-* Defect #7294: "Notifiy for only project I select" is not available anymore in 1.1.0
-* Defect #7307: HTTP 500 error on query for empty revision
-* Defect #7313: Label not translated in french in Settings/Email Notification tab
-* Defect #7329: <code class="javascript"> with long strings may hang server
-* Defect #7337: My page french translation
-* Defect #7348: French Translation of "Connection"
-* Defect #7385: Error when viewing an issue which was related to a deleted subtask
-* Defect #7386: NoMethodError on pdf export
-* Defect #7415: Darcs adapter recognizes new files as modified files above Darcs 2.4
-* Defect #7421: no email sent with 'Notifiy for any event on the selected projects only'
-* Feature #5344: Update to latest CodeRay 0.9.x
-
-== 2011-01-09 v1.1.0
-
-* Defect #2038: Italics in wiki headers show-up wrong in the toc
-* Defect #3449: Redmine Takes Too Long On Large Mercurial Repository
-* Defect #3567: Sorting for changesets might go wrong on Mercurial repos
-* Defect #3707: {{toc}} doesn't work with {{include}}
-* Defect #5096: Redmine hangs up while browsing Git repository
-* Defect #6000: Safe Attributes prevents plugin extension of Issue model...
-* Defect #6064: Modules not assigned to projects created via API
-* Defect #6110: MailHandler should allow updating Issue Priority and Custom fields
-* Defect #6136: JSON API holds less information than XML API
-* Defect #6345: xml used by rest API is invalid
-* Defect #6348: Gantt chart PDF rendering errors
-* Defect #6403: Updating an issue with custom fields fails
-* Defect #6467: "Member of role", "Member of group" filter not work correctly
-* Defect #6473: New gantt broken after clearing issue filters
-* Defect #6541: Email notifications send to everybody
-* Defect #6549: Notification settings not migrated properly
-* Defect #6591: Acronyms must have a minimum of three characters
-* Defect #6674: Delete time log broken after changes to REST
-* Defect #6681: Mercurial, Bazaar and Darcs auto close issue text should be commit id instead of revision number
-* Defect #6724: Wiki uploads does not work anymore (SVN 4266)
-* Defect #6746: Wiki links are broken on Activity page
-* Defect #6747: Wiki diff does not work since r4265
-* Defect #6763: New gantt charts: subject displayed twice on issues
-* Defect #6826: Clicking "Add" twice creates duplicate member record
-* Defect #6844: Unchecking status filter on the issue list has no effect
-* Defect #6895: Wrong Polish translation of "blocks"
-* Defect #6943: Migration from boolean to varchar fails on PostgreSQL 8.1
-* Defect #7064: Mercurial adapter does not recognize non alphabetic nor numeric in UTF-8 copied files
-* Defect #7128: New gantt chart does not render subtasks under parent task
-* Defect #7135: paging mechanism returns the same last page forever
-* Defect #7188: Activity page not refreshed when changing language
-* Defect #7195: Apply CLI-supplied defaults for incoming mail only to new issues not replies
-* Defect #7197: Tracker reset to default when replying to an issue email
-* Defect #7213: Copy project does not copy all roles and permissions
-* Defect #7225: Project settings: Trackers & Custom fields only relevant if module Issue tracking is active
-* Feature #630: Allow non-unique names for projects
-* Feature #1738: Add a "Visible" flag to project/user custom fields
-* Feature #2803: Support for Javascript in Themes
-* Feature #2852: Clean Incoming Email of quoted text "----- Reply above this line ------"
-* Feature #2995: Improve error message when trying to access an archived project
-* Feature #3170: Autocomplete issue relations on subject
-* Feature #3503: Administrator Be Able To Modify Email settings Of Users
-* Feature #4155: Automatic spent time logging from commit messages
-* Feature #5136: Parent select on Wiki rename page
-* Feature #5338: Descendants (subtasks) should be available via REST API
-* Feature #5494: Wiki TOC should display heading from level 4
-* Feature #5594: Improve MailHandler's keyword handling
-* Feature #5622: Allow version to be set via incoming email
-* Feature #5712: Reload themes
-* Feature #5869: Issue filters by Group and Role
-* Feature #6092: Truncate Git revision labels in Activity page/feed and allow configurable length
-* Feature #6112: Accept localized keywords when receiving emails
-* Feature #6140: REST issues response with issue count limit and offset
-* Feature #6260: REST API for Users
-* Feature #6276: Gantt Chart rewrite
-* Feature #6446: Remove length limits on project identifier and name
-* Feature #6628: Improvements in truncate email
-* Feature #6779: Project JSON API
-* Feature #6823: REST API for time tracker.
-* Feature #7072: REST API for news
-* Feature #7111: Expose more detail on journal entries
-* Feature #7141: REST API: get information about current user
-* Patch #4807: Allow to set the done_ratio field with the incoming mail system
-* Patch #5441: Initialize TimeEntry attributes with params[:time_entry]
-* Patch #6762: Use GET instead of POST to retrieve context_menu
-* Patch #7160: French translation ofr "not_a_date" is missing
-* Patch #7212: Missing remove_index in AddUniqueIndexOnMembers down migration
-
-
-== 2010-12-23 v1.0.5
-
-* #6656: Mercurial adapter loses seconds of commit times
-* #6996: Migration trac(sqlite3) -> redmine(postgresql) doesnt escape ' char
-* #7013: v-1.0.4 trunk - see {{count}} in page display rather than value
-* #7016: redundant 'field_start_date' in ja.yml
-* #7018: 'undefined method `reschedule_after' for nil:NilClass' on new issues
-* #7024: E-mail notifications about Wiki changes.
-* #7033: 'class' attribute of <pre> tag shouldn't be truncate
-* #7035: CSV value separator in russian
-* #7122: Issue-description Quote-button missing
-* #7144: custom queries making use of deleted custom fields cause a 500 error
-* #7162: Multiply defined label in french translation
-
-== 2010-11-28 v1.0.4
-
-* #5324: Git not working if color.ui is enabled
-* #6447: Issues API doesn't allow full key auth for all actions
-* #6457: Edit User group problem
-* #6575: start date being filled with current date even when blank value is submitted
-* #6740: Max attachment size, incorrect usage of 'KB'
-* #6760: Select box sorted by ID instead of name in Issue Category
-* #6766: Changing target version name can cause an internal error
-* #6784: Redmine not working with i18n gem 0.4.2
-* #6839: Hardcoded absolute links in my/page_layout
-* #6841: Projects API doesn't allow full key auth for all actions
-* #6860: svn: Write error: Broken pipe when browsing repository
-* #6874: API should return XML description when creating a project
-* #6932: submitting wrong parent task input creates a 500 error
-* #6966: Records of Forums are remained, deleting project
-* #6990: Layout problem in workflow overview
-* #5117: mercurial_adapter should ensure the right LANG environment variable
-* #6782: Traditional Chinese language file (to r4352)
-* #6783: Swedish Translation for r4352
-* #6804: Bugfix: spelling fixes
-* #6814: Japanese Translation for r4362
-* #6948: Bulgarian translation
-* #6973: Update es.yml
-
-== 2010-10-31 v1.0.3
-
-* #4065: Redmine.pm doesn't work with LDAPS and a non-standard port
-* #4416: Link from version details page to edit the wiki.
-* #5484: Add new issue as subtask to an existing ticket
-* #5948: Update help/wiki_syntax_detailed.html with more link options
-* #6494: Typo in pt_BR translation for 1.0.2
-* #6508: Japanese translation update
-* #6509: Localization pt-PT (new strings)
-* #6511: Rake task to test email
-* #6525: Traditional Chinese language file (to r4225)
-* #6536: Patch for swedish translation
-* #6548: Rake tasks to add/remove i18n strings
-* #6569: Updated Hebrew translation
-* #6570: Japanese Translation for r4231
-* #6596: pt-BR translation updates
-* #6629: Change field-name of issues start date
-* #6669: Bulgarian translation
-* #6731: Macedonian translation fix
-* #6732: Japanese Translation for r4287
-* #6735: Add user-agent to reposman
-* #6736: Traditional Chinese language file (to r4288)
-* #6739: Swedish Translation for r4288
-* #6765: Traditional Chinese language file (to r4302)
-* Fixed #5324: Git not working if color.ui is enabled
-* Fixed #5652: Bad URL parsing in the wiki when it ends with right-angle-bracket(greater-than mark).
-* Fixed #5803: Precedes/Follows Relationships Broke
-* Fixed #6435: Links to wikipages bound to versions do not respect version-sharing in Settings -> Versions
-* Fixed #6438: Autologin cannot be disabled again once it's enabled
-* Fixed #6513: "Move" and "Copy" are not displayed when deployed in subdirectory
-* Fixed #6521: Tooltip/label for user "search-refinment" field on group/project member list
-* Fixed #6563: i18n-issues on calendar view
-* Fixed #6598: Wrong caption for button_create_and_continue in German language file
-* Fixed #6607: Unclear caption for german button_update
-* Fixed #6612: SortHelper missing from CalendarsController
-* Fixed #6740: Max attachment size, incorrect usage of 'KB'
-* Fixed #6750: ActionView::TemplateError (undefined method `empty?' for nil:NilClass) on line #12 of app/views/context_menus/issues.html.erb:
-
-== 2010-09-26 v1.0.2
-
-* #2285: issue-refinement: pressing enter should result to an "apply"
-* #3411: Allow mass status update trough context menu
-* #5929: https-enabled gravatars when called over https
-* #6189: Japanese Translation for r4011
-* #6197: Traditional Chinese language file (to r4036)
-* #6198: Updated german translation
-* #6208: Macedonian translation
-* #6210: Swedish Translation for r4039
-* #6248: nl translation update for r4050
-* #6263: Catalan translation update
-* #6275: After submitting a related issue, the Issue field should be re-focused
-* #6289: Checkboxes in issues list shouldn't be displayed when printing
-* #6290: Make journals theming easier
-* #6291: User#allowed_to? is not tested
-* #6306: Traditional Chinese language file (to r4061)
-* #6307: Korean translation update for 4066(4061)
-* #6316: pt_BR update
-* #6339: SERBIAN Updated
-* #6358: Updated Polish translation
-* #6363: Japanese Translation for r4080
-* #6365: Traditional Chinese language file (to r4081)
-* #6382: Issue PDF export variable usage
-* #6428: Interim solution for i18n >= 0.4
-* #6441: Japanese Translation for r4162
-* #6451: Traditional Chinese language file (to r4167)
-* #6465: Japanese Translation for r4171
-* #6466: Traditional Chinese language file (to r4171)
-* #6490: pt-BR translation for 1.0.2
-* Fixed #3935: stylesheet_link_tag with plugin doesn't take into account relative_url_root
-* Fixed #4998: Global issue list's context menu has enabled options for parent menus but there are no valid selections
-* Fixed #5170: Done ratio can not revert to 0% if status is used for done ratio
-* Fixed #5608: broken with i18n 0.4.0
-* Fixed #6054: Error 500 on filenames with whitespace in git reposities
-* Fixed #6135: Default logger configuration grows without bound.
-* Fixed #6191: Deletion of a main task deletes all subtasks
-* Fixed #6195: Missing move issues between projects
-* Fixed #6242: can't switch between inline and side-by-side diff
-* Fixed #6249: Create and continue returns 404
-* Fixed #6267: changing the authentication mode from ldap to internal with setting the password
-* Fixed #6270: diff coderay malformed in the "news" page
-* Fixed #6278: missing "cant_link_an_issue_with_a_descendant"from locale files
-* Fixed #6333: Create and continue results in a 404 Error
-* Fixed #6346: Age column on repository view is skewed for git, probably CVS too
-* Fixed #6351: Context menu on roadmap broken
-* Fixed #6388: New Subproject leads to a 404
-* Fixed #6392: Updated/Created links to activity broken
-* Fixed #6413: Error in SQL
-* Fixed #6443: Redirect to project settings after Copying a Project
-* Fixed #6448: Saving a wiki page with no content has a translation missing
-* Fixed #6452: Unhandled exception on creating File
-* Fixed #6471: Typo in label_report in Czech translation
-* Fixed #6479: Changing tracker type will lose watchers
-* Fixed #6499: Files with leading or trailing whitespace are not shown in git.
-
-== 2010-08-22 v1.0.1
-
-* #819: Add a body ID and class to all pages
-* #871: Commit new CSS styles!
-* #3301: Add favicon to base layout
-* #4656: On Issue#show page, clicking on “Add related issue� should focus on the input
-* #4896: Project identifier should be a limited field
-* #5084: Filter all isssues by projects
-* #5477: Replace Test::Unit::TestCase with ActiveSupport::TestCase
-* #5591: 'calendar' action is used with 'issue' controller in issue/sidebar
-* #5735: Traditional Chinese language file (to r3810)
-* #5740: Swedish Translation for r3810
-* #5785: pt-BR translation update
-* #5898: Projects should be displayed as links in users/memberships
-* #5910: Chinese translation to redmine-1.0.0
-* #5912: Translation update for french locale
-* #5962: Hungarian translation update to r3892
-* #5971: Remove falsly applied chrome on revision links
-* #5972: Updated Hebrew translation for 1.0.0
-* #5982: Updated german translation
-* #6008: Move admin_menu to Redmine::MenuManager
-* #6012: RTL layout
-* #6021: Spanish translation 1.0.0-RC
-* #6025: nl translation updated for r3905
-* #6030: Japanese Translation for r3907
-* #6074: sr-CY.yml contains DOS-type newlines (\r\n)
-* #6087: SERBIAN translation updated
-* #6093: Updated italian translation
-* #6142: Swedish Translation for r3940
-* #6153: Move view_calendar and view_gantt to own modules
-* #6169: Add issue status to issue tooltip
-* Fixed #3834: Add a warning when not choosing a member role
-* Fixed #3922: Bad english arround "Assigned to" text in journal entries
-* Fixed #5158: Simplified Chinese language file zh.yml updated to r3608
-* Fixed #5162: translation missing: zh-TW, field_time_entrie
-* Fixed #5297: openid not validated correctly
-* Fixed #5628: Wrong commit range in git log command
-* Fixed #5760: Assigned_to and author filters in "Projects>View all issues" should be based on user's project visibility
-* Fixed #5771: Problem when importing git repository
-* Fixed #5775: ldap authentication in admin menu should have an icon
-* Fixed #5811: deleting statuses doesnt delete workflow entries
-* Fixed #5834: Emails with trailing spaces incorrectly detected as invalid
-* Fixed #5846: ChangeChangesPathLengthLimit does not remove default for MySQL
-* Fixed #5861: Vertical scrollbar always visible in Wiki "code" blocks in Chrome.
-* Fixed #5883: correct label_project_latest Chinese translation
-* Fixed #5892: Changing status from contextual menu opens the ticket instead
-* Fixed #5904: Global gantt PDF and PNG should display project names
-* Fixed #5925: parent task's priority edit should be disabled through shortcut menu in issues list page
-* Fixed #5935: Add Another file to ticket doesn't work in IE Internet Explorer
-* Fixed #5937: Harmonize french locale "zero" translation with other locales
-* Fixed #5945: Forum message permalinks don't take pagination into account
-* Fixed #5978: Debug code still remains
-* Fixed #6009: When using "English (British)", the repository browser (svn) shows files over 1000 bytes as floating point (2.334355)
-* Fixed #6045: Repository file Diff view sometimes shows more than selected file
-* Fixed #6079: German Translation error in TimeEntryActivity
-* Fixed #6100: User's profile should display all visible projects
-* Fixed #6132: Allow Key based authentication in the Boards atom feed
-* Fixed #6163: Bad CSS class for calendar project menu_item
-* Fixed #6172: Browsing to a missing user's page shows the admin sidebar
-
-== 2010-07-18 v1.0.0 (Release candidate)
-
-* #443: Adds context menu to the roadmap issue lists
-* #443: Subtasking
-* #741: Description preview while editing an issue
-* #1131: Add support for alternate (non-LDAP) authentication
-* #1214: REST API for Issues
-* #1223: File upload on wiki edit form
-* #1755: add "blocked by" as a related issues option
-* #2420: Fetching emails from an POP server
-* #2482: Named scopes in Issue and ActsAsWatchable plus some view refactoring (logic extraction).
-* #2924: Make the right click menu more discoverable using a cursor property
-* #2985: Make syntax highlighting pluggable
-* #3201: Workflow Check/Uncheck All Rows/Columns
-* #3359: Update CodeRay 0.9
-* #3706: Allow assigned_to field configuration on Issue creation by email
-* #3936: configurable list of models to include in search
-* #4480: Create a link to the user profile from the administration interface
-* #4482: Cache textile rendering
-* #4572: Make it harder to ruin your database
-* #4573: Move github gems to Gemcutter
-* #4664: Add pagination to forum threads
-* #4732: Make login case-insensitive also for PostgreSQL
-* #4812: Create links to other projects
-* #4819: Replace images with smushed ones for speed
-* #4945: Allow custom fields attached to project to be searchable
-* #5121: Fix issues list layout overflow
-* #5169: Issue list view hook request
-* #5208: Aibility to edit wiki sidebar
-* #5281: Remove empty ul tags in the issue history
-* #5291: Updated basque translations
-* #5328: Automatically add "Repository" menu_item after repository creation
-* #5415: Fewer SQL statements generated for watcher_recipients
-* #5416: Exclude "fields_for" from overridden methods in TabularFormBuilder
-* #5573: Allow issue assignment in email
-* #5595: Allow start date and due dates to be set via incoming email
-* #5752: The projects view (/projects) renders ul's wrong
-* #5781: Allow to use more macros on the welcome page and project list
-* Fixed #1288: Unable to past escaped wiki syntax in an issue description
-* Fixed #1334: Wiki formatting character *_ and _*
-* Fixed #1416: Inline code with less-then/greater-than produces @lt; and @gt; respectively
-* Fixed #2473: Login and mail should not be case sensitive
-* Fixed #2990: Ruby 1.9 - wrong number of arguments (1 for 0) on rake db:migrate
-* Fixed #3089: Text formatting sometimes breaks when combined
-* Fixed #3690: Status change info duplicates on the issue screen
-* Fixed #3691: Redmine allows two files with the same file name to be uploaded to the same issue
-* Fixed #3764: ApplicationHelperTest fails with JRuby
-* Fixed #4265: Unclosed code tags in issue descriptions affects main UI
-* Fixed #4745: Bug in index.xml.builder (issues)
-* Fixed #4852: changing user/roles of project member not possible without javascript
-* Fixed #4857: Week number calculation in date picker is wrong if a week starts with Sunday
-* Fixed #4883: Bottom "contextual" placement in issue with associated changeset
-* Fixed #4918: Revisions r3453 and r3454 broke On-the-fly user creation with LDAP
-* Fixed #4935: Navigation to the Master Timesheet page (time_entries)
-* Fixed #5043: Flash messages are not displayed after the project settings[module/activity] saved
-* Fixed #5081: Broken links on public/help/wiki_syntax_detailed.html
-* Fixed #5104: Description of document not wikified on documents index
-* Fixed #5108: Issue linking fails inside of []s
-* Fixed #5199: diff code coloring using coderay
-* Fixed #5233: Add a hook to the issue report (Summary) view
-* Fixed #5265: timetracking: subtasks time is added to the main task
-* Fixed #5343: acts_as_event Doesn't Accept Outside URLs
-* Fixed #5440: UI Inconsistency : Administration > Enumerations table row headers should be enclosed in <thead>
-* Fixed #5463: 0.9.4 INSTALL and/or UPGRADE, missing session_store.rb
-* Fixed #5524: Update_parent_attributes doesn't work for the old parent issue when reparenting
-* Fixed #5548: SVN Repository: Can not list content of a folder which includes square brackets.
-* Fixed #5589: "with subproject" malfunction
-* Fixed #5676: Search for Numeric Value
-* Fixed #5696: Redmine + PostgreSQL 8.4.4 fails on _dir_list_content.rhtml
-* Fixed #5698: redmine:email:receive_imap fails silently for mails with subject longer than 255 characters
-* Fixed #5700: TimelogController#destroy assumes success
-* Fixed #5751: developer role is mispelled
-* Fixed #5769: Popup Calendar doesn't Advance in Chrome
-* Fixed #5771: Problem when importing git repository
-* Fixed #5823: Error in comments in plugin.rb
-
-
-== 2010-07-07 v0.9.6
-
-* Fixed: Redmine.pm access by unauthorized users
-
-== 2010-06-24 v0.9.5
-
-* Linkify folder names on revision view
-* "fiters" and "options" should be hidden in print view via css
-* Fixed: NoMethodError when no issue params are submitted
-* Fixed: projects.atom with required authentication
-* Fixed: External links not correctly displayed in Wiki TOC
-* Fixed: Member role forms in project settings are not hidden after member added
-* Fixed: pre can't be inside p
-* Fixed: session cookie path does not respect RAILS_RELATIVE_URL_ROOT
-* Fixed: mail handler fails when the from address is empty
-
-
-== 2010-05-01 v0.9.4
-
-* Filters collapsed by default on issues index page for a saved query
-* Fixed: When categories list is too big the popup menu doesn't adjust (ex. in the issue list)
-* Fixed: remove "main-menu" div when the menu is empty
-* Fixed: Code syntax highlighting not working in Document page
-* Fixed: Git blame/annotate fails on moved files
-* Fixed: Failing test in test_show_atom
-* Fixed: Migrate from trac - not displayed Wikis
-* Fixed: Email notifications on file upload sent to empty recipient list
-* Fixed: Migrating from trac is not possible, fails to allocate memory
-* Fixed: Lost password no longer flashes a confirmation message
-* Fixed: Crash while deleting in-use enumeration
-* Fixed: Hard coded English string at the selection of issue watchers
-* Fixed: Bazaar v2.1.0 changed behaviour
-* Fixed: Roadmap display can raise an exception if no trackers are selected
-* Fixed: Gravatar breaks layout of "logged in" page
-* Fixed: Reposman.rb on Windows
-* Fixed: Possible error 500 while moving an issue to another project with SQLite
-* Fixed: backslashes in issue description/note should be escaped when quoted
-* Fixed: Long text in <pre> disrupts Associated revisions
-* Fixed: Links to missing wiki pages not red on project overview page
-* Fixed: Cannot delete a project with subprojects that shares versions
-* Fixed: Update of Subversion changesets broken under Solaris
-* Fixed: "Move issues" permission not working for Non member
-* Fixed: Sidebar overlap on Users tab of Group editor
-* Fixed: Error on db:migrate with table prefix set (hardcoded name in principal.rb)
-* Fixed: Report shows sub-projects for non-members
-* Fixed: 500 internal error when browsing any Redmine page in epiphany
-* Fixed: Watchers selection lost when issue creation fails
-* Fixed: When copying projects, redmine should not generate an email to people who created issues
-* Fixed: Issue "#" table cells should have a class attribute to enable fine-grained CSS theme
-* Fixed: Plugin generators should display help if no parameter is given
-
-
-== 2010-02-28 v0.9.3
-
-* Adds filter for system shared versions on the cross project issue list
-* Makes project identifiers searchable
-* Remove invalid utf8 sequences from commit comments and author name
-* Fixed: Wrong link when "http" not included in project "Homepage" link
-* Fixed: Escaping in html email templates
-* Fixed: Pound (#) followed by number with leading zero (0) removes leading zero when rendered in wiki
-* Fixed: Deselecting textile text formatting causes interning empty string errors
-* Fixed: error with postgres when entering a non-numeric id for an issue relation
-* Fixed: div.task incorrectly wrapping on Gantt Chart
-* Fixed: Project copy loses wiki pages hierarchy
-* Fixed: parent project field doesn't include blank value when a member with 'add subproject' permission edits a child project
-* Fixed: Repository.fetch_changesets tries to fetch changesets for archived projects
-* Fixed: Duplicated project name for subproject version on gantt chart
-* Fixed: roadmap shows subprojects issues even if subprojects is unchecked
-* Fixed: IndexError if all the :last menu items are deleted from a menu
-* Fixed: Very high CPU usage for a long time when fetching commits from a large Git repository
-
-
-== 2010-02-07 v0.9.2
-
-* Fixed: Sub-project repository commits not displayed on parent project issues
-* Fixed: Potential security leak on my page calendar
-* Fixed: Project tree structure is broken by deleting the project with the subproject
-* Fixed: Error message shown duplicated when creating a new group
-* Fixed: Firefox cuts off large pages
-* Fixed: Invalid format parameter returns a DoubleRenderError on issues index
-* Fixed: Unnecessary Quote button on locked forum message
-* Fixed: Error raised when trying to view the gantt or calendar with a grouped query
-* Fixed: PDF support for Korean locale
-* Fixed: Deprecation warning in extra/svn/reposman.rb
-
-
-== 2010-01-30 v0.9.1
-
-* Vertical alignment for inline images in formatted text set to 'middle'
-* Fixed: Redmine.pm error "closing dbh with active statement handles at /usr/lib/perl5/Apache/Redmine.pm"
-* Fixed: copyright year in footer set to 2010
-* Fixed: Trac migration script may not output query lines
-* Fixed: Email notifications may affect language of notice messages on the UI
-* Fixed: Can not search for 2 letters word
-* Fixed: Attachments get saved on issue update even if validation fails
-* Fixed: Tab's 'border-bottom' not absent when selected
-* Fixed: Issue summary tables that list by user are not sorted
-* Fixed: Issue pdf export fails if target version is set
-* Fixed: Issue list export to PDF breaks when issues are sorted by a custom field
-* Fixed: SQL error when adding a group
-* Fixes: Min password length during password reset always displays as 4 chars
-
-
-== 2010-01-09 v0.9.0 (Release candidate)
-
-* Unlimited subproject nesting
-* Multiple roles per user per project
-* User groups
-* Inheritence of versions
-* OpenID login
-* "Watched by me" issue filter
-* Project copy
-* Project creation by non admin users
-* Accept emails from anyone on a private project
-* Add email notification on Wiki changes
-* Make issue description non-required field
-* Custom fields for Versions
-* Being able to sort the issue list by custom fields
-* Ability to close versions
-* User display/editing of custom fields attached to their user profile
-* Add "follows" issue relation
-* Copy workflows between trackers and roles
-* Defaults enabled modules list for project creation
-* Weighted version completion percentage on the roadmap
-* Autocreate user account when user submits email that creates new issue
-* CSS class on overdue issues on the issue list
-* Enable tracker update on issue edit form
-* Remove issue watchers
-* Ability to move threads between project forums
-* Changed custom field "Possible values" to a textarea
-* Adds projects association on tracker form
-* Set session store to cookie store by default
-* Set a default wiki page on project creation
-* Roadmap for main project should see Roadmaps for sub projects
-* Ticket grouping on the issue list
-* Hierarchical Project links in the page header
-* Allow My Page blocks to be added to from a plugin
-* Sort issues by multiple columns
-* Filters of saved query are now visible and be adjusted without editing the query
-* Saving "sort order" in custom queries
-* Url to fetch changesets for a repository
-* Managers able to create subprojects
-* Issue Totals on My Page Modules
-* Convert Enumerations to single table inheritance (STI)
-* Allow custom my_page blocks to define drop-down names
-* "View Issues" user permission added
-* Ask user what to do with child pages when deleting a parent wiki page
-* Contextual quick search
-* Allow resending of password by email
-* Change reply subject to be a link to the reply itself
-* Include Logged Time as part of the project's Activity history
-* REST API for authentication
-* Browse through Git branches
-* Setup Object Daddy to replace test fixtures
-* Setup shoulda to make it easier to test
-* Custom fields and overrides on Enumerations
-* Add or remove columns from the issue list
-* Ability to add new version from issues screen
-* Setting to choose which day calendars start
-* Asynchronous email delivery method
-* RESTful URLs for (almost) everything
-* Include issue status in search results and activity pages
-* Add email to admin user search filter
-* Proper content type for plain text mails
-* Default value of project jump box
-* Tree based menus
-* Ability to use issue status to update percent done
-* Second set of issue "Action Links" at the bottom of an issue page
-* Proper exist status code for rdm-mailhandler.rb
-* Remove incoming email body via a delimiter
-* Fixed: Custom querry 'Export to PDF' ignores field selection
-* Fixed: Related e-mail notifications aren't threaded
-* Fixed: No warning when the creation of a categories from the issue form fails
-* Fixed: Actually block issues from closing when relation 'blocked by' isn't closed
-* Fixed: Include both first and last name when sorting by users
-* Fixed: Table cell with multiple line text
-* Fixed: Project overview page shows disabled trackers
-* Fixed: Cross project issue relations and user permissions
-* Fixed: My page shows tickets the user doesn't have access to
-* Fixed: TOC does not parse wiki page reference links with description
-* Fixed: Target version-list on bulk edit form is incorrectly sorted
-* Fixed: Cannot modify/delete project named "Documents"
-* Fixed: Email address in brackets breaks html
-* Fixed: Timelog detail loose issue filter passing to report tab
-* Fixed: Inform about custom field's name maximum length
-* Fixed: Activity page and Atom feed links contain project id instead of identifier
-* Fixed: no Atom key for forums with only 1 forum
-* Fixed: When reading RSS feed in MS Outlook, the inline links are broken.
-* Fixed: Sometimes new posts don't show up in the topic list of a forum.
-* Fixed: The all/active filter selection in the project view does not stick.
-* Fixed: Login box has Different width
-* Fixed: User removed from project - still getting project update emails
-* Fixed: Project with the identifier of 'new' cannot be viewed
-* Fixed: Artefacts in search view (Cyrillic)
-* Fixed: Allow [#id] as subject to reply by email
-* Fixed: Wrong language used when closing an issue via a commit message
-* Fixed: email handler drops emails for new issues with no subject
-* Fixed: Calendar misspelled under Roles/Permissions
-* Fixed: Emails from no-reply redmine's address hell cycle
-* Fixed: child_pages macro fails on wiki page history
-* Fixed: Pre-filled time tracking date ignores timezone
-* Fixed: Links on locked users lead to 404 page
-* Fixed: Page changes in issue-list when using context menu
-* Fixed: diff parser removes lines starting with multiple dashes
-* Fixed: Quoting in forums resets message subject
-* Fixed: Editing issue comment removes quote link
-* Fixed: Redmine.pm ignore browse_repository permission
-* Fixed: text formatting breaks on [msg1][msg2]
-* Fixed: Spent Time Default Value of 0.0
-* Fixed: Wiki pages in search results are referenced by project number, not by project identifier.
-* Fixed: When logging in via an autologin cookie the user's last_login_on should be updated
-* Fixed: 50k users cause problems in project->settings->members screen
-* Fixed: Document timestamp needs to show updated timestamps
-* Fixed: Users getting notifications for issues they are no longer allowed to view
-* Fixed: issue summary counts should link to the issue list without subprojects
-* Fixed: 'Delete' link on LDAP list has no effect
-
-
-== 2009-11-15 v0.8.7
-
-* Fixed: Hide paragraph terminator at the end of headings on html export
-* Fixed: pre tags containing "<pre*"
-* Fixed: First date of the date range not included in the time report with SQLite
-* Fixed: Password field not styled correctly on alternative stylesheet
-* Fixed: Error when sumbitting a POST request that requires a login
-* Fixed: CSRF vulnerabilities
-
-
-== 2009-11-04 v0.8.6
-
-* Change links to closed issues to be a grey color
-* Change subversion adapter to not cache authentication and run non interactively
-* Fixed: Custom Values with a nil value cause HTTP error 500
-* Fixed: Failure to convert HTML entities when editing an Issue reply
-* Fixed: Error trying to show repository when there are no comments in a changeset
-* Fixed: account/show/:user_id should not be accessible for other users not in your projects
-* Fixed: XSS vulnerabilities
-* Fixed: IssuesController#destroy should accept POST only
-* Fixed: Inline images in wiki headings
-
-
-== 2009-09-13 v0.8.5
-
-* Incoming mail handler : Allow spaces between keywords and colon
-* Do not require a non-word character after a comma in Redmine links
-* Include issue hyperlinks in reminder emails
-* Prevent nil error when retrieving svn version
-* Various plugin hooks added
-* Add plugins information to script/about
-* Fixed: 500 Internal Server Error is raised if add an empty comment to the news
-* Fixed: Atom links for wiki pages are not correct
-* Fixed: Atom feeds leak email address
-* Fixed: Case sensitivity in Issue filtering
-* Fixed: When reading RSS feed, the inline-embedded images are not properly shown
-
-
-== 2009-05-17 v0.8.4
-
-* Allow textile mailto links
-* Fixed: memory consumption when uploading file
-* Fixed: Mercurial integration doesn't work if Redmine is installed in folder path containing space
-* Fixed: an error is raised when no tab is available on project settings
-* Fixed: insert image macro corrupts urls with excalamation marks
-* Fixed: error on cross-project gantt PNG export
-* Fixed: self and alternate links in atom feeds do not respect Atom specs
-* Fixed: accept any svn tunnel scheme in repository URL
-* Fixed: issues/show should accept user's rss key
-* Fixed: consistency of custom fields display on the issue detail view
-* Fixed: wiki comments length validation is missing
-* Fixed: weak autologin token generation algorithm causes duplicate tokens
-
-
-== 2009-04-05 v0.8.3
-
-* Separate project field and subject in cross-project issue view
-* Ability to set language for redmine:load_default_data task using REDMINE_LANG environment variable
-* Rescue Redmine::DefaultData::DataAlreadyLoaded in redmine:load_default_data task
-* CSS classes to highlight own and assigned issues
-* Hide "New file" link on wiki pages from printing
-* Flush buffer when asking for language in redmine:load_default_data task
-* Minimum project identifier length set to 1
-* Include headers so that emails don't trigger vacation auto-responders
-* Fixed: Time entries csv export links for all projects are malformed
-* Fixed: Files without Version aren't visible in the Activity page
-* Fixed: Commit logs are centered in the repo browser
-* Fixed: News summary field content is not searchable
-* Fixed: Journal#save has a wrong signature
-* Fixed: Email footer signature convention
-* Fixed: Timelog report do not show time for non-versioned issues
-
-
-== 2009-03-07 v0.8.2
-
-* Send an email to the user when an administrator activates a registered user
-* Strip keywords from received email body
-* Footer updated to 2009
-* Show RSS-link even when no issues is found
-* One click filter action in activity view
-* Clickable/linkable line #'s while browsing the repo or viewing a file
-* Links to versions on files list
-* Added request and controller objects to the hooks by default
-* Fixed: exporting an issue with attachments to PDF raises an error
-* Fixed: "too few arguments" error may occur on activerecord error translation
-* Fixed: "Default columns Displayed on the Issues list" setting is not easy to read
-* Fixed: visited links to closed tickets are not striked through with IE6
-* Fixed: MailHandler#plain_text_body returns nil if there was nothing to strip
-* Fixed: MailHandler raises an error when processing an email without From header
-
-
-== 2009-02-15 v0.8.1
-
-* Select watchers on new issue form
-* Issue description is no longer a required field
-* Files module: ability to add files without version
-* Jump to the current tab when using the project quick-jump combo
-* Display a warning if some attachments were not saved
-* Import custom fields values from emails on issue creation
-* Show view/annotate/download links on entry and annotate views
-* Admin Info Screen: Display if plugin assets directory is writable
-* Adds a 'Create and continue' button on the new issue form
-* IMAP: add options to move received emails
-* Do not show Category field when categories are not defined
-* Lower the project identifier limit to a minimum of two characters
-* Add "closed" html class to closed entries in issue list
-* Fixed: broken redirect URL on login failure
-* Fixed: Deleted files are shown when using Darcs
-* Fixed: Darcs adapter works on Win32 only
-* Fixed: syntax highlight doesn't appear in new ticket preview
-* Fixed: email notification for changes I make still occurs when running Repository.fetch_changesets
-* Fixed: no error is raised when entering invalid hours on the issue update form
-* Fixed: Details time log report CSV export doesn't honour date format from settings
-* Fixed: invalid css classes on issue details
-* Fixed: Trac importer creates duplicate custom values
-* Fixed: inline attached image should not match partial filename
-
-
-== 2008-12-30 v0.8.0
-
-* Setting added in order to limit the number of diff lines that should be displayed
-* Makes logged-in username in topbar linking to
-* Mail handler: strip tags when receiving a html-only email
-* Mail handler: add watchers before sending notification
-* Adds a css class (overdue) to overdue issues on issue lists and detail views
-* Fixed: project activity truncated after viewing user's activity
-* Fixed: email address entered for password recovery shouldn't be case-sensitive
-* Fixed: default flag removed when editing a default enumeration
-* Fixed: default category ignored when adding a document
-* Fixed: error on repository user mapping when a repository username is blank
-* Fixed: Firefox cuts off large diffs
-* Fixed: CVS browser should not show dead revisions (deleted files)
-* Fixed: escape double-quotes in image titles
-* Fixed: escape textarea content when editing a issue note
-* Fixed: JS error on context menu with IE
-* Fixed: bold syntax around single character in series doesn't work
-* Fixed several XSS vulnerabilities
-* Fixed a SQL injection vulnerability
-
-
-== 2008-12-07 v0.8.0-rc1
-
-* Wiki page protection
-* Wiki page hierarchy. Parent page can be assigned on the Rename screen
-* Adds support for issue creation via email
-* Adds support for free ticket filtering and custom queries on Gantt chart and calendar
-* Cross-project search
-* Ability to search a project and its subprojects
-* Ability to search the projects the user belongs to
-* Adds custom fields on time entries
-* Adds boolean and list custom fields for time entries as criteria on time report
-* Cross-project time reports
-* Display latest user's activity on account/show view
-* Show last connexion time on user's page
-* Obfuscates email address on user's account page using javascript
-* wiki TOC rendered as an unordered list
-* Adds the ability to search for a user on the administration users list
-* Adds the ability to search for a project name or identifier on the administration projects list
-* Redirect user to the previous page after logging in
-* Adds a permission 'view wiki edits' so that wiki history can be hidden to certain users
-* Adds permissions for viewing the watcher list and adding new watchers on the issue detail view
-* Adds permissions to let users edit and/or delete their messages
-* Link to activity view when displaying dates
-* Hide Redmine version in atom feeds and pdf properties
-* Maps repository users to Redmine users. Users with same username or email are automatically mapped. Mapping can be manually adjusted in repository settings. Multiple usernames can be mapped to the same Redmine user.
-* Sort users by their display names so that user dropdown lists are sorted alphabetically
-* Adds estimated hours to issue filters
-* Switch order of current and previous revisions in side-by-side diff
-* Render the commit changes list as a tree
-* Adds watch/unwatch functionality at forum topic level
-* When moving an issue to another project, reassign it to the category with same name if any
-* Adds child_pages macro for wiki pages
-* Use GET instead of POST on roadmap (#718), gantt and calendar forms
-* Search engine: display total results count and count by result type
-* Email delivery configuration moved to an unversioned YAML file (config/email.yml, see the sample file)
-* Adds icons on search results
-* Adds 'Edit' link on account/show for admin users
-* Adds Lock/Unlock/Activate link on user edit screen
-* Adds user count in status drop down on admin user list
-* Adds multi-levels blockquotes support by using > at the beginning of lines
-* Adds a Reply link to each issue note
-* Adds plain text only option for mail notifications
-* Gravatar support for issue detail, user grid, and activity stream (disabled by default)
-* Adds 'Delete wiki pages attachments' permission
-* Show the most recent file when displaying an inline image
-* Makes permission screens localized
-* AuthSource list: display associated users count and disable 'Delete' buton if any
-* Make the 'duplicates of' relation asymmetric
-* Adds username to the password reminder email
-* Adds links to forum messages using message#id syntax
-* Allow same name for custom fields on different object types
-* One-click bulk edition using the issue list context menu within the same project
-* Adds support for commit logs reencoding to UTF-8 before insertion in the database. Source encoding of commit logs can be selected in Application settings -> Repositories.
-* Adds checkboxes toggle links on permissions report
-* Adds Trac-Like anchors on wiki headings
-* Adds support for wiki links with anchor
-* Adds category to the issue context menu
-* Adds a workflow overview screen
-* Appends the filename to the attachment url so that clients that ignore content-disposition http header get the real filename
-* Dots allowed in custom field name
-* Adds posts quoting functionality
-* Adds an option to generate sequential project identifiers
-* Adds mailto link on the user administration list
-* Ability to remove enumerations (activities, priorities, document categories) that are in use. Associated objects can be reassigned to another value
-* Gantt chart: display issues that don't have a due date if they are assigned to a version with a date
-* Change projects homepage limit to 255 chars
-* Improved on-the-fly account creation. If some attributes are missing (eg. not present in the LDAP) or are invalid, the registration form is displayed so that the user is able to fill or fix these attributes
-* Adds "please select" to activity select box if no activity is set as default
-* Do not silently ignore timelog validation failure on issue edit
-* Adds a rake task to send reminder emails
-* Allow empty cells in wiki tables
-* Makes wiki text formatter pluggable
-* Adds back textile acronyms support
-* Remove pre tag attributes
-* Plugin hooks
-* Pluggable admin menu
-* Plugins can provide activity content
-* Moves plugin list to its own administration menu item
-* Adds url and author_url plugin attributes
-* Adds Plugin#requires_redmine method so that plugin compatibility can be checked against current Redmine version
-* Adds atom feed on time entries details
-* Adds project name to issues feed title
-* Adds a css class on menu items in order to apply item specific styles (eg. icons)
-* Adds a Redmine plugin generators
-* Adds timelog link to the issue context menu
-* Adds links to the user page on various views
-* Turkish translation by Ismail Sezen
-* Catalan translation
-* Vietnamese translation
-* Slovak translation
-* Better naming of activity feed if only one kind of event is displayed
-* Enable syntax highlight on issues, messages and news
-* Add target version to the issue list context menu
-* Hide 'Target version' filter if no version is defined
-* Add filters on cross-project issue list for custom fields marked as 'For all projects'
-* Turn ftp urls into links
-* Hiding the View Differences button when a wiki page's history only has one version
-* Messages on a Board can now be sorted by the number of replies
-* Adds a class ('me') to events of the activity view created by current user
-* Strip pre/code tags content from activity view events
-* Display issue notes in the activity view
-* Adds links to changesets atom feed on repository browser
-* Track project and tracker changes in issue history
-* Adds anchor to atom feed messages links
-* Adds a key in lang files to set the decimal separator (point or comma) in csv exports
-* Makes importer work with Trac 0.8.x
-* Upgraded to Prototype 1.6.0.1
-* File viewer for attached text files
-* Menu mapper: add support for :before, :after and :last options to #push method and add #delete method
-* Removed inconsistent revision numbers on diff view
-* CVS: add support for modules names with spaces
-* Log the user in after registration if account activation is not needed
-* Mercurial adapter improvements
-* Trac importer: read session_attribute table to find user's email and real name
-* Ability to disable unused SCM adapters in application settings
-* Adds Filesystem adapter
-* Clear changesets and changes with raw sql when deleting a repository for performance
-* Redmine.pm now uses the 'commit access' permission defined in Redmine
-* Reposman can create any type of scm (--scm option)
-* Reposman creates a repository if the 'repository' module is enabled at project level only
-* Display svn properties in the browser, svn >= 1.5.0 only
-* Reduces memory usage when importing large git repositories
-* Wider SVG graphs in repository stats
-* SubversionAdapter#entries performance improvement
-* SCM browser: ability to download raw unified diffs
-* More detailed error message in log when scm command fails
-* Adds support for file viewing with Darcs 2.0+
-* Check that git changeset is not in the database before creating it
-* Unified diff viewer for attached files with .patch or .diff extension
-* File size display with Bazaar repositories
-* Git adapter: use commit time instead of author time
-* Prettier url for changesets
-* Makes changes link to entries on the revision view
-* Adds a field on the repository view to browse at specific revision
-* Adds new projects atom feed
-* Added rake tasks to generate rcov code coverage reports
-* Add Redcloth's :block_markdown_rule to allow horizontal rules in wiki
-* Show the project hierarchy in the drop down list for new membership on user administration screen
-* Split user edit screen into tabs
-* Renames bundled RedCloth to RedCloth3 to avoid RedCloth 4 to be loaded instead
-* Fixed: Roadmap crashes when a version has a due date > 2037
-* Fixed: invalid effective date (eg. 99999-01-01) causes an error on version edition screen
-* Fixed: login filter providing incorrect back_url for Redmine installed in sub-directory
-* Fixed: logtime entry duplicated when edited from parent project
-* Fixed: wrong digest for text files under Windows
-* Fixed: associated revisions are displayed in wrong order on issue view
-* Fixed: Git Adapter date parsing ignores timezone
-* Fixed: Printing long roadmap doesn't split across pages
-* Fixes custom fields display order at several places
-* Fixed: urls containing @ are parsed as email adress by the wiki formatter
-* Fixed date filters accuracy with SQLite
-* Fixed: tokens not escaped in highlight_tokens regexp
-* Fixed Bazaar shared repository browsing
-* Fixes platform determination under JRuby
-* Fixed: Estimated time in issue's journal should be rounded to two decimals
-* Fixed: 'search titles only' box ignored after one search is done on titles only
-* Fixed: non-ASCII subversion path can't be displayed
-* Fixed: Inline images don't work if file name has upper case letters or if image is in BMP format
-* Fixed: document listing shows on "my page" when viewing documents is disabled for the role
-* Fixed: Latest news appear on the homepage for projects with the News module disabled
-* Fixed: cross-project issue list should not show issues of projects for which the issue tracking module was disabled
-* Fixed: the default status is lost when reordering issue statuses
-* Fixes error with Postgresql and non-UTF8 commit logs
-* Fixed: textile footnotes no longer work
-* Fixed: http links containing parentheses fail to reder correctly
-* Fixed: GitAdapter#get_rev should use current branch instead of hardwiring master
-
-
-== 2008-07-06 v0.7.3
-
-* Allow dot in firstnames and lastnames
-* Add project name to cross-project Atom feeds
-* Encoding set to utf8 in example database.yml
-* HTML titles on forums related views
-* Fixed: various XSS vulnerabilities
-* Fixed: Entourage (and some old client) fails to correctly render notification styles
-* Fixed: Fixed: timelog redirects inappropriately when :back_url is blank
-* Fixed: wrong relative paths to images in wiki_syntax.html
-
-
-== 2008-06-15 v0.7.2
-
-* "New Project" link on Projects page
-* Links to repository directories on the repo browser
-* Move status to front in Activity View
-* Remove edit step from Status context menu
-* Fixed: No way to do textile horizontal rule
-* Fixed: Repository: View differences doesn't work
-* Fixed: attachement's name maybe invalid.
-* Fixed: Error when creating a new issue
-* Fixed: NoMethodError on @available_filters.has_key?
-* Fixed: Check All / Uncheck All in Email Settings
-* Fixed: "View differences" of one file at /repositories/revision/ fails
-* Fixed: Column width in "my page"
-* Fixed: private subprojects are listed on Issues view
-* Fixed: Textile: bold, italics, underline, etc... not working after parentheses
-* Fixed: Update issue form: comment field from log time end out of screen
-* Fixed: Editing role: "issue can be assigned to this role" out of box
-* Fixed: Unable use angular braces after include word
-* Fixed: Using '*' as keyword for repository referencing keywords doesn't work
-* Fixed: Subversion repository "View differences" on each file rise ERROR
-* Fixed: View differences for individual file of a changeset fails if the repository URL doesn't point to the repository root
-* Fixed: It is possible to lock out the last admin account
-* Fixed: Wikis are viewable for anonymous users on public projects, despite not granting access
-* Fixed: Issue number display clipped on 'my issues'
-* Fixed: Roadmap version list links not carrying state
-* Fixed: Log Time fieldset in IssueController#edit doesn't set default Activity as default
-* Fixed: git's "get_rev" API should use repo's current branch instead of hardwiring "master"
-* Fixed: browser's language subcodes ignored
-* Fixed: Error on project selection with numeric (only) identifier.
-* Fixed: Link to PDF doesn't work after creating new issue
-* Fixed: "Replies" should not be shown on forum threads that are locked
-* Fixed: SVN errors lead to svn username/password being displayed to end users (security issue)
-* Fixed: http links containing hashes don't display correct
-* Fixed: Allow ampersands in Enumeration names
-* Fixed: Atom link on saved query does not include query_id
-* Fixed: Logtime info lost when there's an error updating an issue
-* Fixed: TOC does not parse colorization markups
-* Fixed: CVS: add support for modules names with spaces
-* Fixed: Bad rendering on projects/add
-* Fixed: exception when viewing differences on cvs
-* Fixed: export issue to pdf will messup when use Chinese language
-* Fixed: Redmine::Scm::Adapters::GitAdapter#get_rev ignored GIT_BIN constant
-* Fixed: Adding non-ASCII new issue type in the New Issue page have encoding error using IE
-* Fixed: Importing from trac : some wiki links are messed
-* Fixed: Incorrect weekend definition in Hebrew calendar locale
-* Fixed: Atom feeds don't provide author section for repository revisions
-* Fixed: In Activity views, changesets titles can be multiline while they should not
-* Fixed: Ignore unreadable subversion directories (read disabled using authz)
-* Fixed: lib/SVG/Graph/Graph.rb can't externalize stylesheets
-* Fixed: Close statement handler in Redmine.pm
-
-
-== 2008-05-04 v0.7.1
-
-* Thai translation added (Gampol Thitinilnithi)
-* Translations updates
-* Escape HTML comment tags
-* Prevent "can't convert nil into String" error when :sort_order param is not present
-* Fixed: Updating tickets add a time log with zero hours
-* Fixed: private subprojects names are revealed on the project overview
-* Fixed: Search for target version of "none" fails with postgres 8.3
-* Fixed: Home, Logout, Login links shouldn't be absolute links
-* Fixed: 'Latest projects' box on the welcome screen should be hidden if there are no projects
-* Fixed: error when using upcase language name in coderay
-* Fixed: error on Trac import when :due attribute is nil
-
-
-== 2008-04-28 v0.7.0
-
-* Forces Redmine to use rails 2.0.2 gem when vendor/rails is not present
-* Queries can be marked as 'For all projects'. Such queries will be available on all projects and on the global issue list.
-* Add predefined date ranges to the time report
-* Time report can be done at issue level
-* Various timelog report enhancements
-* Accept the following formats for "hours" field: 1h, 1 h, 1 hour, 2 hours, 30m, 30min, 1h30, 1h30m, 1:30
-* Display the context menu above and/or to the left of the click if needed
-* Make the admin project files list sortable
-* Mercurial: display working directory files sizes unless browsing a specific revision
-* Preserve status filter and page number when using lock/unlock/activate links on the users list
-* Redmine.pm support for LDAP authentication
-* Better error message and AR errors in log for failed LDAP on-the-fly user creation
-* Redirected user to where he is coming from after logging hours
-* Warn user that subprojects are also deleted when deleting a project
-* Include subprojects versions on calendar and gantt
-* Notify project members when a message is posted if they want to receive notifications
-* Fixed: Feed content limit setting has no effect
-* Fixed: Priorities not ordered when displayed as a filter in issue list
-* Fixed: can not display attached images inline in message replies
-* Fixed: Boards are not deleted when project is deleted
-* Fixed: trying to preview a new issue raises an exception with postgresql
-* Fixed: single file 'View difference' links do not work because of duplicate slashes in url
-* Fixed: inline image not displayed when including a wiki page
-* Fixed: CVS duplicate key violation
-* Fixed: ActiveRecord::StaleObjectError exception on closing a set of circular duplicate issues
-* Fixed: custom field filters behaviour
-* Fixed: Postgresql 8.3 compatibility
-* Fixed: Links to repository directories don't work
-
-
-== 2008-03-29 v0.7.0-rc1
-
-* Overall activity view and feed added, link is available on the project list
-* Git VCS support
-* Rails 2.0 sessions cookie store compatibility
-* Use project identifiers in urls instead of ids
-* Default configuration data can now be loaded from the administration screen
-* Administration settings screen split to tabs (email notifications options moved to 'Settings')
-* Project description is now unlimited and optional
-* Wiki annotate view
-* Escape HTML tag in textile content
-* Add Redmine links to documents, versions, attachments and repository files
-* New setting to specify how many objects should be displayed on paginated lists. There are 2 ways to select a set of issues on the issue list:
-    * by using checkbox and/or the little pencil that will select/unselect all issues
-    * by clicking on the rows (but not on the links), Ctrl and Shift keys can be used to select multiple issues
-* Context menu disabled on links so that the default context menu of the browser is displayed when right-clicking on a link (click anywhere else on the row to display the context menu)
-* User display format is now configurable in administration settings
-* Issue list now supports bulk edit/move/delete (for a set of issues that belong to the same project)
-* Merged 'change status', 'edit issue' and 'add note' actions:
-    * Users with 'edit issues' permission can now update any property including custom fields when adding a note or changing the status
-    * 'Change issue status' permission removed. To change an issue status, a user just needs to have either 'Edit' or 'Add note' permissions and some workflow transitions allowed
-* Details by assignees on issue summary view
-* 'New issue' link in the main menu (accesskey 7). The drop-down lists to add an issue on the project overview and the issue list are removed
-* Change status select box default to current status
-* Preview for issue notes, news and messages
-* Optional description for attachments
-* 'Fixed version' label changed to 'Target version'
-* Let the user choose when deleting issues with reported hours to:
-    * delete the hours
-    * assign the hours to the project
-    * reassign the hours to another issue
-* Date range filter and pagination on time entries detail view
-* Propagate time tracking to the parent project
-* Switch added on the project activity view to include subprojects
-* Display total estimated and spent hours on the version detail view
-* Weekly time tracking block for 'My page'
-* Permissions to edit time entries
-* Include subprojects on the issue list, calendar, gantt and timelog by default (can be turned off is administration settings)
-* Roadmap enhancements (separate related issues from wiki contents, leading h1 in version wiki pages is hidden, smaller wiki headings)
-* Make versions with same date sorted by name
-* Allow issue list to be sorted by target version
-* Related changesets messages displayed on the issue details view
-* Create a journal and send an email when an issue is closed by commit
-* Add 'Author' to the available columns for the issue list
-* More appropriate default sort order on sortable columns
-* Add issue subject to the time entries view and issue subject, description and tracker to the csv export
-* Permissions to edit issue notes
-* Display date/time instead of date on files list
-* Do not show Roadmap menu item if the project doesn't define any versions
-* Allow longer version names (60 chars)
-* Ability to copy an existing workflow when creating a new role
-* Display custom fields in two columns on the issue form
-* Added 'estimated time' in the csv export of the issue list
-* Display the last 30 days on the activity view rather than the current month (number of days can be configured in the application settings)
-* Setting for whether new projects should be public by default
-* User preference to choose how comments/replies are displayed: in chronological or reverse chronological order
-* Added default value for custom fields
-* Added tabindex property on wiki toolbar buttons (to easily move from field to field using the tab key)
-* Redirect to issue page after creating a new issue
-* Wiki toolbar improvements (mainly for Firefox)
-* Display wiki syntax quick ref link on all wiki textareas
-* Display links to Atom feeds
-* Breadcrumb nav for the forums
-* Show replies when choosing to display messages in the activity
-* Added 'include' macro to include another wiki page
-* RedmineWikiFormatting page available as a static HTML file locally
-* Wrap diff content
-* Strip out email address from authors in repository screens
-* Highlight the current item of the main menu
-* Added simple syntax highlighters for php and java languages
-* Do not show empty diffs
-* Show explicit error message when the scm command failed (eg. when svn binary is not available)
-* Lithuanian translation added (Sergej Jegorov)
-* Ukrainan translation added (Natalia Konovka & Mykhaylo Sorochan)
-* Danish translation added (Mads Vestergaard)
-* Added i18n support to the jstoolbar and various settings screen
-* RedCloth's glyphs no longer user
-* New icons for the wiki toolbar (from http://www.famfamfam.com/lab/icons/silk/)
-* The following menus can now be extended by plugins: top_menu, account_menu, application_menu
-* Added a simple rake task to fetch changesets from the repositories: rake redmine:fetch_changesets
-* Remove hardcoded "Redmine" strings in account related emails and use application title instead
-* Mantis importer preserve bug ids
-* Trac importer: Trac guide wiki pages skipped
-* Trac importer: wiki attachments migration added
-* Trac importer: support database schema for Trac migration
-* Trac importer: support CamelCase links
-* Removes the Redmine version from the footer (can be viewed on admin -> info)
-* Rescue and display an error message when trying to delete a role that is in use
-* Add various 'X-Redmine' headers to email notifications: X-Redmine-Host, X-Redmine-Site, X-Redmine-Project, X-Redmine-Issue-Id, -Author, -Assignee, X-Redmine-Topic-Id
-* Add "--encoding utf8" option to the Mercurial "hg log" command in order to get utf8 encoded commit logs
-* Fixed: Gantt and calendar not properly refreshed (fragment caching removed)
-* Fixed: Textile image with style attribute cause internal server error
-* Fixed: wiki TOC not rendered properly when used in an issue or document description
-* Fixed: 'has already been taken' error message on username and email fields if left empty
-* Fixed: non-ascii attachement filename with IE
-* Fixed: wrong url for wiki syntax pop-up when Redmine urls are prefixed
-* Fixed: search for all words doesn't work
-* Fixed: Do not show sticky and locked checkboxes when replying to a message
-* Fixed: Mantis importer: do not duplicate Mantis username in firstname and lastname if realname is blank
-* Fixed: Date custom fields not displayed as specified in application settings
-* Fixed: titles not escaped in the activity view
-* Fixed: issue queries can not use custom fields marked as 'for all projects' in a project context
-* Fixed: on calendar, gantt and in the tracker filter on the issue list, only active trackers of the project (and its sub projects) should be available
-* Fixed: locked users should not receive email notifications
-* Fixed: custom field selection is not saved when unchecking them all on project settings
-* Fixed: can not lock a topic when creating it
-* Fixed: Incorrect filtering for unset values when using 'is not' filter
-* Fixed: PostgreSQL issues_seq_id not updated when using Trac importer
-* Fixed: ajax pagination does not scroll up
-* Fixed: error when uploading a file with no content-type specified by the browser
-* Fixed: wiki and changeset links not displayed when previewing issue description or notes
-* Fixed: 'LdapError: no bind result' error when authenticating
-* Fixed: 'LdapError: invalid binding information' when no username/password are set on the LDAP account
-* Fixed: CVS repository doesn't work if port is used in the url
-* Fixed: Email notifications: host name is missing in generated links
-* Fixed: Email notifications: referenced changesets, wiki pages, attachments... are not turned into links
-* Fixed: Do not clear issue relations when moving an issue to another project if cross-project issue relations are allowed
-* Fixed: "undefined method 'textilizable'" error on email notification when running Repository#fetch_changesets from the console
-* Fixed: Do not send an email with no recipient, cc or bcc
-* Fixed: fetch_changesets fails on commit comments that close 2 duplicates issues.
-* Fixed: Mercurial browsing under unix-like os and for directory depth > 2
-* Fixed: Wiki links with pipe can not be used in wiki tables
-* Fixed: migrate_from_trac doesn't import timestamps of wiki and tickets
-* Fixed: when bulk editing, setting "Assigned to" to "nobody" causes an sql error with Postgresql
-
-
-== 2008-03-12 v0.6.4
-
-* Fixed: private projects name are displayed on account/show even if the current user doesn't have access to these private projects
-* Fixed: potential LDAP authentication security flaw
-* Fixed: context submenus on the issue list don't show up with IE6.
-* Fixed: Themes are not applied with Rails 2.0
-* Fixed: crash when fetching Mercurial changesets if changeset[:files] is nil
-* Fixed: Mercurial repository browsing
-* Fixed: undefined local variable or method 'log' in CvsAdapter when a cvs command fails
-* Fixed: not null constraints not removed with Postgresql
-* Doctype set to transitional
-
-
-== 2007-12-18 v0.6.3
-
-* Fixed: upload doesn't work in 'Files' section
-
-
-== 2007-12-16 v0.6.2
-
-* Search engine: issue custom fields can now be searched
-* News comments are now textilized
-* Updated Japanese translation (Satoru Kurashiki)
-* Updated Chinese translation (Shortie Lo)
-* Fixed Rails 2.0 compatibility bugs:
-  * Unable to create a wiki
-  * Gantt and calendar error
-  * Trac importer error (readonly? is defined by ActiveRecord)
-* Fixed: 'assigned to me' filter broken
-* Fixed: crash when validation fails on issue edition with no custom fields
-* Fixed: reposman "can't find group" error
-* Fixed: 'LDAP account password is too long' error when leaving the field empty on creation
-* Fixed: empty lines when displaying repository files with Windows style eol
-* Fixed: missing body closing tag in repository annotate and entry views
-
-
-== 2007-12-10 v0.6.1
-
-* Rails 2.0 compatibility
-* Custom fields can now be displayed as columns on the issue list
-* Added version details view (accessible from the roadmap)
-* Roadmap: more accurate completion percentage calculation (done ratio of open issues is now taken into account)
-* Added per-project tracker selection. Trackers can be selected on project settings
-* Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums
-* Forums: messages can now be edited/deleted (explicit permissions need to be given)
-* Forums: topics can be locked so that no reply can be added
-* Forums: topics can be marked as sticky so that they always appear at the top of the list
-* Forums: attachments can now be added to replies
-* Added time zone support
-* Added a setting to choose the account activation strategy (available in application settings)
-* Added 'Classic' theme (inspired from the v0.51 design)
-* Added an alternate theme which provides issue list colorization based on issues priority
-* Added Bazaar SCM adapter
-* Added Annotate/Blame view in the repository browser (except for Darcs SCM)
-* Diff style (inline or side by side) automatically saved as a user preference
-* Added issues status changes on the activity view (by Cyril Mougel)
-* Added forums topics on the activity view (disabled by default)
-* Added an option on 'My account' for users who don't want to be notified of changes that they make
-* Trac importer now supports mysql and postgresql databases
-* Trac importer improvements (by Mat Trudel)
-* 'fixed version' field can now be displayed on the issue list
-* Added a couple of new formats for the 'date format' setting
-* Added Traditional Chinese translation (by Shortie Lo)
-* Added Russian translation (iGor kMeta)
-* Project name format limitation removed (name can now contain any character)
-* Project identifier maximum length changed from 12 to 20
-* Changed the maximum length of LDAP account to 255 characters
-* Removed the 12 characters limit on passwords
-* Added wiki macros support
-* Performance improvement on workflow setup screen
-* More detailed html title on several views
-* Custom fields can now be reordered
-* Search engine: search can be restricted to an exact phrase by using quotation marks
-* Added custom fields marked as 'For all projects' to the csv export of the cross project issue list
-* Email notifications are now sent as Blind carbon copy by default
-* Fixed: all members (including non active) should be deleted when deleting a project
-* Fixed: Error on wiki syntax link (accessible from wiki/edit)
-* Fixed: 'quick jump to a revision' form on the revisions list
-* Fixed: error on admin/info if there's more than 1 plugin installed
-* Fixed: svn or ldap password can be found in clear text in the html source in editing mode
-* Fixed: 'Assigned to' drop down list is not sorted
-* Fixed: 'View all issues' link doesn't work on issues/show
-* Fixed: error on account/register when validation fails
-* Fixed: Error when displaying the issue list if a float custom field is marked as 'used as filter'
-* Fixed: Mercurial adapter breaks on missing :files entry in changeset hash (James Britt)
-* Fixed: Wrong feed URLs on the home page
-* Fixed: Update of time entry fails when the issue has been moved to an other project
-* Fixed: Error when moving an issue without changing its tracker (Postgresql)
-* Fixed: Changes not recorded when using :pserver string (CVS adapter)
-* Fixed: admin should be able to move issues to any project
-* Fixed: adding an attachment is not possible when changing the status of an issue
-* Fixed: No mime-types in documents/files downloading
-* Fixed: error when sorting the messages if there's only one board for the project
-* Fixed: 'me' doesn't appear in the drop down filters on a project issue list.
-
-== 2007-11-04 v0.6.0
-
-* Permission model refactoring.
-* Permissions: there are now 2 builtin roles that can be used to specify permissions given to other users than members of projects
-* Permissions: some permissions (eg. browse the repository) can be removed for certain roles
-* Permissions: modules (eg. issue tracking, news, documents...) can be enabled/disabled at project level
-* Added Mantis and Trac importers
-* New application layout
-* Added "Bulk edit" functionality on the issue list
-* More flexible mail notifications settings at user level
-* Added AJAX based context menu on the project issue list that provide shortcuts for editing, re-assigning, changing the status or the priority, moving or deleting an issue
-* Added the hability to copy an issue. It can be done from the "issue/show" view or from the context menu on the issue list
-* Added the ability to customize issue list columns (at application level or for each saved query)
-* Overdue versions (date reached and open issues > 0) are now always displayed on the roadmap
-* Added the ability to rename wiki pages (specific permission required)
-* Search engines now supports pagination. Results are sorted in reverse chronological order
-* Added "Estimated hours" attribute on issues
-* A category with assigned issue can now be deleted. 2 options are proposed: remove assignments or reassign issues to another category
-* Forum notifications are now also sent to the authors of the thread, even if they don�t watch the board
-* Added an application setting to specify the application protocol (http or https) used to generate urls in emails
-* Gantt chart: now starts at the current month by default
-* Gantt chart: month count and zoom factor are automatically saved as user preferences
-* Wiki links can now refer to other project wikis
-* Added wiki index by date
-* Added preview on add/edit issue form
-* Emails footer can now be customized from the admin interface (Admin -> Email notifications)
-* Default encodings for repository files can now be set in application settings (used to convert files content and diff to UTF-8 so that they�re properly displayed)
-* Calendar: first day of week can now be set in lang files
-* Automatic closing of duplicate issues
-* Added a cross-project issue list
-* AJAXified the SCM browser (tree view)
-* Pretty URL for the repository browser (Cyril Mougel)
-* Search engine: added a checkbox to search titles only
-* Added "% done" in the filter list
-* Enumerations: values can now be reordered and a default value can be specified (eg. default issue priority)
-* Added some accesskeys
-* Added "Float" as a custom field format
-* Added basic Theme support
-* Added the ability to set the �done ratio� of issues fixed by commit (Nikolay Solakov)
-* Added custom fields in issue related mail notifications
-* Email notifications are now sent in plain text and html
-* Gantt chart can now be exported to a graphic file (png). This functionality is only available if RMagick is installed.
-* Added syntax highlightment for repository files and wiki
-* Improved automatic Redmine links
-* Added automatic table of content support on wiki pages
-* Added radio buttons on the documents list to sort documents by category, date, title or author
-* Added basic plugin support, with a sample plugin
-* Added a link to add a new category when creating or editing an issue
-* Added a "Assignable" boolean on the Role model. If unchecked, issues can not be assigned to users having this role.
-* Added an option to be able to relate issues in different projects
-* Added the ability to move issues (to another project) without changing their trackers.
-* Atom feeds added on project activity, news and changesets
-* Added the ability to reset its own RSS access key
-* Main project list now displays root projects with their subprojects
-* Added anchor links to issue notes
-* Added reposman Ruby version. This script can now register created repositories in Redmine (Nicolas Chuche)
-* Issue notes are now included in search
-* Added email sending test functionality
-* Added LDAPS support for LDAP authentication
-* Removed hard-coded URLs in mail templates
-* Subprojects are now grouped by projects in the navigation drop-down menu
-* Added a new value for date filters: this week
-* Added cache for application settings
-* Added Polish translation (Tomasz Gawryl)
-* Added Czech translation (Jan Kadlecek)
-* Added Romanian translation (Csongor Bartus)
-* Added Hebrew translation (Bob Builder)
-* Added Serbian translation (Dragan Matic)
-* Added Korean translation (Choi Jong Yoon)
-* Fixed: the link to delete issue relations is displayed even if the user is not authorized to delete relations
-* Performance improvement on calendar and gantt
-* Fixed: wiki preview doesn�t work on long entries
-* Fixed: queries with multiple custom fields return no result
-* Fixed: Can not authenticate user against LDAP if its DN contains non-ascii characters
-* Fixed: URL with ~ broken in wiki formatting
-* Fixed: some quotation marks are rendered as strange characters in pdf
-
-
-== 2007-07-15 v0.5.1
-
-* per project forums added
-* added the ability to archive projects
-* added �Watch� functionality on issues. It allows users to receive notifications about issue changes
-* custom fields for issues can now be used as filters on issue list
-* added per user custom queries
-* commit messages are now scanned for referenced or fixed issue IDs (keywords defined in Admin -> Settings)
-* projects list now shows the list of public projects and private projects for which the user is a member
-* versions can now be created with no date
-* added issue count details for versions on Reports view
-* added time report, by member/activity/tracker/version and year/month/week for the selected period
-* each category can now be associated to a user, so that new issues in that category are automatically assigned to that user
-* added autologin feature (disabled by default)
-* optimistic locking added for wiki edits
-* added wiki diff
-* added the ability to destroy wiki pages (requires permission)
-* a wiki page can now be attached to each version, and displayed on the roadmap
-* attachments can now be added to wiki pages (original patch by Pavol Murin) and displayed online
-* added an option to see all versions in the roadmap view (including completed ones)
-* added basic issue relations
-* added the ability to log time when changing an issue status
-* account information can now be sent to the user when creating an account
-* author and assignee of an issue always receive notifications (even if they turned of mail notifications)
-* added a quick search form in page header
-* added 'me' value for 'assigned to' and 'author' query filters
-* added a link on revision screen to see the entire diff for the revision
-* added last commit message for each entry in repository browser
-* added the ability to view a file diff with free to/from revision selection.
-* text files can now be viewed online when browsing the repository
-* added basic support for other SCM: CVS (Ralph Vater), Mercurial and Darcs
-* added fragment caching for svn diffs
-* added fragment caching for calendar and gantt views
-* login field automatically focused on login form
-* subproject name displayed on issue list, calendar and gantt
-* added an option to choose the date format: language based or ISO 8601
-* added a simple mail handler. It lets users add notes to an existing issue by replying to the initial notification email.
-* a 403 error page is now displayed (instead of a blank page) when trying to access a protected page
-* added portuguese translation (Joao Carlos Clementoni)
-* added partial online help japanese translation (Ken Date)
-* added bulgarian translation (Nikolay Solakov)
-* added dutch translation (Linda van den Brink)
-* added swedish translation (Thomas Habets)
-* italian translation update (Alessio Spadaro)
-* japanese translation update (Satoru Kurashiki)
-* fixed: error on history atom feed when there�s no notes on an issue change
-* fixed: error in journalizing an issue with longtext custom fields (Postgresql)
-* fixed: creation of Oracle schema
-* fixed: last day of the month not included in project activity
-* fixed: files with an apostrophe in their names can't be accessed in SVN repository
-* fixed: performance issue on RepositoriesController#revisions when a changeset has a great number of changes (eg. 100,000)
-* fixed: open/closed issue counts are always 0 on reports view (postgresql)
-* fixed: date query filters (wrong results and sql error with postgresql)
-* fixed: confidentiality issue on account/show (private project names displayed to anyone)
-* fixed: Long text custom fields displayed without line breaks
-* fixed: Error when editing the wokflow after deleting a status
-* fixed: SVN commit dates are now stored as local time
-
-
-== 2007-04-11 v0.5.0
-
-* added per project Wiki
-* added rss/atom feeds at project level (custom queries can be used as feeds)
-* added search engine (search in issues, news, commits, wiki pages, documents)
-* simple time tracking functionality added
-* added version due dates on calendar and gantt
-* added subprojects issue count on project Reports page
-* added the ability to copy an existing workflow when creating a new tracker
-* added the ability to include subprojects on calendar and gantt
-* added the ability to select trackers to display on calendar and gantt (Jeffrey Jones)
-* added side by side svn diff view (Cyril Mougel)
-* added back subproject filter on issue list
-* added permissions report in admin area
-* added a status filter on users list
-* support for password-protected SVN repositories
-* SVN commits are now stored in the database
-* added simple svn statistics SVG graphs
-* progress bars for roadmap versions (Nick Read)
-* issue history now shows file uploads and deletions
-* #id patterns are turned into links to issues in descriptions and commit messages
-* japanese translation added (Satoru Kurashiki)
-* chinese simplified translation added (Andy Wu)
-* italian translation added (Alessio Spadaro)
-* added scripts to manage SVN repositories creation and user access control using ssh+svn (Nicolas Chuche)
-* better calendar rendering time
-* fixed migration scripts to work with mysql 5 running in strict mode
-* fixed: error when clicking "add" with no block selected on my/page_layout
-* fixed: hard coded links in navigation bar
-* fixed: table_name pre/suffix support
-
-
-== 2007-02-18 v0.4.2
-
-* Rails 1.2 is now required
-* settings are now stored in the database and editable through the application in: Admin -> Settings (config_custom.rb is no longer used)
-* added project roadmap view
-* mail notifications added when a document, a file or an attachment is added
-* tooltips added on Gantt chart and calender to view the details of the issues
-* ability to set the sort order for roles, trackers, issue statuses
-* added missing fields to csv export: priority, start date, due date, done ratio
-* added total number of issues per tracker on project overview
-* all icons replaced (new icons are based on GPL icon set: "KDE Crystal Diamond 2.5" -by paolino- and "kNeu! Alpha v0.1" -by Pablo Fabregat-)
-* added back "fixed version" field on issue screen and in filters
-* project settings screen split in 4 tabs
-* custom fields screen split in 3 tabs (one for each kind of custom field)
-* multiple issues pdf export now rendered as a table
-* added a button on users/list to manually activate an account
-* added a setting option to disable "password lost" functionality
-* added a setting option to set max number of issues in csv/pdf exports
-* fixed: subprojects count is always 0 on projects list
-* fixed: locked users are proposed when adding a member to a project
-* fixed: setting an issue status as default status leads to an sql error with SQLite
-* fixed: unable to delete an issue status even if it's not used yet
-* fixed: filters ignored when exporting a predefined query to csv/pdf
-* fixed: crash when french "issue_edit" email notification is sent
-* fixed: hide mail preference not saved (my/account)
-* fixed: crash when a new user try to edit its "my page" layout
-
-
-== 2007-01-03 v0.4.1
-
-* fixed: emails have no recipient when one of the project members has notifications disabled
-
-
-== 2007-01-02 v0.4.0
-
-* simple SVN browser added (just needs svn binaries in PATH)
-* comments can now be added on news
-* "my page" is now customizable 
-* more powerfull and savable filters for issues lists
-* improved issues change history
-* new functionality: move an issue to another project or tracker
-* new functionality: add a note to an issue
-* new report: project activity
-* "start date" and "% done" fields added on issues
-* project calendar added
-* gantt chart added (exportable to pdf)
-* single/multiple issues pdf export added
-* issues reports improvements
-* multiple file upload for issues, documents and files
-* option to set maximum size of uploaded files
-* textile formating of issue and news descritions (RedCloth required)
-* integration of DotClear jstoolbar for textile formatting
-* calendar date picker for date fields (LGPL DHTML Calendar http://sourceforge.net/projects/jscalendar)
-* new filter in issues list: Author
-* ajaxified paginators
-* news rss feed added
-* option to set number of results per page on issues list
-* localized csv separator (comma/semicolon)
-* csv output encoded to ISO-8859-1
-* user custom field displayed on account/show
-* default configuration improved (default roles, trackers, status, permissions and workflows)
-* language for default configuration data can now be chosen when running 'load_default_data' task
-* javascript added on custom field form to show/hide fields according to the format of custom field
-* fixed: custom fields not in csv exports
-* fixed: project settings now displayed according to user's permissions
-* fixed: application error when no version is selected on projects/add_file
-* fixed: public actions not authorized for members of non public projects
-* fixed: non public projects were shown on welcome screen even if current user is not a member
-
-
-== 2006-10-08 v0.3.0
-
-* user authentication against multiple LDAP (optional)
-* token based "lost password" functionality
-* user self-registration functionality (optional)
-* custom fields now available for issues, users and projects
-* new custom field format "text" (displayed as a textarea field) 
-* project & administration drop down menus in navigation bar for quicker access
-* text formatting is preserved for long text fields (issues, projects and news descriptions)
-* urls and emails are turned into clickable links in long text fields
-* "due date" field added on issues
-* tracker selection filter added on change log
-* Localization plugin replaced with GLoc 1.1.0 (iconv required)
-* error messages internationalization
-* german translation added (thanks to Karim Trott)
-* data locking for issues to prevent update conflicts (using ActiveRecord builtin optimistic locking)
-* new filter in issues list: "Fixed version"
-* active filters are displayed with colored background on issues list
-* custom configuration is now defined in config/config_custom.rb
-* user object no more stored in session (only user_id)
-* news summary field is no longer required
-* tables and forms redesign
-* Fixed: boolean custom field not working
-* Fixed: error messages for custom fields are not displayed
-* Fixed: invalid custom fields should have a red border
-* Fixed: custom fields values are not validated on issue update
-* Fixed: unable to choose an empty value for 'List' custom fields
-* Fixed: no issue categories sorting
-* Fixed: incorrect versions sorting
-
-
-== 2006-07-12 - v0.2.2
-
-* Fixed: bug in "issues list"
-
-
-== 2006-07-09 - v0.2.1
-
-* new databases supported: Oracle, PostgreSQL, SQL Server
-* projects/subprojects hierarchy (1 level of subprojects only)
-* environment information display in admin/info
-* more filter options in issues list (rev6)
-* default language based on browser settings (Accept-Language HTTP header)
-* issues list exportable to CSV (rev6)
-* simple_format and auto_link on long text fields
-* more data validations
-* Fixed: error when all mail notifications are unchecked in admin/mail_options
-* Fixed: all project news are displayed on project summary
-* Fixed: Can't change user password in users/edit
-* Fixed: Error on tables creation with PostgreSQL (rev5)
-* Fixed: SQL error in "issue reports" view with PostgreSQL (rev5)
-
-
-== 2006-06-25 - v0.1.0
-
-* multiple users/multiple projects
-* role based access control
-* issue tracking system
-* fully customizable workflow
-* documents/files repository
-* email notifications on issue creation and update
-* multilanguage support (except for error messages):english, french, spanish
-* online manual in french (unfinished)
--- a/.svn/pristine/79/79e517db7aa41460bc02061dfd2de5b4541e346b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingSearchTest < ActionController::IntegrationTest
-  def test_search
-    assert_routing(
-        { :method => 'get', :path => "/search" },
-        { :controller => 'search', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/foo/search" },
-        { :controller => 'search', :action => 'index', :id => 'foo' }
-      )
-  end
-end
--- a/.svn/pristine/7a/7a0c6d75615202ef4fc661b90d1880959dd6577d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class AdminController < ApplicationController
-  layout 'admin'
-  menu_item :projects, :only => :projects
-  menu_item :plugins, :only => :plugins
-  menu_item :info, :only => :info
-
-  before_filter :require_admin
-  helper :sort
-  include SortHelper
-
-  def index
-    @no_configuration_data = Redmine::DefaultData::Loader::no_data?
-  end
-
-  def projects
-    @status = params[:status] || 1
-
-    scope = Project.status(@status).order('lft')
-    scope = scope.like(params[:name]) if params[:name].present?
-    @projects = scope.all
-
-    render :action => "projects", :layout => false if request.xhr?
-  end
-
-  def plugins
-    @plugins = Redmine::Plugin.all
-  end
-
-  # Loads the default configuration
-  # (roles, trackers, statuses, workflow, enumerations)
-  def default_configuration
-    if request.post?
-      begin
-        Redmine::DefaultData::Loader::load(params[:lang])
-        flash[:notice] = l(:notice_default_data_loaded)
-      rescue Exception => e
-        flash[:error] = l(:error_can_t_load_default_data, e.message)
-      end
-    end
-    redirect_to admin_path
-  end
-
-  def test_email
-    raise_delivery_errors = ActionMailer::Base.raise_delivery_errors
-    # Force ActionMailer to raise delivery errors so we can catch it
-    ActionMailer::Base.raise_delivery_errors = true
-    begin
-      @test = Mailer.test_email(User.current).deliver
-      flash[:notice] = l(:notice_email_sent, User.current.mail)
-    rescue Exception => e
-      flash[:error] = l(:notice_email_error, Redmine::CodesetUtil.replace_invalid_utf8(e.message))
-    end
-    ActionMailer::Base.raise_delivery_errors = raise_delivery_errors
-    redirect_to settings_path(:tab => 'notifications')
-  end
-
-  def info
-    @db_adapter_name = ActiveRecord::Base.connection.adapter_name
-    @checklist = [
-      [:text_default_administrator_account_changed, User.default_admin_account_changed?],
-      [:text_file_repository_writable, File.writable?(Attachment.storage_path)],
-      [:text_plugin_assets_writable,   File.writable?(Redmine::Plugin.public_directory)],
-      [:text_rmagick_available,        Object.const_defined?(:Magick)],
-      [:text_convert_available,        Redmine::Thumbnail.convert_available?]
-    ]
-  end
-end
--- a/.svn/pristine/7a/7ae54c43f56efaece5e4ecd309a31e0849a96145.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,297 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module RepositoriesHelper
-  def format_revision(revision)
-    if revision.respond_to? :format_identifier
-      revision.format_identifier
-    else
-      revision.to_s
-    end
-  end
-
-  def truncate_at_line_break(text, length = 255)
-    if text
-      text.gsub(%r{^(.{#{length}}[^\n]*)\n.+$}m, '\\1...')
-    end
-  end
-
-  def render_properties(properties)
-    unless properties.nil? || properties.empty?
-      content = ''
-      properties.keys.sort.each do |property|
-        content << content_tag('li', "<b>#{h property}</b>: <span>#{h properties[property]}</span>".html_safe)
-      end
-      content_tag('ul', content.html_safe, :class => 'properties')
-    end
-  end
-
-  def render_changeset_changes
-    changes = @changeset.filechanges.limit(1000).reorder('path').all.collect do |change|
-      case change.action
-      when 'A'
-        # Detects moved/copied files
-        if !change.from_path.blank?
-          change.action =
-             @changeset.filechanges.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C'
-        end
-        change
-      when 'D'
-        @changeset.filechanges.detect {|c| c.from_path == change.path} ? nil : change
-      else
-        change
-      end
-    end.compact
-
-    tree = { }
-    changes.each do |change|
-      p = tree
-      dirs = change.path.to_s.split('/').select {|d| !d.blank?}
-      path = ''
-      dirs.each do |dir|
-        path += '/' + dir
-        p[:s] ||= {}
-        p = p[:s]
-        p[path] ||= {}
-        p = p[path]
-      end
-      p[:c] = change
-    end
-    render_changes_tree(tree[:s])
-  end
-
-  def render_changes_tree(tree)
-    return '' if tree.nil?
-    output = ''
-    output << '<ul>'
-    tree.keys.sort.each do |file|
-      style = 'change'
-      text = File.basename(h(file))
-      if s = tree[file][:s]
-        style << ' folder'
-        path_param = to_path_param(@repository.relative_path(file))
-        text = link_to(h(text), :controller => 'repositories',
-                             :action => 'show',
-                             :id => @project,
-                             :repository_id => @repository.identifier_param,
-                             :path => path_param,
-                             :rev => @changeset.identifier)
-        output << "<li class='#{style}'>#{text}"
-        output << render_changes_tree(s)
-        output << "</li>"
-      elsif c = tree[file][:c]
-        style << " change-#{c.action}"
-        path_param = to_path_param(@repository.relative_path(c.path))
-        text = link_to(h(text), :controller => 'repositories',
-                             :action => 'entry',
-                             :id => @project,
-                             :repository_id => @repository.identifier_param,
-                             :path => path_param,
-                             :rev => @changeset.identifier) unless c.action == 'D'
-        text << " - #{h(c.revision)}" unless c.revision.blank?
-        text << ' ('.html_safe + link_to(l(:label_diff), :controller => 'repositories',
-                                       :action => 'diff',
-                                       :id => @project,
-                                       :repository_id => @repository.identifier_param,
-                                       :path => path_param,
-                                       :rev => @changeset.identifier) + ') '.html_safe if c.action == 'M'
-        text << ' '.html_safe + content_tag('span', h(c.from_path), :class => 'copied-from') unless c.from_path.blank?
-        output << "<li class='#{style}'>#{text}</li>"
-      end
-    end
-    output << '</ul>'
-    output.html_safe
-  end
-
-  def repository_field_tags(form, repository)
-    method = repository.class.name.demodulize.underscore + "_field_tags"
-    if repository.is_a?(Repository) &&
-        respond_to?(method) && method != 'repository_field_tags'
-      send(method, form, repository)
-    end
-  end
-
-  def scm_select_tag(repository)
-    scm_options = [["--- #{l(:actionview_instancetag_blank_option)} ---", '']]
-    Redmine::Scm::Base.all.each do |scm|
-    if Setting.enabled_scm.include?(scm) ||
-          (repository && repository.class.name.demodulize == scm)
-        scm_options << ["Repository::#{scm}".constantize.scm_name, scm]
-      end
-    end
-    select_tag('repository_scm',
-               options_for_select(scm_options, repository.class.name.demodulize),
-               :disabled => (repository && !repository.new_record?),
-               :data => {:remote => true, :method => 'get'})
-  end
-
-  def with_leading_slash(path)
-    path.to_s.starts_with?('/') ? path : "/#{path}"
-  end
-
-  def without_leading_slash(path)
-    path.gsub(%r{^/+}, '')
-  end
-
-  def subversion_field_tags(form, repository)
-      content_tag('p', form.text_field(:url, :size => 60, :required => true,
-                       :disabled => !repository.safe_attribute?('url')) +
-                       '<br />'.html_safe +
-                       '(file:///, http://, https://, svn://, svn+[tunnelscheme]://)') +
-      content_tag('p', form.text_field(:login, :size => 30)) +
-      content_tag('p', form.password_field(
-                            :password, :size => 30, :name => 'ignore',
-                            :value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)),
-                            :onfocus => "this.value=''; this.name='repository[password]';",
-                            :onchange => "this.name='repository[password]';"))
-  end
-
-  def darcs_field_tags(form, repository)
-    content_tag('p', form.text_field(
-                     :url, :label => l(:field_path_to_repository),
-                     :size => 60, :required => true,
-                     :disabled => !repository.safe_attribute?('url'))) +
-    content_tag('p', form.select(
-                     :log_encoding, [nil] + Setting::ENCODINGS,
-                     :label => l(:field_commit_logs_encoding), :required => true))
-  end
-
-  def mercurial_field_tags(form, repository)
-    content_tag('p', form.text_field(
-                       :url, :label => l(:field_path_to_repository),
-                       :size => 60, :required => true,
-                       :disabled => !repository.safe_attribute?('url')
-                         ) +
-                     '<br />'.html_safe + l(:text_mercurial_repository_note)) +
-    content_tag('p', form.select(
-                        :path_encoding, [nil] + Setting::ENCODINGS,
-                        :label => l(:field_scm_path_encoding)
-                        ) +
-                     '<br />'.html_safe + l(:text_scm_path_encoding_note))
-  end
-
-  def git_field_tags(form, repository)
-    content_tag('p', form.text_field(
-                       :url, :label => l(:field_path_to_repository),
-                       :size => 60, :required => true,
-                       :disabled => !repository.safe_attribute?('url')
-                         ) +
-                      '<br />'.html_safe +
-                      l(:text_git_repository_note)) +
-    content_tag('p', form.select(
-                        :path_encoding, [nil] + Setting::ENCODINGS,
-                        :label => l(:field_scm_path_encoding)
-                        ) +
-                     '<br />'.html_safe + l(:text_scm_path_encoding_note)) +
-    content_tag('p', form.check_box(
-                        :extra_report_last_commit,
-                        :label => l(:label_git_report_last_commit)
-                         ))
-  end
-
-  def cvs_field_tags(form, repository)
-    content_tag('p', form.text_field(
-                     :root_url,
-                     :label => l(:field_cvsroot),
-                     :size => 60, :required => true,
-                     :disabled => !repository.safe_attribute?('root_url'))) +
-    content_tag('p', form.text_field(
-                     :url,
-                     :label => l(:field_cvs_module),
-                     :size => 30, :required => true,
-                     :disabled => !repository.safe_attribute?('url'))) +
-    content_tag('p', form.select(
-                     :log_encoding, [nil] + Setting::ENCODINGS,
-                     :label => l(:field_commit_logs_encoding), :required => true)) +
-    content_tag('p', form.select(
-                        :path_encoding, [nil] + Setting::ENCODINGS,
-                        :label => l(:field_scm_path_encoding)
-                        ) +
-                     '<br />'.html_safe + l(:text_scm_path_encoding_note))
-  end
-
-  def bazaar_field_tags(form, repository)
-    content_tag('p', form.text_field(
-                     :url, :label => l(:field_path_to_repository),
-                     :size => 60, :required => true,
-                     :disabled => !repository.safe_attribute?('url'))) +
-    content_tag('p', form.select(
-                     :log_encoding, [nil] + Setting::ENCODINGS,
-                     :label => l(:field_commit_logs_encoding), :required => true))
-  end
-
-  def filesystem_field_tags(form, repository)
-    content_tag('p', form.text_field(
-                     :url, :label => l(:field_root_directory),
-                     :size => 60, :required => true,
-                     :disabled => !repository.safe_attribute?('url'))) +
-    content_tag('p', form.select(
-                        :path_encoding, [nil] + Setting::ENCODINGS,
-                        :label => l(:field_scm_path_encoding)
-                        ) +
-                     '<br />'.html_safe + l(:text_scm_path_encoding_note))
-  end
-
-  def index_commits(commits, heads)
-    return nil if commits.nil? or commits.first.parents.nil?
-    refs_map = {}
-    heads.each do |head|
-      refs_map[head.scmid] ||= []
-      refs_map[head.scmid] << head
-    end
-    commits_by_scmid = {}
-    commits.reverse.each_with_index do |commit, commit_index|
-      commits_by_scmid[commit.scmid] = {
-        :parent_scmids => commit.parents.collect { |parent| parent.scmid },
-        :rdmid => commit_index,
-        :refs  => refs_map.include?(commit.scmid) ? refs_map[commit.scmid].join(" ") : nil,
-        :scmid => commit.scmid,
-        :href  => block_given? ? yield(commit.scmid) : commit.scmid
-      }
-    end
-    heads.sort! { |head1, head2| head1.to_s <=> head2.to_s }
-    space = nil  
-    heads.each do |head|
-      if commits_by_scmid.include? head.scmid
-        space = index_head((space || -1) + 1, head, commits_by_scmid)
-      end
-    end
-    # when no head matched anything use first commit
-    space ||= index_head(0, commits.first, commits_by_scmid)
-    return commits_by_scmid, space
-  end
-
-  def index_head(space, commit, commits_by_scmid)
-    stack = [[space, commits_by_scmid[commit.scmid]]]
-    max_space = space
-    until stack.empty?
-      space, commit = stack.pop
-      commit[:space] = space if commit[:space].nil?
-      space -= 1
-      commit[:parent_scmids].each_with_index do |parent_scmid, parent_index|
-        parent_commit = commits_by_scmid[parent_scmid]
-        if parent_commit and parent_commit[:space].nil?
-          stack.unshift [space += 1, parent_commit]
-        end
-      end
-      max_space = space if max_space < space
-    end
-    max_space
-  end
-end
--- a/.svn/pristine/7b/7b2768a4d4eb7647598cd0f016196785ba208ee6.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module VersionsHelper
-
-  def version_anchor(version)
-    if @project == version.project
-      anchor version.name
-    else
-      anchor "#{version.project.try(:identifier)}-#{version.name}"
-    end
-  end
-
-  STATUS_BY_CRITERIAS = %w(tracker status priority author assigned_to category)
-
-  def render_issue_status_by(version, criteria)
-    criteria = 'tracker' unless STATUS_BY_CRITERIAS.include?(criteria)
-
-    h = Hash.new {|k,v| k[v] = [0, 0]}
-    begin
-      # Total issue count
-      Issue.where(:fixed_version_id => version.id).group(criteria).count.each {|c,s| h[c][0] = s}
-      # Open issues count
-      Issue.open.where(:fixed_version_id => version.id).group(criteria).count.each {|c,s| h[c][1] = s}
-    rescue ActiveRecord::RecordNotFound
-    # When grouping by an association, Rails throws this exception if there's no result (bug)
-    end
-    # Sort with nil keys in last position
-    counts = h.keys.sort {|a,b| a.nil? ? 1 : (b.nil? ? -1 : a <=> b)}.collect {|k| {:group => k, :total => h[k][0], :open => h[k][1], :closed => (h[k][0] - h[k][1])}}
-    max = counts.collect {|c| c[:total]}.max
-
-    render :partial => 'issue_counts', :locals => {:version => version, :criteria => criteria, :counts => counts, :max => max}
-  end
-
-  def status_by_options_for_select(value)
-    options_for_select(STATUS_BY_CRITERIAS.collect {|criteria| [l("field_#{criteria}".to_sym), criteria]}, value)
-  end
-end
--- a/.svn/pristine/7b/7b34d32f77bf4ac1a9acbab33d65a9b853c9c460.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class ActivitiesHelperTest < ActionView::TestCase
-  include ActivitiesHelper
-  include Redmine::I18n
-
-  class MockEvent
-    attr_reader :event_datetime, :event_group, :name
-
-    def initialize(group=nil)
-      @@count ||= 0
-      @name = "e#{@@count}"
-      @event_datetime = Time.now + @@count.hours
-      @event_group = group || self
-      @@count += 1
-    end
-
-    def self.clear
-      @@count = 0
-    end
-  end
-
-  def setup
-    MockEvent.clear
-  end
-
-  def test_sort_activity_events_should_sort_by_datetime
-    events = []
-    events << MockEvent.new
-    events << MockEvent.new
-    events << MockEvent.new
-
-    assert_equal [
-        ['e2', false],
-        ['e1', false],
-        ['e0', false]
-      ], sort_activity_events(events).map {|event, grouped| [event.name, grouped]}
-  end
-
-  def test_sort_activity_events_should_group_events
-    events = []
-    events << MockEvent.new
-    events << MockEvent.new(events[0])
-    events << MockEvent.new(events[0])
-
-    assert_equal [
-        ['e2', false],
-        ['e1', true],
-        ['e0', true]
-      ], sort_activity_events(events).map {|event, grouped| [event.name, grouped]}
-  end
-
-  def test_sort_activity_events_with_group_not_in_set_should_group_events
-    e = MockEvent.new
-    events = []
-    events << MockEvent.new(e)
-    events << MockEvent.new(e)
-
-    assert_equal [
-        ['e2', false],
-        ['e1', true]
-      ], sort_activity_events(events).map {|event, grouped| [event.name, grouped]}
-  end
-
-  def test_sort_activity_events_should_sort_by_datetime_and_group
-    events = []
-    events << MockEvent.new
-    events << MockEvent.new
-    events << MockEvent.new
-    events << MockEvent.new(events[1])
-    events << MockEvent.new(events[2])
-    events << MockEvent.new
-    events << MockEvent.new(events[2])
-
-    assert_equal [
-        ['e6', false],
-        ['e4', true],
-        ['e2', true],
-        ['e5', false],
-        ['e3', false],
-        ['e1', true],
-        ['e0', false]
-      ], sort_activity_events(events).map {|event, grouped| [event.name, grouped]}
-  end
-end
--- a/.svn/pristine/7b/7b4fab45dadc851ece3c8f70d2660b6cfb36eddc.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WikiRedirectTest < ActiveSupport::TestCase
-  fixtures :projects, :wikis, :wiki_pages
-
-  def setup
-    @wiki = Wiki.find(1)
-    @original = WikiPage.create(:wiki => @wiki, :title => 'Original title')
-  end
-
-  def test_create_redirect
-    @original.title = 'New title'
-    assert @original.save
-    @original.reload
-
-    assert_equal 'New_title', @original.title
-    assert @wiki.redirects.find_by_title('Original_title')
-    assert @wiki.find_page('Original title')
-    assert @wiki.find_page('ORIGINAL title')
-  end
-
-  def test_update_redirect
-    # create a redirect that point to this page
-    assert WikiRedirect.create(:wiki => @wiki, :title => 'An_old_page', :redirects_to => 'Original_title')
-
-    @original.title = 'New title'
-    @original.save
-    # make sure the old page now points to the new page
-    assert_equal 'New_title', @wiki.find_page('An old page').title
-  end
-
-  def test_reverse_rename
-    # create a redirect that point to this page
-    assert WikiRedirect.create(:wiki => @wiki, :title => 'An_old_page', :redirects_to => 'Original_title')
-
-    @original.title = 'An old page'
-    @original.save
-    assert !@wiki.redirects.find_by_title_and_redirects_to('An_old_page', 'An_old_page')
-    assert @wiki.redirects.find_by_title_and_redirects_to('Original_title', 'An_old_page')
-  end
-
-  def test_rename_to_already_redirected
-    assert WikiRedirect.create(:wiki => @wiki, :title => 'An_old_page', :redirects_to => 'Other_page')
-
-    @original.title = 'An old page'
-    @original.save
-    # this redirect have to be removed since 'An old page' page now exists
-    assert !@wiki.redirects.find_by_title_and_redirects_to('An_old_page', 'Other_page')
-  end
-
-  def test_redirects_removed_when_deleting_page
-    assert WikiRedirect.create(:wiki => @wiki, :title => 'An_old_page', :redirects_to => 'Original_title')
-
-    @original.destroy
-    assert_nil @wiki.redirects.first
-  end
-end
--- a/.svn/pristine/7b/7b5e0d5bd15f4cf751b3c4e4e461784203fe4354.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueCustomFieldTest < ActiveSupport::TestCase
-  include Redmine::I18n
-
-  fixtures :roles
-
-  def test_custom_field_with_visible_set_to_false_should_validate_roles
-    set_language_if_valid 'en'
-    field = IssueCustomField.new(:name => 'Field', :field_format => 'string', :visible => false)
-    assert !field.save
-    assert_include "Roles can't be blank", field.errors.full_messages
-    field.role_ids = [1, 2]
-    assert field.save
-  end
-
-  def test_changing_visible_to_true_should_clear_roles
-    field = IssueCustomField.create!(:name => 'Field', :field_format => 'string', :visible => false, :role_ids => [1, 2])
-    assert_equal 2, field.roles.count
-
-    field.visible = true
-    field.save!
-    assert_equal 0, field.roles.count
-  end
-end
--- a/.svn/pristine/7b/7b79b397a58396e6741da83eb4295f4a9b8a4385.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2303 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueTest < ActiveSupport::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles,
-           :groups_users,
-           :trackers, :projects_trackers,
-           :enabled_modules,
-           :versions,
-           :issue_statuses, :issue_categories, :issue_relations, :workflows,
-           :enumerations,
-           :issues, :journals, :journal_details,
-           :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
-           :time_entries
-
-  include Redmine::I18n
-
-  def teardown
-    User.current = nil
-  end
-
-  def test_initialize
-    issue = Issue.new
-
-    assert_nil issue.project_id
-    assert_nil issue.tracker_id
-    assert_nil issue.author_id
-    assert_nil issue.assigned_to_id
-    assert_nil issue.category_id
-
-    assert_equal IssueStatus.default, issue.status
-    assert_equal IssuePriority.default, issue.priority
-  end
-
-  def test_create
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
-                      :status_id => 1, :priority => IssuePriority.all.first,
-                      :subject => 'test_create',
-                      :description => 'IssueTest#test_create', :estimated_hours => '1:30')
-    assert issue.save
-    issue.reload
-    assert_equal 1.5, issue.estimated_hours
-  end
-
-  def test_create_minimal
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
-                      :status_id => 1, :priority => IssuePriority.all.first,
-                      :subject => 'test_create')
-    assert issue.save
-    assert issue.description.nil?
-    assert_nil issue.estimated_hours
-  end
-
-  def test_start_date_format_should_be_validated
-    set_language_if_valid 'en'
-    ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
-      issue = Issue.new(:start_date => invalid_date)
-      assert !issue.valid?
-      assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
-    end
-  end
-
-  def test_due_date_format_should_be_validated
-    set_language_if_valid 'en'
-    ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
-      issue = Issue.new(:due_date => invalid_date)
-      assert !issue.valid?
-      assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
-    end
-  end
-
-  def test_due_date_lesser_than_start_date_should_not_validate
-    set_language_if_valid 'en'
-    issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
-    assert !issue.valid?
-    assert_include 'Due date must be greater than start date', issue.errors.full_messages
-  end
-
-  def test_start_date_lesser_than_soonest_start_should_not_validate_on_create
-    issue = Issue.generate(:start_date => '2013-06-04')
-    issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
-    assert !issue.valid?
-    assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
-  end
-
-  def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed
-    issue = Issue.generate!(:start_date => '2013-06-04')
-    issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
-    issue.start_date = '2013-06-07'
-    assert !issue.valid?
-    assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
-  end
-
-  def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged
-    issue = Issue.generate!(:start_date => '2013-06-04')
-    issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
-    assert issue.valid?
-  end
-
-  def test_estimated_hours_should_be_validated
-    set_language_if_valid 'en'
-    ['-2'].each do |invalid|
-      issue = Issue.new(:estimated_hours => invalid)
-      assert !issue.valid?
-      assert_include 'Estimated time is invalid', issue.errors.full_messages
-    end
-  end
-
-  def test_create_with_required_custom_field
-    set_language_if_valid 'en'
-    field = IssueCustomField.find_by_name('Database')
-    field.update_attribute(:is_required, true)
-
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
-                      :status_id => 1, :subject => 'test_create',
-                      :description => 'IssueTest#test_create_with_required_custom_field')
-    assert issue.available_custom_fields.include?(field)
-    # No value for the custom field
-    assert !issue.save
-    assert_equal ["Database can't be blank"], issue.errors.full_messages
-    # Blank value
-    issue.custom_field_values = { field.id => '' }
-    assert !issue.save
-    assert_equal ["Database can't be blank"], issue.errors.full_messages
-    # Invalid value
-    issue.custom_field_values = { field.id => 'SQLServer' }
-    assert !issue.save
-    assert_equal ["Database is not included in the list"], issue.errors.full_messages
-    # Valid value
-    issue.custom_field_values = { field.id => 'PostgreSQL' }
-    assert issue.save
-    issue.reload
-    assert_equal 'PostgreSQL', issue.custom_value_for(field).value
-  end
-
-  def test_create_with_group_assignment
-    with_settings :issue_group_assignment => '1' do
-      assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
-                       :subject => 'Group assignment',
-                       :assigned_to_id => 11).save
-      issue = Issue.first(:order => 'id DESC')
-      assert_kind_of Group, issue.assigned_to
-      assert_equal Group.find(11), issue.assigned_to
-    end
-  end
-
-  def test_create_with_parent_issue_id
-    issue = Issue.new(:project_id => 1, :tracker_id => 1,
-                      :author_id => 1, :subject => 'Group assignment',
-                      :parent_issue_id => 1)
-    assert_save issue
-    assert_equal 1, issue.parent_issue_id
-    assert_equal Issue.find(1), issue.parent
-  end
-
-  def test_create_with_sharp_parent_issue_id
-    issue = Issue.new(:project_id => 1, :tracker_id => 1,
-                      :author_id => 1, :subject => 'Group assignment',
-                      :parent_issue_id => "#1")
-    assert_save issue
-    assert_equal 1, issue.parent_issue_id
-    assert_equal Issue.find(1), issue.parent
-  end
-
-  def test_create_with_invalid_parent_issue_id
-    set_language_if_valid 'en'
-    issue = Issue.new(:project_id => 1, :tracker_id => 1,
-                      :author_id => 1, :subject => 'Group assignment',
-                      :parent_issue_id => '01ABC')
-    assert !issue.save
-    assert_equal '01ABC', issue.parent_issue_id
-    assert_include 'Parent task is invalid', issue.errors.full_messages
-  end
-
-  def test_create_with_invalid_sharp_parent_issue_id
-    set_language_if_valid 'en'
-    issue = Issue.new(:project_id => 1, :tracker_id => 1,
-                      :author_id => 1, :subject => 'Group assignment',
-                      :parent_issue_id => '#01ABC')
-    assert !issue.save
-    assert_equal '#01ABC', issue.parent_issue_id
-    assert_include 'Parent task is invalid', issue.errors.full_messages
-  end
-
-  def assert_visibility_match(user, issues)
-    assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
-  end
-
-  def test_visible_scope_for_anonymous
-    # Anonymous user should see issues of public projects only
-    issues = Issue.visible(User.anonymous).all
-    assert issues.any?
-    assert_nil issues.detect {|issue| !issue.project.is_public?}
-    assert_nil issues.detect {|issue| issue.is_private?}
-    assert_visibility_match User.anonymous, issues
-  end
-
-  def test_visible_scope_for_anonymous_without_view_issues_permissions
-    # Anonymous user should not see issues without permission
-    Role.anonymous.remove_permission!(:view_issues)
-    issues = Issue.visible(User.anonymous).all
-    assert issues.empty?
-    assert_visibility_match User.anonymous, issues
-  end
-
-  def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
-    assert Role.anonymous.update_attribute(:issues_visibility, 'default')
-    issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
-    assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
-    assert !issue.visible?(User.anonymous)
-  end
-
-  def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
-    assert Role.anonymous.update_attribute(:issues_visibility, 'own')
-    issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
-    assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
-    assert !issue.visible?(User.anonymous)
-  end
-
-  def test_visible_scope_for_non_member
-    user = User.find(9)
-    assert user.projects.empty?
-    # Non member user should see issues of public projects only
-    issues = Issue.visible(user).all
-    assert issues.any?
-    assert_nil issues.detect {|issue| !issue.project.is_public?}
-    assert_nil issues.detect {|issue| issue.is_private?}
-    assert_visibility_match user, issues
-  end
-
-  def test_visible_scope_for_non_member_with_own_issues_visibility
-    Role.non_member.update_attribute :issues_visibility, 'own'
-    Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
-    user = User.find(9)
-
-    issues = Issue.visible(user).all
-    assert issues.any?
-    assert_nil issues.detect {|issue| issue.author != user}
-    assert_visibility_match user, issues
-  end
-
-  def test_visible_scope_for_non_member_without_view_issues_permissions
-    # Non member user should not see issues without permission
-    Role.non_member.remove_permission!(:view_issues)
-    user = User.find(9)
-    assert user.projects.empty?
-    issues = Issue.visible(user).all
-    assert issues.empty?
-    assert_visibility_match user, issues
-  end
-
-  def test_visible_scope_for_member
-    user = User.find(9)
-    # User should see issues of projects for which user has view_issues permissions only
-    Role.non_member.remove_permission!(:view_issues)
-    Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
-    issues = Issue.visible(user).all
-    assert issues.any?
-    assert_nil issues.detect {|issue| issue.project_id != 3}
-    assert_nil issues.detect {|issue| issue.is_private?}
-    assert_visibility_match user, issues
-  end
-
-  def test_visible_scope_for_member_with_groups_should_return_assigned_issues
-    user = User.find(8)
-    assert user.groups.any?
-    Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
-    Role.non_member.remove_permission!(:view_issues)
-
-    issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
-      :status_id => 1, :priority => IssuePriority.all.first,
-      :subject => 'Assignment test',
-      :assigned_to => user.groups.first,
-      :is_private => true)
-
-    Role.find(2).update_attribute :issues_visibility, 'default'
-    issues = Issue.visible(User.find(8)).all
-    assert issues.any?
-    assert issues.include?(issue)
-
-    Role.find(2).update_attribute :issues_visibility, 'own'
-    issues = Issue.visible(User.find(8)).all
-    assert issues.any?
-    assert issues.include?(issue)
-  end
-
-  def test_visible_scope_for_admin
-    user = User.find(1)
-    user.members.each(&:destroy)
-    assert user.projects.empty?
-    issues = Issue.visible(user).all
-    assert issues.any?
-    # Admin should see issues on private projects that admin does not belong to
-    assert issues.detect {|issue| !issue.project.is_public?}
-    # Admin should see private issues of other users
-    assert issues.detect {|issue| issue.is_private? && issue.author != user}
-    assert_visibility_match user, issues
-  end
-
-  def test_visible_scope_with_project
-    project = Project.find(1)
-    issues = Issue.visible(User.find(2), :project => project).all
-    projects = issues.collect(&:project).uniq
-    assert_equal 1, projects.size
-    assert_equal project, projects.first
-  end
-
-  def test_visible_scope_with_project_and_subprojects
-    project = Project.find(1)
-    issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
-    projects = issues.collect(&:project).uniq
-    assert projects.size > 1
-    assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
-  end
-
-  def test_visible_and_nested_set_scopes
-    assert_equal 0, Issue.find(1).descendants.visible.all.size
-  end
-
-  def test_open_scope
-    issues = Issue.open.all
-    assert_nil issues.detect(&:closed?)
-  end
-
-  def test_open_scope_with_arg
-    issues = Issue.open(false).all
-    assert_equal issues, issues.select(&:closed?)
-  end
-
-  def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
-    version = Version.find(2)
-    assert version.fixed_issues.any?
-    assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
-  end
-
-  def test_fixed_version_scope_with_empty_array_should_return_no_result
-    assert_equal 0, Issue.fixed_version([]).count
-  end
-
-  def test_errors_full_messages_should_include_custom_fields_errors
-    field = IssueCustomField.find_by_name('Database')
-
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
-                      :status_id => 1, :subject => 'test_create',
-                      :description => 'IssueTest#test_create_with_required_custom_field')
-    assert issue.available_custom_fields.include?(field)
-    # Invalid value
-    issue.custom_field_values = { field.id => 'SQLServer' }
-
-    assert !issue.valid?
-    assert_equal 1, issue.errors.full_messages.size
-    assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
-                 issue.errors.full_messages.first
-  end
-
-  def test_update_issue_with_required_custom_field
-    field = IssueCustomField.find_by_name('Database')
-    field.update_attribute(:is_required, true)
-
-    issue = Issue.find(1)
-    assert_nil issue.custom_value_for(field)
-    assert issue.available_custom_fields.include?(field)
-    # No change to custom values, issue can be saved
-    assert issue.save
-    # Blank value
-    issue.custom_field_values = { field.id => '' }
-    assert !issue.save
-    # Valid value
-    issue.custom_field_values = { field.id => 'PostgreSQL' }
-    assert issue.save
-    issue.reload
-    assert_equal 'PostgreSQL', issue.custom_value_for(field).value
-  end
-
-  def test_should_not_update_attributes_if_custom_fields_validation_fails
-    issue = Issue.find(1)
-    field = IssueCustomField.find_by_name('Database')
-    assert issue.available_custom_fields.include?(field)
-
-    issue.custom_field_values = { field.id => 'Invalid' }
-    issue.subject = 'Should be not be saved'
-    assert !issue.save
-
-    issue.reload
-    assert_equal "Can't print recipes", issue.subject
-  end
-
-  def test_should_not_recreate_custom_values_objects_on_update
-    field = IssueCustomField.find_by_name('Database')
-
-    issue = Issue.find(1)
-    issue.custom_field_values = { field.id => 'PostgreSQL' }
-    assert issue.save
-    custom_value = issue.custom_value_for(field)
-    issue.reload
-    issue.custom_field_values = { field.id => 'MySQL' }
-    assert issue.save
-    issue.reload
-    assert_equal custom_value.id, issue.custom_value_for(field).id
-  end
-
-  def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
-    issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
-                          :status_id => 1, :subject => 'Test',
-                          :custom_field_values => {'2' => 'Test'})
-    assert !Tracker.find(2).custom_field_ids.include?(2)
-
-    issue = Issue.find(issue.id)
-    issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
-
-    issue = Issue.find(issue.id)
-    custom_value = issue.custom_value_for(2)
-    assert_not_nil custom_value
-    assert_equal 'Test', custom_value.value
-  end
-
-  def test_assigning_tracker_id_should_reload_custom_fields_values
-    issue = Issue.new(:project => Project.find(1))
-    assert issue.custom_field_values.empty?
-    issue.tracker_id = 1
-    assert issue.custom_field_values.any?
-  end
-
-  def test_assigning_attributes_should_assign_project_and_tracker_first
-    seq = sequence('seq')
-    issue = Issue.new
-    issue.expects(:project_id=).in_sequence(seq)
-    issue.expects(:tracker_id=).in_sequence(seq)
-    issue.expects(:subject=).in_sequence(seq)
-    issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
-  end
-
-  def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
-    attributes = ActiveSupport::OrderedHash.new
-    attributes['custom_field_values'] = { '1' => 'MySQL' }
-    attributes['tracker_id'] = '1'
-    issue = Issue.new(:project => Project.find(1))
-    issue.attributes = attributes
-    assert_equal 'MySQL', issue.custom_field_value(1)
-  end
-
-  def test_reload_should_reload_custom_field_values
-    issue = Issue.generate!
-    issue.custom_field_values = {'2' => 'Foo'}
-    issue.save!
-
-    issue = Issue.order('id desc').first
-    assert_equal 'Foo', issue.custom_field_value(2)
-
-    issue.custom_field_values = {'2' => 'Bar'}
-    assert_equal 'Bar', issue.custom_field_value(2)
-
-    issue.reload
-    assert_equal 'Foo', issue.custom_field_value(2)
-  end
-
-  def test_should_update_issue_with_disabled_tracker
-    p = Project.find(1)
-    issue = Issue.find(1)
-
-    p.trackers.delete(issue.tracker)
-    assert !p.trackers.include?(issue.tracker)
-
-    issue.reload
-    issue.subject = 'New subject'
-    assert issue.save
-  end
-
-  def test_should_not_set_a_disabled_tracker
-    p = Project.find(1)
-    p.trackers.delete(Tracker.find(2))
-
-    issue = Issue.find(1)
-    issue.tracker_id = 2
-    issue.subject = 'New subject'
-    assert !issue.save
-    assert_not_equal [], issue.errors[:tracker_id]
-  end
-
-  def test_category_based_assignment
-    issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
-                         :status_id => 1, :priority => IssuePriority.all.first,
-                         :subject => 'Assignment test',
-                         :description => 'Assignment test', :category_id => 1)
-    assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
-  end
-
-  def test_new_statuses_allowed_to
-    WorkflowTransition.delete_all
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
-                               :old_status_id => 1, :new_status_id => 2,
-                               :author => false, :assignee => false)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
-                               :old_status_id => 1, :new_status_id => 3,
-                               :author => true, :assignee => false)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
-                               :old_status_id => 1, :new_status_id => 4,
-                               :author => false, :assignee => true)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
-                               :old_status_id => 1, :new_status_id => 5,
-                               :author => true, :assignee => true)
-    status = IssueStatus.find(1)
-    role = Role.find(1)
-    tracker = Tracker.find(1)
-    user = User.find(2)
-
-    issue = Issue.generate!(:tracker => tracker, :status => status,
-                            :project_id => 1, :author_id => 1)
-    assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
-
-    issue = Issue.generate!(:tracker => tracker, :status => status,
-                            :project_id => 1, :author => user)
-    assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
-
-    issue = Issue.generate!(:tracker => tracker, :status => status,
-                            :project_id => 1, :author_id => 1,
-                            :assigned_to => user)
-    assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
-
-    issue = Issue.generate!(:tracker => tracker, :status => status,
-                            :project_id => 1, :author => user,
-                            :assigned_to => user)
-    assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
-
-    group = Group.generate!
-    group.users << user
-    issue = Issue.generate!(:tracker => tracker, :status => status,
-                            :project_id => 1, :author => user,
-                            :assigned_to => group)
-    assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
-  end
-
-  def test_new_statuses_allowed_to_should_consider_group_assignment
-    WorkflowTransition.delete_all
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
-                               :old_status_id => 1, :new_status_id => 4,
-                               :author => false, :assignee => true)
-    user = User.find(2)
-    group = Group.generate!
-    group.users << user
- 
-    issue = Issue.generate!(:author_id => 1, :assigned_to => group)
-    assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
-  end
-
-  def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
-    admin = User.find(1)
-    issue = Issue.find(1)
-    assert !admin.member_of?(issue.project)
-    expected_statuses = [issue.status] +
-                            WorkflowTransition.find_all_by_old_status_id(
-                                issue.status_id).map(&:new_status).uniq.sort
-    assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
-  end
-
-  def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
-    issue = Issue.find(1).copy
-    assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
-
-    issue = Issue.find(2).copy
-    assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
-  end
-
-  def test_safe_attributes_names_should_not_include_disabled_field
-    tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
-
-    issue = Issue.new(:tracker => tracker)
-    assert_include 'tracker_id', issue.safe_attribute_names
-    assert_include 'status_id', issue.safe_attribute_names
-    assert_include 'subject', issue.safe_attribute_names
-    assert_include 'description', issue.safe_attribute_names
-    assert_include 'custom_field_values', issue.safe_attribute_names
-    assert_include 'custom_fields', issue.safe_attribute_names
-    assert_include 'lock_version', issue.safe_attribute_names
-
-    tracker.core_fields.each do |field|
-      assert_include field, issue.safe_attribute_names
-    end
-
-    tracker.disabled_core_fields.each do |field|
-      assert_not_include field, issue.safe_attribute_names
-    end
-  end
-
-  def test_safe_attributes_should_ignore_disabled_fields
-    tracker = Tracker.find(1)
-    tracker.core_fields = %w(assigned_to_id due_date)
-    tracker.save!
-
-    issue = Issue.new(:tracker => tracker)
-    issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
-    assert_nil issue.start_date
-    assert_equal Date.parse('2012-07-14'), issue.due_date
-  end
-
-  def test_safe_attributes_should_accept_target_tracker_enabled_fields
-    source = Tracker.find(1)
-    source.core_fields = []
-    source.save!
-    target = Tracker.find(2)
-    target.core_fields = %w(assigned_to_id due_date)
-    target.save!
-
-    issue = Issue.new(:tracker => source)
-    issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
-    assert_equal target, issue.tracker
-    assert_equal Date.parse('2012-07-14'), issue.due_date
-  end
-
-  def test_safe_attributes_should_not_include_readonly_fields
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'due_date',
-                               :rule => 'readonly')
-    user = User.find(2)
-
-    issue = Issue.new(:project_id => 1, :tracker_id => 1)
-    assert_equal %w(due_date), issue.read_only_attribute_names(user)
-    assert_not_include 'due_date', issue.safe_attribute_names(user)
-
-    issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
-    assert_equal Date.parse('2012-07-14'), issue.start_date
-    assert_nil issue.due_date
-  end
-
-  def test_safe_attributes_should_not_include_readonly_custom_fields
-    cf1 = IssueCustomField.create!(:name => 'Writable field',
-                                   :field_format => 'string',
-                                   :is_for_all => true, :tracker_ids => [1])
-    cf2 = IssueCustomField.create!(:name => 'Readonly field',
-                                   :field_format => 'string',
-                                   :is_for_all => true, :tracker_ids => [1])
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => cf2.id.to_s,
-                               :rule => 'readonly')
-    user = User.find(2)
-    issue = Issue.new(:project_id => 1, :tracker_id => 1)
-    assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
-    assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
-
-    issue.send :safe_attributes=, {'custom_field_values' => {
-                                       cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
-                                     }}, user
-    assert_equal 'value1', issue.custom_field_value(cf1)
-    assert_nil issue.custom_field_value(cf2)
-
-    issue.send :safe_attributes=, {'custom_fields' => [
-                                      {'id' => cf1.id.to_s, 'value' => 'valuea'},
-                                      {'id' => cf2.id.to_s, 'value' => 'valueb'}
-                                    ]}, user
-    assert_equal 'valuea', issue.custom_field_value(cf1)
-    assert_nil issue.custom_field_value(cf2)
-  end
-
-  def test_editable_custom_field_values_should_return_non_readonly_custom_values
-    cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
-                                   :is_for_all => true, :tracker_ids => [1, 2])
-    cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
-                                   :is_for_all => true, :tracker_ids => [1, 2])
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
-                               :field_name => cf2.id.to_s, :rule => 'readonly')
-    user = User.find(2)
-
-    issue = Issue.new(:project_id => 1, :tracker_id => 1)
-    values = issue.editable_custom_field_values(user)
-    assert values.detect {|value| value.custom_field == cf1}
-    assert_nil values.detect {|value| value.custom_field == cf2}
-
-    issue.tracker_id = 2
-    values = issue.editable_custom_field_values(user)
-    assert values.detect {|value| value.custom_field == cf1}
-    assert values.detect {|value| value.custom_field == cf2}
-  end
-
-  def test_safe_attributes_should_accept_target_tracker_writable_fields
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'due_date',
-                               :rule => 'readonly')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
-                               :role_id => 1, :field_name => 'start_date',
-                               :rule => 'readonly')
-    user = User.find(2)
-
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
-
-    issue.send :safe_attributes=, {'start_date' => '2012-07-12',
-                                   'due_date' => '2012-07-14'}, user
-    assert_equal Date.parse('2012-07-12'), issue.start_date
-    assert_nil issue.due_date
-
-    issue.send :safe_attributes=, {'start_date' => '2012-07-15',
-                                   'due_date' => '2012-07-16',
-                                   'tracker_id' => 2}, user
-    assert_equal Date.parse('2012-07-12'), issue.start_date
-    assert_equal Date.parse('2012-07-16'), issue.due_date
-  end
-
-  def test_safe_attributes_should_accept_target_status_writable_fields
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'due_date',
-                               :rule => 'readonly')
-    WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'start_date',
-                               :rule => 'readonly')
-    user = User.find(2)
-
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
-
-    issue.send :safe_attributes=, {'start_date' => '2012-07-12',
-                                   'due_date' => '2012-07-14'},
-                                   user
-    assert_equal Date.parse('2012-07-12'), issue.start_date
-    assert_nil issue.due_date
-
-    issue.send :safe_attributes=, {'start_date' => '2012-07-15',
-                                    'due_date' => '2012-07-16',
-                                    'status_id' => 2},
-                                  user
-    assert_equal Date.parse('2012-07-12'), issue.start_date
-    assert_equal Date.parse('2012-07-16'), issue.due_date
-  end
-
-  def test_required_attributes_should_be_validated
-    cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
-                                  :is_for_all => true, :tracker_ids => [1, 2])
-
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'due_date',
-                               :rule => 'required')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'category_id',
-                               :rule => 'required')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => cf.id.to_s,
-                               :rule => 'required')
-
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
-                               :role_id => 1, :field_name => 'start_date',
-                               :rule => 'required')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
-                               :role_id => 1, :field_name => cf.id.to_s,
-                               :rule => 'required')
-    user = User.find(2)
-
-    issue = Issue.new(:project_id => 1, :tracker_id => 1,
-                      :status_id => 1, :subject => 'Required fields',
-                      :author => user)
-    assert_equal [cf.id.to_s, "category_id", "due_date"],
-                 issue.required_attribute_names(user).sort
-    assert !issue.save, "Issue was saved"
-    assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"],
-                  issue.errors.full_messages.sort
-
-    issue.tracker_id = 2
-    assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
-    assert !issue.save, "Issue was saved"
-    assert_equal ["Foo can't be blank", "Start date can't be blank"],
-                 issue.errors.full_messages.sort
-
-    issue.start_date = Date.today
-    issue.custom_field_values = {cf.id.to_s => 'bar'}
-    assert issue.save
-  end
-
-  def test_required_attribute_names_for_multiple_roles_should_intersect_rules
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'due_date',
-                               :rule => 'required')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'start_date',
-                               :rule => 'required')
-    user = User.find(2)
-    member = Member.find(1)
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
-
-    assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
-
-    member.role_ids = [1, 2]
-    member.save!
-    assert_equal [], issue.required_attribute_names(user.reload)
-
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 2, :field_name => 'due_date',
-                               :rule => 'required')
-    assert_equal %w(due_date), issue.required_attribute_names(user)
-
-    member.role_ids = [1, 2, 3]
-    member.save!
-    assert_equal [], issue.required_attribute_names(user.reload)
-
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 2, :field_name => 'due_date',
-                               :rule => 'readonly')
-    # required + readonly => required
-    assert_equal %w(due_date), issue.required_attribute_names(user)
-  end
-
-  def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'due_date',
-                               :rule => 'readonly')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                               :role_id => 1, :field_name => 'start_date',
-                               :rule => 'readonly')
-    user = User.find(2)
-    member = Member.find(1)
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
-
-    assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
-
-    member.role_ids = [1, 2]
-    member.save!
-    assert_equal [], issue.read_only_attribute_names(user.reload)
-
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
-                              :role_id => 2, :field_name => 'due_date',
-                              :rule => 'readonly')
-    assert_equal %w(due_date), issue.read_only_attribute_names(user)
-  end
-
-  def test_copy
-    issue = Issue.new.copy_from(1)
-    assert issue.copy?
-    assert issue.save
-    issue.reload
-    orig = Issue.find(1)
-    assert_equal orig.subject, issue.subject
-    assert_equal orig.tracker, issue.tracker
-    assert_equal "125", issue.custom_value_for(2).value
-  end
-
-  def test_copy_should_copy_status
-    orig = Issue.find(8)
-    assert orig.status != IssueStatus.default
-
-    issue = Issue.new.copy_from(orig)
-    assert issue.save
-    issue.reload
-    assert_equal orig.status, issue.status
-  end
-
-  def test_copy_should_add_relation_with_copied_issue
-    copied = Issue.find(1)
-    issue = Issue.new.copy_from(copied)
-    assert issue.save
-    issue.reload
-
-    assert_equal 1, issue.relations.size
-    relation = issue.relations.first
-    assert_equal 'copied_to', relation.relation_type
-    assert_equal copied, relation.issue_from
-    assert_equal issue, relation.issue_to
-  end
-
-  def test_copy_should_copy_subtasks
-    issue = Issue.generate_with_descendants!
-
-    copy = issue.reload.copy
-    copy.author = User.find(7)
-    assert_difference 'Issue.count', 1+issue.descendants.count do
-      assert copy.save
-    end
-    copy.reload
-    assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
-    child_copy = copy.children.detect {|c| c.subject == 'Child1'}
-    assert_equal %w(Child11), child_copy.children.map(&:subject).sort
-    assert_equal copy.author, child_copy.author
-  end
-
-  def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
-    parent = Issue.generate!
-    child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
-    child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
-
-    copy = parent.reload.copy
-    copy.parent_issue_id = parent.id
-    copy.author = User.find(7)
-    assert_difference 'Issue.count', 3 do
-      assert copy.save
-    end
-    parent.reload
-    copy.reload
-    assert_equal parent, copy.parent
-    assert_equal 3, parent.children.count
-    assert_equal 5, parent.descendants.count
-    assert_equal 2, copy.children.count
-    assert_equal 2, copy.descendants.count
-  end
-
-  def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
-    parent = Issue.generate!
-    child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
-    child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
-
-    copy = parent.reload.copy
-    copy.parent_issue_id = child1.id
-    copy.author = User.find(7)
-    assert_difference 'Issue.count', 3 do
-      assert copy.save
-    end
-    parent.reload
-    child1.reload
-    copy.reload
-    assert_equal child1, copy.parent
-    assert_equal 2, parent.children.count
-    assert_equal 5, parent.descendants.count
-    assert_equal 1, child1.children.count
-    assert_equal 3, child1.descendants.count
-    assert_equal 2, copy.children.count
-    assert_equal 2, copy.descendants.count
-  end
-
-  def test_copy_should_copy_subtasks_to_target_project
-    issue = Issue.generate_with_descendants!
-
-    copy = issue.copy(:project_id => 3)
-    assert_difference 'Issue.count', 1+issue.descendants.count do
-      assert copy.save
-    end
-    assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
-  end
-
-  def test_copy_should_not_copy_subtasks_twice_when_saving_twice
-    issue = Issue.generate_with_descendants!
-
-    copy = issue.reload.copy
-    assert_difference 'Issue.count', 1+issue.descendants.count do
-      assert copy.save
-      assert copy.save
-    end
-  end
-
-  def test_should_not_call_after_project_change_on_creation
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
-                      :subject => 'Test', :author_id => 1)
-    issue.expects(:after_project_change).never
-    issue.save!
-  end
-
-  def test_should_not_call_after_project_change_on_update
-    issue = Issue.find(1)
-    issue.project = Project.find(1)
-    issue.subject = 'No project change'
-    issue.expects(:after_project_change).never
-    issue.save!
-  end
-
-  def test_should_call_after_project_change_on_project_change
-    issue = Issue.find(1)
-    issue.project = Project.find(2)
-    issue.expects(:after_project_change).once
-    issue.save!
-  end
-
-  def test_adding_journal_should_update_timestamp
-    issue = Issue.find(1)
-    updated_on_was = issue.updated_on
-
-    issue.init_journal(User.first, "Adding notes")
-    assert_difference 'Journal.count' do
-      assert issue.save
-    end
-    issue.reload
-
-    assert_not_equal updated_on_was, issue.updated_on
-  end
-
-  def test_should_close_duplicates
-    # Create 3 issues
-    issue1 = Issue.generate!
-    issue2 = Issue.generate!
-    issue3 = Issue.generate!
-
-    # 2 is a dupe of 1
-    IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
-                          :relation_type => IssueRelation::TYPE_DUPLICATES)
-    # And 3 is a dupe of 2
-    IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
-                          :relation_type => IssueRelation::TYPE_DUPLICATES)
-    # And 3 is a dupe of 1 (circular duplicates)
-    IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
-                          :relation_type => IssueRelation::TYPE_DUPLICATES)
-
-    assert issue1.reload.duplicates.include?(issue2)
-
-    # Closing issue 1
-    issue1.init_journal(User.first, "Closing issue1")
-    issue1.status = IssueStatus.where(:is_closed => true).first
-    assert issue1.save
-    # 2 and 3 should be also closed
-    assert issue2.reload.closed?
-    assert issue3.reload.closed?
-  end
-
-  def test_should_not_close_duplicated_issue
-    issue1 = Issue.generate!
-    issue2 = Issue.generate!
-
-    # 2 is a dupe of 1
-    IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
-                         :relation_type => IssueRelation::TYPE_DUPLICATES)
-    # 2 is a dup of 1 but 1 is not a duplicate of 2
-    assert !issue2.reload.duplicates.include?(issue1)
-
-    # Closing issue 2
-    issue2.init_journal(User.first, "Closing issue2")
-    issue2.status = IssueStatus.where(:is_closed => true).first
-    assert issue2.save
-    # 1 should not be also closed
-    assert !issue1.reload.closed?
-  end
-
-  def test_assignable_versions
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
-                      :status_id => 1, :fixed_version_id => 1,
-                      :subject => 'New issue')
-    assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
-  end
-
-  def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
-                      :status_id => 1, :fixed_version_id => 1,
-                      :subject => 'New issue')
-    assert !issue.save
-    assert_not_equal [], issue.errors[:fixed_version_id]
-  end
-
-  def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
-                      :status_id => 1, :fixed_version_id => 2,
-                      :subject => 'New issue')
-    assert !issue.save
-    assert_not_equal [], issue.errors[:fixed_version_id]
-  end
-
-  def test_should_be_able_to_assign_a_new_issue_to_an_open_version
-    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
-                      :status_id => 1, :fixed_version_id => 3,
-                      :subject => 'New issue')
-    assert issue.save
-  end
-
-  def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
-    issue = Issue.find(11)
-    assert_equal 'closed', issue.fixed_version.status
-    issue.subject = 'Subject changed'
-    assert issue.save
-  end
-
-  def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
-    issue = Issue.find(11)
-    issue.status_id = 1
-    assert !issue.save
-    assert_not_equal [], issue.errors[:base]
-  end
-
-  def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
-    issue = Issue.find(11)
-    issue.status_id = 1
-    issue.fixed_version_id = 3
-    assert issue.save
-  end
-
-  def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
-    issue = Issue.find(12)
-    assert_equal 'locked', issue.fixed_version.status
-    issue.status_id = 1
-    assert issue.save
-  end
-
-  def test_should_not_be_able_to_keep_unshared_version_when_changing_project
-    issue = Issue.find(2)
-    assert_equal 2, issue.fixed_version_id
-    issue.project_id = 3
-    assert_nil issue.fixed_version_id
-    issue.fixed_version_id = 2
-    assert !issue.save
-    assert_include 'Target version is not included in the list', issue.errors.full_messages
-  end
-
-  def test_should_keep_shared_version_when_changing_project
-    Version.find(2).update_attribute :sharing, 'tree'
-
-    issue = Issue.find(2)
-    assert_equal 2, issue.fixed_version_id
-    issue.project_id = 3
-    assert_equal 2, issue.fixed_version_id
-    assert issue.save
-  end
-
-  def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
-    assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
-  end
-
-  def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
-    Project.find(2).disable_module! :issue_tracking
-    assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
-  end
-
-  def test_move_to_another_project_with_same_category
-    issue = Issue.find(1)
-    issue.project = Project.find(2)
-    assert issue.save
-    issue.reload
-    assert_equal 2, issue.project_id
-    # Category changes
-    assert_equal 4, issue.category_id
-    # Make sure time entries were move to the target project
-    assert_equal 2, issue.time_entries.first.project_id
-  end
-
-  def test_move_to_another_project_without_same_category
-    issue = Issue.find(2)
-    issue.project = Project.find(2)
-    assert issue.save
-    issue.reload
-    assert_equal 2, issue.project_id
-    # Category cleared
-    assert_nil issue.category_id
-  end
-
-  def test_move_to_another_project_should_clear_fixed_version_when_not_shared
-    issue = Issue.find(1)
-    issue.update_attribute(:fixed_version_id, 1)
-    issue.project = Project.find(2)
-    assert issue.save
-    issue.reload
-    assert_equal 2, issue.project_id
-    # Cleared fixed_version
-    assert_equal nil, issue.fixed_version
-  end
-
-  def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
-    issue = Issue.find(1)
-    issue.update_attribute(:fixed_version_id, 4)
-    issue.project = Project.find(5)
-    assert issue.save
-    issue.reload
-    assert_equal 5, issue.project_id
-    # Keep fixed_version
-    assert_equal 4, issue.fixed_version_id
-  end
-
-  def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
-    issue = Issue.find(1)
-    issue.update_attribute(:fixed_version_id, 1)
-    issue.project = Project.find(5)
-    assert issue.save
-    issue.reload
-    assert_equal 5, issue.project_id
-    # Cleared fixed_version
-    assert_equal nil, issue.fixed_version
-  end
-
-  def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
-    issue = Issue.find(1)
-    issue.update_attribute(:fixed_version_id, 7)
-    issue.project = Project.find(2)
-    assert issue.save
-    issue.reload
-    assert_equal 2, issue.project_id
-    # Keep fixed_version
-    assert_equal 7, issue.fixed_version_id
-  end
-
-  def test_move_to_another_project_should_keep_parent_if_valid
-    issue = Issue.find(1)
-    issue.update_attribute(:parent_issue_id, 2)
-    issue.project = Project.find(3)
-    assert issue.save
-    issue.reload
-    assert_equal 2, issue.parent_id
-  end
-
-  def test_move_to_another_project_should_clear_parent_if_not_valid
-    issue = Issue.find(1)
-    issue.update_attribute(:parent_issue_id, 2)
-    issue.project = Project.find(2)
-    assert issue.save
-    issue.reload
-    assert_nil issue.parent_id
-  end
-
-  def test_move_to_another_project_with_disabled_tracker
-    issue = Issue.find(1)
-    target = Project.find(2)
-    target.tracker_ids = [3]
-    target.save
-    issue.project = target
-    assert issue.save
-    issue.reload
-    assert_equal 2, issue.project_id
-    assert_equal 3, issue.tracker_id
-  end
-
-  def test_copy_to_the_same_project
-    issue = Issue.find(1)
-    copy = issue.copy
-    assert_difference 'Issue.count' do
-      copy.save!
-    end
-    assert_kind_of Issue, copy
-    assert_equal issue.project, copy.project
-    assert_equal "125", copy.custom_value_for(2).value
-  end
-
-  def test_copy_to_another_project_and_tracker
-    issue = Issue.find(1)
-    copy = issue.copy(:project_id => 3, :tracker_id => 2)
-    assert_difference 'Issue.count' do
-      copy.save!
-    end
-    copy.reload
-    assert_kind_of Issue, copy
-    assert_equal Project.find(3), copy.project
-    assert_equal Tracker.find(2), copy.tracker
-    # Custom field #2 is not associated with target tracker
-    assert_nil copy.custom_value_for(2)
-  end
-
-  test "#copy should not create a journal" do
-    copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
-    copy.save!
-    assert_equal 0, copy.reload.journals.size
-  end
-
-  test "#copy should allow assigned_to changes" do
-    copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
-    assert_equal 3, copy.assigned_to_id
-  end
-
-  test "#copy should allow status changes" do
-    copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
-    assert_equal 2, copy.status_id
-  end
-
-  test "#copy should allow start date changes" do
-    date = Date.today
-    copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
-    assert_equal date, copy.start_date
-  end
-
-  test "#copy should allow due date changes" do
-    date = Date.today
-    copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
-    assert_equal date, copy.due_date
-  end
-
-  test "#copy should set current user as author" do
-    User.current = User.find(9)
-    copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
-    assert_equal User.current, copy.author
-  end
-
-  test "#copy should create a journal with notes" do
-    date = Date.today
-    notes = "Notes added when copying"
-    copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
-    copy.init_journal(User.current, notes)
-    copy.save!
-
-    assert_equal 1, copy.journals.size
-    journal = copy.journals.first
-    assert_equal 0, journal.details.size
-    assert_equal notes, journal.notes
-  end
-
-  def test_valid_parent_project
-    issue = Issue.find(1)
-    issue_in_same_project = Issue.find(2)
-    issue_in_child_project = Issue.find(5)
-    issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
-    issue_in_other_child_project = Issue.find(6)
-    issue_in_different_tree = Issue.find(4)
-
-    with_settings :cross_project_subtasks => '' do
-      assert_equal true, issue.valid_parent_project?(issue_in_same_project)
-      assert_equal false, issue.valid_parent_project?(issue_in_child_project)
-      assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
-      assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
-    end
-
-    with_settings :cross_project_subtasks => 'system' do
-      assert_equal true, issue.valid_parent_project?(issue_in_same_project)
-      assert_equal true, issue.valid_parent_project?(issue_in_child_project)
-      assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
-    end
-
-    with_settings :cross_project_subtasks => 'tree' do
-      assert_equal true, issue.valid_parent_project?(issue_in_same_project)
-      assert_equal true, issue.valid_parent_project?(issue_in_child_project)
-      assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
-      assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
-
-      assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
-      assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
-    end
-
-    with_settings :cross_project_subtasks => 'descendants' do
-      assert_equal true, issue.valid_parent_project?(issue_in_same_project)
-      assert_equal false, issue.valid_parent_project?(issue_in_child_project)
-      assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
-      assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
-
-      assert_equal true, issue_in_child_project.valid_parent_project?(issue)
-      assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
-    end
-  end
-
-  def test_recipients_should_include_previous_assignee
-    user = User.find(3)
-    user.members.update_all ["mail_notification = ?", false]
-    user.update_attribute :mail_notification, 'only_assigned'
-
-    issue = Issue.find(2)
-    issue.assigned_to = nil
-    assert_include user.mail, issue.recipients
-    issue.save!
-    assert !issue.recipients.include?(user.mail)
-  end
-
-  def test_recipients_should_not_include_users_that_cannot_view_the_issue
-    issue = Issue.find(12)
-    assert issue.recipients.include?(issue.author.mail)
-    # copy the issue to a private project
-    copy  = issue.copy(:project_id => 5, :tracker_id => 2)
-    # author is not a member of project anymore
-    assert !copy.recipients.include?(copy.author.mail)
-  end
-
-  def test_recipients_should_include_the_assigned_group_members
-    group_member = User.generate!
-    group = Group.generate!
-    group.users << group_member
-
-    issue = Issue.find(12)
-    issue.assigned_to = group
-    assert issue.recipients.include?(group_member.mail)
-  end
-
-  def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
-    user = User.find(3)
-    issue = Issue.find(9)
-    Watcher.create!(:user => user, :watchable => issue)
-    assert issue.watched_by?(user)
-    assert !issue.watcher_recipients.include?(user.mail)
-  end
-
-  def test_issue_destroy
-    Issue.find(1).destroy
-    assert_nil Issue.find_by_id(1)
-    assert_nil TimeEntry.find_by_issue_id(1)
-  end
-
-  def test_destroying_a_deleted_issue_should_not_raise_an_error
-    issue = Issue.find(1)
-    Issue.find(1).destroy
-
-    assert_nothing_raised do
-      assert_no_difference 'Issue.count' do
-        issue.destroy
-      end
-      assert issue.destroyed?
-    end
-  end
-
-  def test_destroying_a_stale_issue_should_not_raise_an_error
-    issue = Issue.find(1)
-    Issue.find(1).update_attribute :subject, "Updated"
-
-    assert_nothing_raised do
-      assert_difference 'Issue.count', -1 do
-        issue.destroy
-      end
-      assert issue.destroyed?
-    end
-  end
-
-  def test_blocked
-    blocked_issue = Issue.find(9)
-    blocking_issue = Issue.find(10)
-
-    assert blocked_issue.blocked?
-    assert !blocking_issue.blocked?
-  end
-
-  def test_blocked_issues_dont_allow_closed_statuses
-    blocked_issue = Issue.find(9)
-
-    allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
-    assert !allowed_statuses.empty?
-    closed_statuses = allowed_statuses.select {|st| st.is_closed?}
-    assert closed_statuses.empty?
-  end
-
-  def test_unblocked_issues_allow_closed_statuses
-    blocking_issue = Issue.find(10)
-
-    allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
-    assert !allowed_statuses.empty?
-    closed_statuses = allowed_statuses.select {|st| st.is_closed?}
-    assert !closed_statuses.empty?
-  end
-
-  def test_reschedule_an_issue_without_dates
-    with_settings :non_working_week_days => [] do
-      issue = Issue.new(:start_date => nil, :due_date => nil)
-      issue.reschedule_on '2012-10-09'.to_date
-      assert_equal '2012-10-09'.to_date, issue.start_date
-      assert_equal '2012-10-09'.to_date, issue.due_date
-    end
-
-    with_settings :non_working_week_days => %w(6 7) do
-      issue = Issue.new(:start_date => nil, :due_date => nil)
-      issue.reschedule_on '2012-10-09'.to_date
-      assert_equal '2012-10-09'.to_date, issue.start_date
-      assert_equal '2012-10-09'.to_date, issue.due_date
-
-      issue = Issue.new(:start_date => nil, :due_date => nil)
-      issue.reschedule_on '2012-10-13'.to_date
-      assert_equal '2012-10-15'.to_date, issue.start_date
-      assert_equal '2012-10-15'.to_date, issue.due_date
-    end
-  end
-
-  def test_reschedule_an_issue_with_start_date
-    with_settings :non_working_week_days => [] do
-      issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
-      issue.reschedule_on '2012-10-13'.to_date
-      assert_equal '2012-10-13'.to_date, issue.start_date
-      assert_equal '2012-10-13'.to_date, issue.due_date
-    end
-
-    with_settings :non_working_week_days => %w(6 7) do
-      issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
-      issue.reschedule_on '2012-10-11'.to_date
-      assert_equal '2012-10-11'.to_date, issue.start_date
-      assert_equal '2012-10-11'.to_date, issue.due_date
-
-      issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
-      issue.reschedule_on '2012-10-13'.to_date
-      assert_equal '2012-10-15'.to_date, issue.start_date
-      assert_equal '2012-10-15'.to_date, issue.due_date
-    end
-  end
-
-  def test_reschedule_an_issue_with_start_and_due_dates
-    with_settings :non_working_week_days => [] do
-      issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
-      issue.reschedule_on '2012-10-13'.to_date
-      assert_equal '2012-10-13'.to_date, issue.start_date
-      assert_equal '2012-10-19'.to_date, issue.due_date
-    end
-
-    with_settings :non_working_week_days => %w(6 7) do
-      issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
-      issue.reschedule_on '2012-10-11'.to_date
-      assert_equal '2012-10-11'.to_date, issue.start_date
-      assert_equal '2012-10-23'.to_date, issue.due_date
-
-      issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
-      issue.reschedule_on '2012-10-13'.to_date
-      assert_equal '2012-10-15'.to_date, issue.start_date
-      assert_equal '2012-10-25'.to_date, issue.due_date
-    end
-  end
-
-  def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
-    issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
-    issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
-    IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
-                          :relation_type => IssueRelation::TYPE_PRECEDES)
-    assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
-
-    issue1.reload
-    issue1.due_date = '2012-10-23'
-    issue1.save!
-    issue2.reload
-    assert_equal Date.parse('2012-10-24'), issue2.start_date
-    assert_equal Date.parse('2012-10-26'), issue2.due_date
-  end
-
-  def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
-    issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
-    issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
-    IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
-                          :relation_type => IssueRelation::TYPE_PRECEDES)
-    assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
-
-    issue1.reload
-    issue1.start_date = '2012-09-17'
-    issue1.due_date = '2012-09-18'
-    issue1.save!
-    issue2.reload
-    assert_equal Date.parse('2012-09-19'), issue2.start_date
-    assert_equal Date.parse('2012-09-21'), issue2.due_date
-  end
-
-  def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
-    issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
-    issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
-    issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
-    IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
-                          :relation_type => IssueRelation::TYPE_PRECEDES)
-    IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
-                          :relation_type => IssueRelation::TYPE_PRECEDES)
-    assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
-
-    issue1.reload
-    issue1.start_date = '2012-09-17'
-    issue1.due_date = '2012-09-18'
-    issue1.save!
-    issue2.reload
-    # Issue 2 must start after Issue 3
-    assert_equal Date.parse('2012-10-03'), issue2.start_date
-    assert_equal Date.parse('2012-10-05'), issue2.due_date
-  end
-
-  def test_rescheduling_a_stale_issue_should_not_raise_an_error
-    with_settings :non_working_week_days => [] do
-      stale = Issue.find(1)
-      issue = Issue.find(1)
-      issue.subject = "Updated"
-      issue.save!
-      date = 10.days.from_now.to_date
-      assert_nothing_raised do
-        stale.reschedule_on!(date)
-      end
-      assert_equal date, stale.reload.start_date
-    end
-  end
-
-  def test_child_issue_should_consider_parent_soonest_start_on_create
-    set_language_if_valid 'en'
-    issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
-    issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
-    IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
-                          :relation_type => IssueRelation::TYPE_PRECEDES)
-    issue1.reload
-    issue2.reload
-    assert_equal Date.parse('2012-10-18'), issue2.start_date
-
-    child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
-      :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
-    assert !child.valid?
-    assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
-    assert_equal Date.parse('2012-10-18'), child.soonest_start
-    child.start_date = '2012-10-18'
-    assert child.save
-  end
-
-  def test_setting_parent_to_a_dependent_issue_should_not_validate
-    set_language_if_valid 'en'
-    issue1 = Issue.generate!
-    issue2 = Issue.generate!
-    issue3 = Issue.generate!
-    IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
-    IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
-    issue3.reload
-    issue3.parent_issue_id = issue2.id
-    assert !issue3.valid?
-    assert_include 'Parent task is invalid', issue3.errors.full_messages
-  end
-
-  def test_setting_parent_should_not_allow_circular_dependency
-    set_language_if_valid 'en'
-    issue1 = Issue.generate!
-    issue2 = Issue.generate!
-    IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
-    issue3 = Issue.generate!
-    issue2.reload
-    issue2.parent_issue_id = issue3.id
-    issue2.save!
-    issue4 = Issue.generate!
-    IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
-    issue4.reload
-    issue4.parent_issue_id = issue1.id
-    assert !issue4.valid?
-    assert_include 'Parent task is invalid', issue4.errors.full_messages
-  end
-
-  def test_overdue
-    assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
-    assert !Issue.new(:due_date => Date.today).overdue?
-    assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
-    assert !Issue.new(:due_date => nil).overdue?
-    assert !Issue.new(:due_date => 1.day.ago.to_date,
-                      :status => IssueStatus.where(:is_closed => true).first
-                      ).overdue?
-  end
-
-  test "#behind_schedule? should be false if the issue has no start_date" do
-    assert !Issue.new(:start_date => nil,
-                      :due_date => 1.day.from_now.to_date,
-                      :done_ratio => 0).behind_schedule?
-  end
-
-  test "#behind_schedule? should be false if the issue has no end_date" do
-    assert !Issue.new(:start_date => 1.day.from_now.to_date,
-                      :due_date => nil,
-                      :done_ratio => 0).behind_schedule?
-  end
-
-  test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
-    assert !Issue.new(:start_date => 50.days.ago.to_date,
-                      :due_date => 50.days.from_now.to_date,
-                      :done_ratio => 90).behind_schedule?
-  end
-
-  test "#behind_schedule? should be true if the issue hasn't been started at all" do
-    assert Issue.new(:start_date => 1.day.ago.to_date,
-                     :due_date => 1.day.from_now.to_date,
-                     :done_ratio => 0).behind_schedule?
-  end
-
-  test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
-    assert Issue.new(:start_date => 100.days.ago.to_date,
-                     :due_date => Date.today,
-                     :done_ratio => 90).behind_schedule?
-  end
-
-  test "#assignable_users should be Users" do
-    assert_kind_of User, Issue.find(1).assignable_users.first
-  end
-
-  test "#assignable_users should include the issue author" do
-    non_project_member = User.generate!
-    issue = Issue.generate!(:author => non_project_member)
-
-    assert issue.assignable_users.include?(non_project_member)
-  end
-
-  test "#assignable_users should include the current assignee" do
-    user = User.generate!
-    issue = Issue.generate!(:assigned_to => user)
-    user.lock!
-
-    assert Issue.find(issue.id).assignable_users.include?(user)
-  end
-
-  test "#assignable_users should not show the issue author twice" do
-    assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
-    assert_equal 2, assignable_user_ids.length
-
-    assignable_user_ids.each do |user_id|
-      assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
-                   "User #{user_id} appears more or less than once"
-    end
-  end
-
-  test "#assignable_users with issue_group_assignment should include groups" do
-    issue = Issue.new(:project => Project.find(2))
-
-    with_settings :issue_group_assignment => '1' do
-      assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
-      assert issue.assignable_users.include?(Group.find(11))
-    end
-  end
-
-  test "#assignable_users without issue_group_assignment should not include groups" do
-    issue = Issue.new(:project => Project.find(2))
-
-    with_settings :issue_group_assignment => '0' do
-      assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
-      assert !issue.assignable_users.include?(Group.find(11))
-    end
-  end
-
-  def test_create_should_send_email_notification
-    ActionMailer::Base.deliveries.clear
-    issue = Issue.new(:project_id => 1, :tracker_id => 1,
-                      :author_id => 3, :status_id => 1,
-                      :priority => IssuePriority.all.first,
-                      :subject => 'test_create', :estimated_hours => '1:30')
-
-    assert issue.save
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_update_should_notify_previous_assignee
-    ActionMailer::Base.deliveries.clear
-    user = User.find(3)
-    user.members.update_all ["mail_notification = ?", false]
-    user.update_attribute :mail_notification, 'only_assigned'
-
-    issue = Issue.find(2)
-    issue.init_journal User.find(1)
-    issue.assigned_to = nil
-    issue.save!
-    assert_include user.mail, ActionMailer::Base.deliveries.last.bcc
-  end
-
-  def test_stale_issue_should_not_send_email_notification
-    ActionMailer::Base.deliveries.clear
-    issue = Issue.find(1)
-    stale = Issue.find(1)
-
-    issue.init_journal(User.find(1))
-    issue.subject = 'Subjet update'
-    assert issue.save
-    assert_equal 1, ActionMailer::Base.deliveries.size
-    ActionMailer::Base.deliveries.clear
-
-    stale.init_journal(User.find(1))
-    stale.subject = 'Another subjet update'
-    assert_raise ActiveRecord::StaleObjectError do
-      stale.save
-    end
-    assert ActionMailer::Base.deliveries.empty?
-  end
-
-  def test_journalized_description
-    IssueCustomField.delete_all
-
-    i = Issue.first
-    old_description = i.description
-    new_description = "This is the new description"
-
-    i.init_journal(User.find(2))
-    i.description = new_description
-    assert_difference 'Journal.count', 1 do
-      assert_difference 'JournalDetail.count', 1 do
-        i.save!
-      end
-    end
-
-    detail = JournalDetail.first(:order => 'id DESC')
-    assert_equal i, detail.journal.journalized
-    assert_equal 'attr', detail.property
-    assert_equal 'description', detail.prop_key
-    assert_equal old_description, detail.old_value
-    assert_equal new_description, detail.value
-  end
-
-  def test_blank_descriptions_should_not_be_journalized
-    IssueCustomField.delete_all
-    Issue.update_all("description = NULL", "id=1")
-
-    i = Issue.find(1)
-    i.init_journal(User.find(2))
-    i.subject = "blank description"
-    i.description = "\r\n"
-
-    assert_difference 'Journal.count', 1 do
-      assert_difference 'JournalDetail.count', 1 do
-        i.save!
-      end
-    end
-  end
-
-  def test_journalized_multi_custom_field
-    field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
-                                     :is_filter => true, :is_for_all => true,
-                                     :tracker_ids => [1],
-                                     :possible_values => ['value1', 'value2', 'value3'],
-                                     :multiple => true)
-
-    issue = Issue.create!(:project_id => 1, :tracker_id => 1,
-                          :subject => 'Test', :author_id => 1)
-
-    assert_difference 'Journal.count' do
-      assert_difference 'JournalDetail.count' do
-        issue.init_journal(User.first)
-        issue.custom_field_values = {field.id => ['value1']}
-        issue.save!
-      end
-      assert_difference 'JournalDetail.count' do
-        issue.init_journal(User.first)
-        issue.custom_field_values = {field.id => ['value1', 'value2']}
-        issue.save!
-      end
-      assert_difference 'JournalDetail.count', 2 do
-        issue.init_journal(User.first)
-        issue.custom_field_values = {field.id => ['value3', 'value2']}
-        issue.save!
-      end
-      assert_difference 'JournalDetail.count', 2 do
-        issue.init_journal(User.first)
-        issue.custom_field_values = {field.id => nil}
-        issue.save!
-      end
-    end
-  end
-
-  def test_description_eol_should_be_normalized
-    i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
-    assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
-  end
-
-  def test_saving_twice_should_not_duplicate_journal_details
-    i = Issue.first
-    i.init_journal(User.find(2), 'Some notes')
-    # initial changes
-    i.subject = 'New subject'
-    i.done_ratio = i.done_ratio + 10
-    assert_difference 'Journal.count' do
-      assert i.save
-    end
-    # 1 more change
-    i.priority = IssuePriority.where("id <> ?", i.priority_id).first
-    assert_no_difference 'Journal.count' do
-      assert_difference 'JournalDetail.count', 1 do
-        i.save
-      end
-    end
-    # no more change
-    assert_no_difference 'Journal.count' do
-      assert_no_difference 'JournalDetail.count' do
-        i.save
-      end
-    end
-  end
-
-  def test_all_dependent_issues
-    IssueRelation.delete_all
-    assert IssueRelation.create!(:issue_from => Issue.find(1),
-                                 :issue_to   => Issue.find(2),
-                                 :relation_type => IssueRelation::TYPE_PRECEDES)
-    assert IssueRelation.create!(:issue_from => Issue.find(2),
-                                 :issue_to   => Issue.find(3),
-                                 :relation_type => IssueRelation::TYPE_PRECEDES)
-    assert IssueRelation.create!(:issue_from => Issue.find(3),
-                                 :issue_to   => Issue.find(8),
-                                 :relation_type => IssueRelation::TYPE_PRECEDES)
-
-    assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
-  end
-
-  def test_all_dependent_issues_with_subtask
-    IssueRelation.delete_all
-
-    project = Project.generate!(:name => "testproject")
-
-    parentIssue = Issue.generate!(:project => project)
-    childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
-    childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
-
-    assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
-  end
-
-  def test_all_dependent_issues_does_not_include_self
-    IssueRelation.delete_all
-
-    project = Project.generate!(:name => "testproject")
-
-    parentIssue = Issue.generate!(:project => project)
-    childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
-
-    assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
-  end
-
-  def test_all_dependent_issues_with_parenttask_and_sibling
-    IssueRelation.delete_all
-
-    project = Project.generate!(:name => "testproject")
-
-    parentIssue = Issue.generate!(:project => project)
-    childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
-    childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
-
-    assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
-  end
-
-  def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
-    IssueRelation.delete_all
-
-    project = Project.generate!(:name => "testproject")
-
-    parentIssue1 = Issue.generate!(:project => project)
-    childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
-    childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
-
-    parentIssue2 = Issue.generate!(:project => project)
-    childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
-    childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
-
-
-    assert IssueRelation.create(:issue_from => parentIssue1,
-                                :issue_to   => childIssue2_2,
-                                :relation_type => IssueRelation::TYPE_BLOCKS)
-
-    assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
-                 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
-  end
-
-  def test_all_dependent_issues_with_relation_to_parent_in_other_tree
-    IssueRelation.delete_all
-
-    project = Project.generate!(:name => "testproject")
-
-    parentIssue1 = Issue.generate!(:project => project)
-    childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
-    childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
-
-    parentIssue2 = Issue.generate!(:project => project)
-    childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
-    childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
-
-
-    assert IssueRelation.create(:issue_from => parentIssue1,
-                                :issue_to   => parentIssue2,
-                                :relation_type => IssueRelation::TYPE_BLOCKS)
-
-    assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
-                 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
-  end
-
-  def test_all_dependent_issues_with_transitive_relation
-    IssueRelation.delete_all
-
-    project = Project.generate!(:name => "testproject")
-
-    parentIssue1 = Issue.generate!(:project => project)
-    childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
-
-    parentIssue2 = Issue.generate!(:project => project)
-    childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
-
-    independentIssue = Issue.generate!(:project => project)
-
-    assert IssueRelation.create(:issue_from => parentIssue1,
-                                :issue_to   => childIssue2_1,
-                                :relation_type => IssueRelation::TYPE_RELATES)
-
-    assert IssueRelation.create(:issue_from => childIssue2_1,
-                                :issue_to   => independentIssue,
-                                :relation_type => IssueRelation::TYPE_RELATES)
-
-    assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
-                 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
-  end
-
-  def test_all_dependent_issues_with_transitive_relation2
-    IssueRelation.delete_all
-
-    project = Project.generate!(:name => "testproject")
-
-    parentIssue1 = Issue.generate!(:project => project)
-    childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
-
-    parentIssue2 = Issue.generate!(:project => project)
-    childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
-
-    independentIssue = Issue.generate!(:project => project)
-
-    assert IssueRelation.create(:issue_from => parentIssue1,
-                                :issue_to   => independentIssue,
-                                :relation_type => IssueRelation::TYPE_RELATES)
-
-    assert IssueRelation.create(:issue_from => independentIssue,
-                                :issue_to   => childIssue2_1,
-                                :relation_type => IssueRelation::TYPE_RELATES)
-
-    assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
-                 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
-
-  end
-
-  def test_all_dependent_issues_with_persistent_circular_dependency
-    IssueRelation.delete_all
-    assert IssueRelation.create!(:issue_from => Issue.find(1),
-                                 :issue_to   => Issue.find(2),
-                                 :relation_type => IssueRelation::TYPE_PRECEDES)
-    assert IssueRelation.create!(:issue_from => Issue.find(2),
-                                 :issue_to   => Issue.find(3),
-                                 :relation_type => IssueRelation::TYPE_PRECEDES)
-
-    r = IssueRelation.create!(:issue_from => Issue.find(3),
-                             :issue_to   => Issue.find(7),
-                             :relation_type => IssueRelation::TYPE_PRECEDES)
-    IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
-
-    assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
-  end
-
-  def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
-    IssueRelation.delete_all
-    assert IssueRelation.create!(:issue_from => Issue.find(1),
-                                 :issue_to   => Issue.find(2),
-                                 :relation_type => IssueRelation::TYPE_RELATES)
-    assert IssueRelation.create!(:issue_from => Issue.find(2),
-                                 :issue_to   => Issue.find(3),
-                                 :relation_type => IssueRelation::TYPE_RELATES)
-    assert IssueRelation.create!(:issue_from => Issue.find(3),
-                                 :issue_to   => Issue.find(8),
-                                 :relation_type => IssueRelation::TYPE_RELATES)
-
-    r = IssueRelation.create!(:issue_from => Issue.find(8),
-                             :issue_to   => Issue.find(7),
-                             :relation_type => IssueRelation::TYPE_RELATES)
-    IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
-
-    r = IssueRelation.create!(:issue_from => Issue.find(3),
-                             :issue_to   => Issue.find(7),
-                             :relation_type => IssueRelation::TYPE_RELATES)
-    IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
-
-    assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
-  end
-
-  test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
-    @issue = Issue.find(1)
-    @issue_status = IssueStatus.find(1)
-    @issue_status.update_attribute(:default_done_ratio, 50)
-    @issue2 = Issue.find(2)
-    @issue_status2 = IssueStatus.find(2)
-    @issue_status2.update_attribute(:default_done_ratio, 0)
-
-    with_settings :issue_done_ratio => 'issue_field' do
-      assert_equal 0, @issue.done_ratio
-      assert_equal 30, @issue2.done_ratio
-    end
-
-    with_settings :issue_done_ratio => 'issue_status' do
-      assert_equal 50, @issue.done_ratio
-      assert_equal 0, @issue2.done_ratio
-    end
-  end
-
-  test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
-    @issue = Issue.find(1)
-    @issue_status = IssueStatus.find(1)
-    @issue_status.update_attribute(:default_done_ratio, 50)
-    @issue2 = Issue.find(2)
-    @issue_status2 = IssueStatus.find(2)
-    @issue_status2.update_attribute(:default_done_ratio, 0)
-
-    with_settings :issue_done_ratio => 'issue_field' do
-      @issue.update_done_ratio_from_issue_status
-      @issue2.update_done_ratio_from_issue_status
-
-      assert_equal 0, @issue.read_attribute(:done_ratio)
-      assert_equal 30, @issue2.read_attribute(:done_ratio)
-    end
-
-    with_settings :issue_done_ratio => 'issue_status' do
-      @issue.update_done_ratio_from_issue_status
-      @issue2.update_done_ratio_from_issue_status
-
-      assert_equal 50, @issue.read_attribute(:done_ratio)
-      assert_equal 0, @issue2.read_attribute(:done_ratio)
-    end
-  end
-
-  test "#by_tracker" do
-    User.current = User.anonymous
-    groups = Issue.by_tracker(Project.find(1))
-    assert_equal 3, groups.count
-    assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
-  end
-
-  test "#by_version" do
-    User.current = User.anonymous
-    groups = Issue.by_version(Project.find(1))
-    assert_equal 3, groups.count
-    assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
-  end
-
-  test "#by_priority" do
-    User.current = User.anonymous
-    groups = Issue.by_priority(Project.find(1))
-    assert_equal 4, groups.count
-    assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
-  end
-
-  test "#by_category" do
-    User.current = User.anonymous
-    groups = Issue.by_category(Project.find(1))
-    assert_equal 2, groups.count
-    assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
-  end
-
-  test "#by_assigned_to" do
-    User.current = User.anonymous
-    groups = Issue.by_assigned_to(Project.find(1))
-    assert_equal 2, groups.count
-    assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
-  end
-
-  test "#by_author" do
-    User.current = User.anonymous
-    groups = Issue.by_author(Project.find(1))
-    assert_equal 4, groups.count
-    assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
-  end
-
-  test "#by_subproject" do
-    User.current = User.anonymous
-    groups = Issue.by_subproject(Project.find(1))
-    # Private descendant not visible
-    assert_equal 1, groups.count
-    assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
-  end
-
-  def test_recently_updated_scope
-    #should return the last updated issue
-    assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
-  end
-
-  def test_on_active_projects_scope
-    assert Project.find(2).archive
-
-    before = Issue.on_active_project.length
-    # test inclusion to results
-    issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
-    assert_equal before + 1, Issue.on_active_project.length
-
-    # Move to an archived project
-    issue.project = Project.find(2)
-    assert issue.save
-    assert_equal before, Issue.on_active_project.length
-  end
-
-  test "Issue#recipients should include project recipients" do
-    issue = Issue.generate!
-    assert issue.project.recipients.present?
-    issue.project.recipients.each do |project_recipient|
-      assert issue.recipients.include?(project_recipient)
-    end
-  end
-
-  test "Issue#recipients should include the author if the author is active" do
-    issue = Issue.generate!(:author => User.generate!)
-    assert issue.author, "No author set for Issue"
-    assert issue.recipients.include?(issue.author.mail)
-  end
-
-  test "Issue#recipients should include the assigned to user if the assigned to user is active" do
-    issue = Issue.generate!(:assigned_to => User.generate!)
-    assert issue.assigned_to, "No assigned_to set for Issue"
-    assert issue.recipients.include?(issue.assigned_to.mail)
-  end
-
-  test "Issue#recipients should not include users who opt out of all email" do
-    issue = Issue.generate!(:author => User.generate!)
-    issue.author.update_attribute(:mail_notification, :none)
-    assert !issue.recipients.include?(issue.author.mail)
-  end
-
-  test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
-    issue = Issue.generate!(:author => User.generate!)
-    issue.author.update_attribute(:mail_notification, :only_assigned)
-    assert !issue.recipients.include?(issue.author.mail)
-  end
-
-  test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
-    issue = Issue.generate!(:assigned_to => User.generate!)
-    issue.assigned_to.update_attribute(:mail_notification, :only_owner)
-    assert !issue.recipients.include?(issue.assigned_to.mail)
-  end
-
-  def test_last_journal_id_with_journals_should_return_the_journal_id
-    assert_equal 2, Issue.find(1).last_journal_id
-  end
-
-  def test_last_journal_id_without_journals_should_return_nil
-    assert_nil Issue.find(3).last_journal_id
-  end
-
-  def test_journals_after_should_return_journals_with_greater_id
-    assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
-    assert_equal [], Issue.find(1).journals_after('2')
-  end
-
-  def test_journals_after_with_blank_arg_should_return_all_journals
-    assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
-  end
-
-  def test_css_classes_should_include_tracker
-    issue = Issue.new(:tracker => Tracker.find(2))
-    classes = issue.css_classes.split(' ')
-    assert_include 'tracker-2', classes
-  end
-
-  def test_css_classes_should_include_priority
-    issue = Issue.new(:priority => IssuePriority.find(8))
-    classes = issue.css_classes.split(' ')
-    assert_include 'priority-8', classes
-    assert_include 'priority-highest', classes
-  end
-
-  def test_css_classes_should_include_user_assignment
-    issue = Issue.generate(:assigned_to_id => 2)
-    assert_include 'assigned-to-me', issue.css_classes(User.find(2))
-    assert_not_include 'assigned-to-me', issue.css_classes(User.find(3))
-  end
-
-  def test_css_classes_should_include_user_group_assignment
-    issue = Issue.generate(:assigned_to_id => 10)
-    assert_include 'assigned-to-my-group', issue.css_classes(Group.find(10).users.first)
-    assert_not_include 'assigned-to-my-group', issue.css_classes(User.find(3))
-  end
-
-  def test_save_attachments_with_hash_should_save_attachments_in_keys_order
-    set_tmp_attachments_directory
-    issue = Issue.generate!
-    issue.save_attachments({
-      'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
-      '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
-      '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
-    })
-    issue.attach_saved_attachments
-
-    assert_equal 3, issue.reload.attachments.count
-    assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
-  end
-
-  def test_closed_on_should_be_nil_when_creating_an_open_issue
-    issue = Issue.generate!(:status_id => 1).reload
-    assert !issue.closed?
-    assert_nil issue.closed_on
-  end
-
-  def test_closed_on_should_be_set_when_creating_a_closed_issue
-    issue = Issue.generate!(:status_id => 5).reload
-    assert issue.closed?
-    assert_not_nil issue.closed_on
-    assert_equal issue.updated_on, issue.closed_on
-    assert_equal issue.created_on, issue.closed_on
-  end
-
-  def test_closed_on_should_be_nil_when_updating_an_open_issue
-    issue = Issue.find(1)
-    issue.subject = 'Not closed yet'
-    issue.save!
-    issue.reload
-    assert_nil issue.closed_on
-  end
-
-  def test_closed_on_should_be_set_when_closing_an_open_issue
-    issue = Issue.find(1)
-    issue.subject = 'Now closed'
-    issue.status_id = 5
-    issue.save!
-    issue.reload
-    assert_not_nil issue.closed_on
-    assert_equal issue.updated_on, issue.closed_on
-  end
-
-  def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
-    issue = Issue.open(false).first
-    was_closed_on = issue.closed_on
-    assert_not_nil was_closed_on
-    issue.subject = 'Updating a closed issue'
-    issue.save!
-    issue.reload
-    assert_equal was_closed_on, issue.closed_on
-  end
-
-  def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
-    issue = Issue.open(false).first
-    was_closed_on = issue.closed_on
-    assert_not_nil was_closed_on
-    issue.subject = 'Reopening a closed issue'
-    issue.status_id = 1
-    issue.save!
-    issue.reload
-    assert !issue.closed?
-    assert_equal was_closed_on, issue.closed_on
-  end
-
-  def test_status_was_should_return_nil_for_new_issue
-    issue = Issue.new
-    assert_nil issue.status_was
-  end
-
-  def test_status_was_should_return_status_before_change
-    issue = Issue.find(1)
-    issue.status = IssueStatus.find(2)
-    assert_equal IssueStatus.find(1), issue.status_was
-  end
-
-  def test_status_was_should_be_reset_on_save
-    issue = Issue.find(1)
-    issue.status = IssueStatus.find(2)
-    assert_equal IssueStatus.find(1), issue.status_was
-    assert issue.save!
-    assert_equal IssueStatus.find(2), issue.status_was
-  end
-end
--- a/.svn/pristine/7c/7c4ad291b9dee635242d3836e9f5883b5338f41d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssueStatusesController < ApplicationController
-  layout 'admin'
-
-  before_filter :require_admin, :except => :index
-  before_filter :require_admin_or_api_request, :only => :index
-  accept_api_auth :index
-
-  def index
-    respond_to do |format|
-      format.html {
-        @issue_status_pages, @issue_statuses = paginate IssueStatus.sorted, :per_page => 25
-        render :action => "index", :layout => false if request.xhr?
-      }
-      format.api {
-        @issue_statuses = IssueStatus.all(:order => 'position')
-      }
-    end
-  end
-
-  def new
-    @issue_status = IssueStatus.new
-  end
-
-  def create
-    @issue_status = IssueStatus.new(params[:issue_status])
-    if @issue_status.save
-      flash[:notice] = l(:notice_successful_create)
-      redirect_to issue_statuses_path
-    else
-      render :action => 'new'
-    end
-  end
-
-  def edit
-    @issue_status = IssueStatus.find(params[:id])
-  end
-
-  def update
-    @issue_status = IssueStatus.find(params[:id])
-    if @issue_status.update_attributes(params[:issue_status])
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to issue_statuses_path
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def destroy
-    IssueStatus.find(params[:id]).destroy
-    redirect_to issue_statuses_path
-  rescue
-    flash[:error] = l(:error_unable_delete_issue_status)
-    redirect_to issue_statuses_path
-  end
-
-  def update_issue_done_ratio
-    if request.post? && IssueStatus.update_issue_done_ratios
-      flash[:notice] = l(:notice_issue_done_ratios_updated)
-    else
-      flash[:error] =  l(:error_issue_done_ratios_not_updated)
-    end
-    redirect_to issue_statuses_path
-  end
-end
--- a/.svn/pristine/7d/7d062943a639ef0006481fe9e87f6780c25c226e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingMessagesTest < ActionController::IntegrationTest
-  def test_messages
-    assert_routing(
-        { :method => 'get', :path => "/boards/22/topics/2" },
-        { :controller => 'messages', :action => 'show', :id => '2',
-          :board_id => '22' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/boards/lala/topics/new" },
-        { :controller => 'messages', :action => 'new', :board_id => 'lala' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/boards/lala/topics/22/edit" },
-        { :controller => 'messages', :action => 'edit', :id => '22',
-          :board_id => 'lala' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/boards/lala/topics/quote/22" },
-        { :controller => 'messages', :action => 'quote', :id => '22',
-          :board_id => 'lala' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/boards/lala/topics/new" },
-        { :controller => 'messages', :action => 'new', :board_id => 'lala' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/boards/lala/topics/preview" },
-        { :controller => 'messages', :action => 'preview',
-          :board_id => 'lala' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/boards/lala/topics/22/edit" },
-        { :controller => 'messages', :action => 'edit', :id => '22',
-          :board_id => 'lala' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/boards/22/topics/555/replies" },
-        { :controller => 'messages', :action => 'reply', :id => '555',
-          :board_id => '22' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/boards/22/topics/555/destroy" },
-        { :controller => 'messages', :action => 'destroy', :id => '555',
-          :board_id => '22' }
-      )
-  end
-end
--- a/.svn/pristine/7d/7d347f5736383447d929cfa493b44727c73c536a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-
-class Redmine::Views::Builders::XmlTest < ActiveSupport::TestCase
-
-  def test_hash
-    assert_xml_output('<person><name>Ryan</name><age>32</age></person>') do |b|
-      b.person do
-        b.name 'Ryan'
-        b.age  32
-      end
-    end
-  end
-
-  def test_array
-    assert_xml_output('<books type="array"><book title="Book 1"/><book title="Book 2"/></books>') do |b|
-      b.array :books do |b|
-        b.book :title => 'Book 1'
-        b.book :title => 'Book 2'
-      end
-    end
-  end
-
-  def test_array_with_content_tags
-    assert_xml_output('<books type="array"><book author="B. Smith">Book 1</book><book author="G. Cooper">Book 2</book></books>') do |b|
-      b.array :books do |b|
-        b.book 'Book 1', :author => 'B. Smith'
-        b.book 'Book 2', :author => 'G. Cooper'
-      end
-    end
-  end
-
-  def test_nested_arrays
-    assert_xml_output('<books type="array"><book><authors type="array"><author>B. Smith</author><author>G. Cooper</author></authors></book></books>') do |b|
-      b.array :books do |books|
-        books.book do |book|
-          book.array :authors do |authors|
-            authors.author 'B. Smith'
-            authors.author 'G. Cooper'
-          end
-        end
-      end
-    end
-  end
-
-  def assert_xml_output(expected, &block)
-    builder = Redmine::Views::Builders::Xml.new(ActionDispatch::TestRequest.new, ActionDispatch::TestResponse.new)
-    block.call(builder)
-    assert_equal('<?xml version="1.0" encoding="UTF-8"?>' + expected, builder.output)
-  end
-end
--- a/.svn/pristine/7e/7e362e9571e296e9ab312aca34fbe7dfde644cd2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-module RedminePmTest
-  class TestCase < ActiveSupport::TestCase
-    attr_reader :command, :response, :status, :username, :password
-    
-    # Cannot use transactional fixtures here: database
-    # will be accessed from Redmine.pm with its own connection
-    self.use_transactional_fixtures = false
-  
-    def test_dummy
-    end
-  
-    protected
-  
-    def assert_response(expected, msg=nil)
-      case expected
-      when :success
-        assert_equal 0, status,
-          (msg || "The command failed (exit: #{status}):\n  #{command}\nOutput was:\n#{formatted_response}")
-      when :failure
-        assert_not_equal 0, status,
-          (msg || "The command succeed (exit: #{status}):\n  #{command}\nOutput was:\n#{formatted_response}")
-      else
-        assert_equal expected, status, msg
-      end
-    end
-  
-    def assert_success(*args)
-      execute *args
-      assert_response :success
-    end
-  
-    def assert_failure(*args)
-      execute *args
-      assert_response :failure
-    end
-    
-    def with_credentials(username, password)
-      old_username, old_password = @username, @password
-      @username, @password = username, password
-      yield if block_given?
-    ensure
-      @username, @password = old_username, old_password
-    end
-    
-    def execute(*args)
-      @command = args.join(' ')
-      @status = nil
-      IO.popen("#{command} 2>&1") do |io|
-        @response = io.read
-      end
-      @status = $?.exitstatus
-    end
-  
-    def formatted_response
-      "#{'='*40}\n#{response}#{'='*40}"
-    end
-  
-    def random_filename
-      Redmine::Utils.random_hex(16)
-    end
-  end
-end
--- a/.svn/pristine/7f/7f4c045aa51ecaded0b2c44282890f940876ab00.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingFilesTest < ActionController::IntegrationTest
-  def test_files
-    assert_routing(
-        { :method => 'get', :path => "/projects/33/files" },
-        { :controller => 'files', :action => 'index', :project_id => '33' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/33/files/new" },
-        { :controller => 'files', :action => 'new', :project_id => '33' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/33/files" },
-        { :controller => 'files', :action => 'create', :project_id => '33' }
-      )
-  end
-end
--- a/.svn/pristine/7f/7f767334e88e235349f209d5526da1c032d7d91c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/subversion_adapter'
-
-class Repository::Subversion < Repository
-  attr_protected :root_url
-  validates_presence_of :url
-  validates_format_of :url, :with => %r{\A(http|https|svn(\+[^\s:\/\\]+)?|file):\/\/.+}i
-
-  def self.scm_adapter_class
-    Redmine::Scm::Adapters::SubversionAdapter
-  end
-
-  def self.scm_name
-    'Subversion'
-  end
-
-  def supports_directory_revisions?
-    true
-  end
-
-  def repo_log_encoding
-    'UTF-8'
-  end
-
-  def latest_changesets(path, rev, limit=10)
-    revisions = scm.revisions(path, rev, nil, :limit => limit)
-    if revisions
-      identifiers = revisions.collect(&:identifier).compact
-      changesets.where(:revision => identifiers).reorder("committed_on DESC").includes(:repository, :user).all
-    else
-      []
-    end
-  end
-
-  # Returns a path relative to the url of the repository
-  def relative_path(path)
-    path.gsub(Regexp.new("^\/?#{Regexp.escape(relative_url)}"), '')
-  end
-
-  def fetch_changesets
-    scm_info = scm.info
-    if scm_info
-      # latest revision found in database
-      db_revision = latest_changeset ? latest_changeset.revision.to_i : 0
-      # latest revision in the repository
-      scm_revision = scm_info.lastrev.identifier.to_i
-      if db_revision < scm_revision
-        logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
-        identifier_from = db_revision + 1
-        while (identifier_from <= scm_revision)
-          # loads changesets by batches of 200
-          identifier_to = [identifier_from + 199, scm_revision].min
-          revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
-          revisions.reverse_each do |revision|
-            transaction do
-              changeset = Changeset.create(:repository   => self,
-                                           :revision     => revision.identifier,
-                                           :committer    => revision.author,
-                                           :committed_on => revision.time,
-                                           :comments     => revision.message)
-
-              revision.paths.each do |change|
-                changeset.create_change(change)
-              end unless changeset.new_record?
-            end
-          end unless revisions.nil?
-          identifier_from = identifier_to + 1
-        end
-      end
-    end
-  end
-
-  protected
-
-  def load_entries_changesets(entries)
-    return unless entries
-
-    entries_with_identifier = entries.select {|entry| entry.lastrev && entry.lastrev.identifier.present?}
-    identifiers = entries_with_identifier.map {|entry| entry.lastrev.identifier}.compact.uniq
-
-    if identifiers.any?
-      changesets_by_identifier = changesets.where(:revision => identifiers).includes(:user, :repository).all.group_by(&:revision)
-      entries_with_identifier.each do |entry|
-        if m = changesets_by_identifier[entry.lastrev.identifier]
-          entry.changeset = m.first
-        end
-      end
-    end
-  end
-
-  private
-
-  # Returns the relative url of the repository
-  # Eg: root_url = file:///var/svn/foo
-  #     url      = file:///var/svn/foo/bar
-  #     => returns /bar
-  def relative_url
-    @relative_url ||= url.gsub(Regexp.new("^#{Regexp.escape(root_url || scm.root_url)}", Regexp::IGNORECASE), '')
-  end
-end
--- a/.svn/pristine/80/801b8da4e3d5456a0e7124a4e9736317dd235f5b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,377 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoryMercurialTest < ActiveSupport::TestCase
-  fixtures :projects
-
-  include Redmine::I18n
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
-  NUM_REV = 32
-  CHAR_1_HEX = "\xc3\x9c"
-
-  def setup
-    @project    = Project.find(3)
-    @repository = Repository::Mercurial.create(
-                      :project => @project,
-                      :url     => REPOSITORY_PATH,
-                      :path_encoding => 'ISO-8859-1'
-                      )
-    assert @repository
-    @char_1        = CHAR_1_HEX.dup
-    @tag_char_1    = "tag-#{CHAR_1_HEX}-00"
-    @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
-    @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
-    if @char_1.respond_to?(:force_encoding)
-      @char_1.force_encoding('UTF-8')
-      @tag_char_1.force_encoding('UTF-8')
-      @branch_char_0.force_encoding('UTF-8')
-      @branch_char_1.force_encoding('UTF-8')
-    end
-  end
-
-
-  def test_blank_path_to_repository_error_message
-    set_language_if_valid 'en'
-    repo = Repository::Mercurial.new(
-                          :project      => @project,
-                          :identifier   => 'test'
-                        )
-    assert !repo.save
-    assert_include "Path to repository can't be blank",
-                   repo.errors.full_messages
-  end
-
-  def test_blank_path_to_repository_error_message_fr
-    set_language_if_valid 'fr'
-    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    repo = Repository::Mercurial.new(
-                          :project      => @project,
-                          :url          => "",
-                          :identifier   => 'test',
-                          :path_encoding => ''
-                        )
-    assert !repo.save
-    assert_include str, repo.errors.full_messages
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    def test_scm_available
-      klass = Repository::Mercurial
-      assert_equal "Mercurial", klass.scm_name
-      assert klass.scm_adapter_class
-      assert_not_equal "", klass.scm_command
-      assert_equal true, klass.scm_available
-    end
-
-    def test_entries
-      entries = @repository.entries
-      assert_kind_of Redmine::Scm::Adapters::Entries, entries
-    end
-
-    def test_fetch_changesets_from_scratch
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_equal 46, @repository.filechanges.count
-      assert_equal "Initial import.\nThe repository contains 3 files.",
-                   @repository.changesets.find_by_revision('0').comments
-    end
-
-    def test_fetch_changesets_incremental
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      # Remove changesets with revision > 2
-      @repository.changesets.all.each {|c| c.destroy if c.revision.to_i > 2}
-      @project.reload
-      assert_equal 3, @repository.changesets.count
-
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-    end
-
-    def test_isodatesec
-      # Template keyword 'isodatesec' supported in Mercurial 1.0 and higher
-      if @repository.scm.class.client_version_above?([1, 0])
-        assert_equal 0, @repository.changesets.count
-        @repository.fetch_changesets
-        @project.reload
-        assert_equal NUM_REV, @repository.changesets.count
-        rev0_committed_on = Time.gm(2007, 12, 14, 9, 22, 52)
-        assert_equal @repository.changesets.find_by_revision('0').committed_on, rev0_committed_on
-      end
-    end
-
-    def test_changeset_order_by_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      c0 = @repository.latest_changeset
-      c1 = @repository.changesets.find_by_revision('0')
-      # sorted by revision (id), not by date
-      assert c0.revision.to_i > c1.revision.to_i
-      assert c0.committed_on  < c1.committed_on
-    end
-
-    def test_latest_changesets
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      # with_limit
-      changesets = @repository.latest_changesets('', nil, 2)
-      assert_equal %w|31 30|, changesets.collect(&:revision)
-
-      # with_filepath
-      changesets = @repository.latest_changesets(
-                      '/sql_escape/percent%dir/percent%file1.txt', nil)
-      assert_equal %w|30 11 10 9|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets(
-                      '/sql_escape/underscore_dir/understrike_file.txt', nil)
-      assert_equal %w|30 12 9|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README', nil)
-      assert_equal %w|31 30 28 17 8 6 1 0|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README','8')
-      assert_equal %w|8 6 1 0|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('README','8', 2)
-      assert_equal %w|8 6|, changesets.collect(&:revision)
-
-      # with_dirpath
-      changesets = @repository.latest_changesets('images', nil)
-      assert_equal %w|1 0|, changesets.collect(&:revision)
-
-      path = 'sql_escape/percent%dir'
-      changesets = @repository.latest_changesets(path, nil)
-      assert_equal %w|30 13 11 10 9|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets(path, '11')
-      assert_equal %w|11 10 9|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets(path, '11', 2)
-      assert_equal %w|11 10|, changesets.collect(&:revision)
-
-      path = 'sql_escape/underscore_dir'
-      changesets = @repository.latest_changesets(path, nil)
-      assert_equal %w|30 13 12 9|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets(path, '12')
-      assert_equal %w|12 9|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets(path, '12', 1)
-      assert_equal %w|12|, changesets.collect(&:revision)
-
-      # tag
-      changesets = @repository.latest_changesets('', 'tag_test.00')
-      assert_equal %w|5 4 3 2 1 0|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('', 'tag_test.00', 2)
-      assert_equal %w|5 4|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('sources', 'tag_test.00')
-      assert_equal %w|4 3 2 1 0|, changesets.collect(&:revision)
-
-      changesets = @repository.latest_changesets('sources', 'tag_test.00', 2)
-      assert_equal %w|4 3|, changesets.collect(&:revision)
-
-      # named branch
-      if @repository.scm.class.client_version_above?([1, 6])
-        changesets = @repository.latest_changesets('', @branch_char_1)
-        assert_equal %w|27 26|, changesets.collect(&:revision)
-      end
-
-      changesets = @repository.latest_changesets("latin-1-dir/test-#{@char_1}-subdir", @branch_char_1)
-      assert_equal %w|27|, changesets.collect(&:revision)
-    end
-
-    def test_copied_files
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      cs1 = @repository.changesets.find_by_revision('13')
-      assert_not_nil cs1
-      c1  = cs1.filechanges.sort_by(&:path)
-      assert_equal 2, c1.size
-
-      assert_equal 'A', c1[0].action
-      assert_equal '/sql_escape/percent%dir/percentfile1.txt',  c1[0].path
-      assert_equal '/sql_escape/percent%dir/percent%file1.txt', c1[0].from_path
-      assert_equal '3a330eb32958', c1[0].from_revision
-
-      assert_equal 'A', c1[1].action
-      assert_equal '/sql_escape/underscore_dir/understrike-file.txt', c1[1].path
-      assert_equal '/sql_escape/underscore_dir/understrike_file.txt', c1[1].from_path
-
-      cs2 = @repository.changesets.find_by_revision('15')
-      c2  = cs2.filechanges
-      assert_equal 1, c2.size
-
-      assert_equal 'A', c2[0].action
-      assert_equal '/README (1)[2]&,%.-3_4', c2[0].path
-      assert_equal '/README', c2[0].from_path
-      assert_equal '933ca60293d7', c2[0].from_revision
-
-      cs3 = @repository.changesets.find_by_revision('19')
-      c3  = cs3.filechanges
-      assert_equal 1, c3.size
-      assert_equal 'A', c3[0].action
-      assert_equal "/latin-1-dir/test-#{@char_1}-1.txt",  c3[0].path
-      assert_equal "/latin-1-dir/test-#{@char_1}.txt",    c3[0].from_path
-      assert_equal '5d9891a1b425', c3[0].from_revision
-    end
-
-    def test_find_changeset_by_name
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      %w|2 400bb8672109 400|.each do |r|
-        assert_equal '2', @repository.find_changeset_by_name(r).revision
-      end
-    end
-
-    def test_find_changeset_by_invalid_name
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_nil @repository.find_changeset_by_name('100000')
-    end
-
-    def test_identifier
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      c = @repository.changesets.find_by_revision('2')
-      assert_equal c.scmid, c.identifier
-    end
-
-    def test_format_identifier
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      c = @repository.changesets.find_by_revision('2')
-      assert_equal '2:400bb8672109', c.format_identifier
-    end
-
-    def test_find_changeset_by_empty_name
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['', ' ', nil].each do |r|
-        assert_nil @repository.find_changeset_by_name(r)
-      end
-    end
-
-    def test_parents
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      r1 = @repository.changesets.find_by_revision('0')
-      assert_equal [], r1.parents
-      r2 = @repository.changesets.find_by_revision('1')
-      assert_equal 1, r2.parents.length
-      assert_equal "0885933ad4f6",
-                   r2.parents[0].identifier
-      r3 = @repository.changesets.find_by_revision('30')
-      assert_equal 2, r3.parents.length
-      r4 = [r3.parents[0].identifier, r3.parents[1].identifier].sort
-      assert_equal "3a330eb32958", r4[0]
-      assert_equal "a94b0528f24f", r4[1]
-    end
-
-    def test_activities
-      c = Changeset.new(:repository   => @repository,
-                        :committed_on => Time.now,
-                        :revision     => '123',
-                        :scmid        => 'abc400bb8672',
-                        :comments     => 'test')
-      assert c.event_title.include?('123:abc400bb8672:')
-      assert_equal 'abc400bb8672', c.event_url[:rev]
-    end
-
-    def test_previous
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      %w|28 3ae45e2d177d 3ae45|.each do |r1|
-        changeset = @repository.find_changeset_by_name(r1)
-        %w|27 7bbf4c738e71 7bbf|.each do |r2|
-          assert_equal @repository.find_changeset_by_name(r2), changeset.previous
-        end
-      end
-    end
-
-    def test_previous_nil
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      %w|0 0885933ad4f6 0885|.each do |r1|
-        changeset = @repository.find_changeset_by_name(r1)
-        assert_nil changeset.previous
-      end
-    end
-
-    def test_next
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      %w|27 7bbf4c738e71 7bbf|.each do |r2|
-        changeset = @repository.find_changeset_by_name(r2)
-        %w|28 3ae45e2d177d 3ae45|.each do |r1|
-        assert_equal @repository.find_changeset_by_name(r1), changeset.next
-        end
-      end
-    end
-
-    def test_next_nil
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      %w|31 31eeee7395c8 31eee|.each do |r1|
-        changeset = @repository.find_changeset_by_name(r1)
-        assert_nil changeset.next
-      end
-    end
-  else
-    puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/80/803dbec2bea6411200938908113051447e1d81f1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'digest/md5'
-
-module Redmine
-  module WikiFormatting
-    class StaleSectionError < Exception; end
-
-    @@formatters = {}
-
-    class << self
-      def map
-        yield self
-      end
-
-      def register(name, formatter, helper)
-        raise ArgumentError, "format name '#{name}' is already taken" if @@formatters[name.to_s]
-        @@formatters[name.to_s] = {:formatter => formatter, :helper => helper}
-      end
-
-      def formatter
-        formatter_for(Setting.text_formatting)
-      end
-
-      def formatter_for(name)
-        entry = @@formatters[name.to_s]
-        (entry && entry[:formatter]) || Redmine::WikiFormatting::NullFormatter::Formatter
-      end
-
-      def helper_for(name)
-        entry = @@formatters[name.to_s]
-        (entry && entry[:helper]) || Redmine::WikiFormatting::NullFormatter::Helper
-      end
-
-      def format_names
-        @@formatters.keys.map
-      end
-
-      def to_html(format, text, options = {})
-        text = if Setting.cache_formatted_text? && text.size > 2.kilobyte && cache_store && cache_key = cache_key_for(format, text, options[:object], options[:attribute])
-          # Text retrieved from the cache store may be frozen
-          # We need to dup it so we can do in-place substitutions with gsub!
-          cache_store.fetch cache_key do
-            formatter_for(format).new(text).to_html
-          end.dup
-        else
-          formatter_for(format).new(text).to_html
-        end
-        text
-      end
-
-      # Returns true if the text formatter supports single section edit
-      def supports_section_edit?
-        (formatter.instance_methods & ['update_section', :update_section]).any?
-      end
-
-      # Returns a cache key for the given text +format+, +text+, +object+ and +attribute+ or nil if no caching should be done
-      def cache_key_for(format, text, object, attribute)
-        if object && attribute && !object.new_record? && format.present?
-          "formatted_text/#{format}/#{object.class.model_name.cache_key}/#{object.id}-#{attribute}-#{Digest::MD5.hexdigest text}"
-        end
-      end
-
-      # Returns the cache store used to cache HTML output
-      def cache_store
-        ActionController::Base.cache_store
-      end
-    end
-
-    module LinksHelper
-      AUTO_LINK_RE = %r{
-                      (                          # leading text
-                        <\w+.*?>|                # leading HTML tag, or
-                        [\s\(\[,;]|              # leading punctuation, or
-                        ^                        # beginning of line
-                      )
-                      (
-                        (?:https?://)|           # protocol spec, or
-                        (?:s?ftps?://)|
-                        (?:www\.)                # www.*
-                      )
-                      (
-                        ([^<]\S*?)               # url
-                        (\/)?                    # slash
-                      )
-                      ((?:&gt;)?|[^[:alnum:]_\=\/;\(\)]*?)               # post
-                      (?=<|\s|$)
-                     }x unless const_defined?(:AUTO_LINK_RE)
-
-      # Destructively remplaces urls into clickable links
-      def auto_link!(text)
-        text.gsub!(AUTO_LINK_RE) do
-          all, leading, proto, url, post = $&, $1, $2, $3, $6
-          if leading =~ /<a\s/i || leading =~ /![<>=]?/
-            # don't replace URL's that are already linked
-            # and URL's prefixed with ! !> !< != (textile images)
-            all
-          else
-            # Idea below : an URL with unbalanced parethesis and
-            # ending by ')' is put into external parenthesis
-            if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) )
-              url=url[0..-2] # discard closing parenth from url
-              post = ")"+post # add closing parenth to post
-            end
-            content = proto + url
-            href = "#{proto=="www."?"http://www.":proto}#{url}"
-            %(#{leading}<a class="external" href="#{ERB::Util.html_escape href}">#{ERB::Util.html_escape content}</a>#{post}).html_safe
-          end
-        end
-      end
-
-      # Destructively remplaces email addresses into clickable links
-      def auto_mailto!(text)
-        text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
-          mail = $1
-          if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
-            mail
-          else
-            %(<a class="email" href="mailto:#{ERB::Util.html_escape mail}">#{ERB::Util.html_escape mail}</a>).html_safe
-          end
-        end
-      end      
-    end
-
-    # Default formatter module
-    module NullFormatter
-      class Formatter
-        include ActionView::Helpers::TagHelper
-        include ActionView::Helpers::TextHelper
-        include ActionView::Helpers::UrlHelper
-        include Redmine::WikiFormatting::LinksHelper
-
-        def initialize(text)
-          @text = text
-        end
-
-        def to_html(*args)
-          t = CGI::escapeHTML(@text)
-          auto_link!(t)
-          auto_mailto!(t)
-          simple_format(t, {}, :sanitize => false)
-        end
-      end
-
-      module Helper
-        def wikitoolbar_for(field_id)
-        end
-
-        def heads_for_wiki_formatter
-        end
-
-        def initial_page_content(page)
-          page.pretty_title.to_s
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/80/805e2c5bfc6d36709102674e1adfa9d208ce9081.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Document < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  belongs_to :project
-  belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
-  acts_as_attachable :delete_permission => :delete_documents
-
-  acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
-  acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
-                :author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) },
-                :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
-  acts_as_activity_provider :find_options => {:include => :project}
-
-  validates_presence_of :project, :title, :category
-  validates_length_of :title, :maximum => 60
-
-  after_create :send_notification
-
-  scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args))
-  }
-
-  safe_attributes 'category_id', 'title', 'description'
-
-  def visible?(user=User.current)
-    !user.nil? && user.allowed_to?(:view_documents, project)
-  end
-
-  def initialize(attributes=nil, *args)
-    super
-    if new_record?
-      self.category ||= DocumentCategory.default
-    end
-  end
-
-  def updated_on
-    unless @updated_on
-      a = attachments.last
-      @updated_on = (a && a.created_on) || created_on
-    end
-    @updated_on
-  end
-
-  private
-
-  def send_notification
-    if Setting.notified_events.include?('document_added')
-      Mailer.document_added(self).deliver
-    end
-  end
-end
--- a/.svn/pristine/81/81609ac3f30763970c764d86e00b3512d937facd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class Redmine::Utils::DateCalculationTest < ActiveSupport::TestCase
-  include Redmine::Utils::DateCalculation
-
-  def test_working_days_without_non_working_week_days
-    with_settings :non_working_week_days => [] do
-      assert_working_days 18, '2012-10-09', '2012-10-27'
-      assert_working_days  6, '2012-10-09', '2012-10-15'
-      assert_working_days  5, '2012-10-09', '2012-10-14'
-      assert_working_days  3, '2012-10-09', '2012-10-12'
-      assert_working_days  3, '2012-10-14', '2012-10-17'
-      assert_working_days 16, '2012-10-14', '2012-10-30'
-    end
-  end
-
-  def test_working_days_with_non_working_week_days
-    with_settings :non_working_week_days => %w(6 7) do
-      assert_working_days 14, '2012-10-09', '2012-10-27'
-      assert_working_days  4, '2012-10-09', '2012-10-15'
-      assert_working_days  4, '2012-10-09', '2012-10-14'
-      assert_working_days  3, '2012-10-09', '2012-10-12'
-      assert_working_days  8, '2012-10-09', '2012-10-19'
-      assert_working_days  8, '2012-10-11', '2012-10-23'
-      assert_working_days  2, '2012-10-14', '2012-10-17'
-      assert_working_days 11, '2012-10-14', '2012-10-30'
-    end
-  end
-
-  def test_add_working_days_without_non_working_week_days
-    with_settings :non_working_week_days => [] do
-      assert_add_working_days '2012-10-10', '2012-10-10', 0
-      assert_add_working_days '2012-10-11', '2012-10-10', 1
-      assert_add_working_days '2012-10-12', '2012-10-10', 2
-      assert_add_working_days '2012-10-13', '2012-10-10', 3
-      assert_add_working_days '2012-10-25', '2012-10-10', 15
-    end
-  end
-
-  def test_add_working_days_with_non_working_week_days
-    with_settings :non_working_week_days => %w(6 7) do
-      assert_add_working_days '2012-10-10', '2012-10-10', 0
-      assert_add_working_days '2012-10-11', '2012-10-10', 1
-      assert_add_working_days '2012-10-12', '2012-10-10', 2
-      assert_add_working_days '2012-10-15', '2012-10-10', 3
-      assert_add_working_days '2012-10-31', '2012-10-10', 15
-      assert_add_working_days '2012-10-19', '2012-10-09', 8
-      assert_add_working_days '2012-10-23', '2012-10-11', 8
-    end
-  end
-
-  def assert_working_days(expected_days, from, to)
-    assert_equal expected_days, working_days(from.to_date, to.to_date)
-  end
-
-  def assert_add_working_days(expected_date, from, working_days)
-    assert_equal expected_date.to_date, add_working_days(from.to_date, working_days)
-  end
-end
--- a/.svn/pristine/82/821d4ef82eeed4cbb18ce34368856a650d31c2d8.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingTrackersTest < ActionController::IntegrationTest
-  def test_trackers
-    assert_routing(
-        { :method => 'get', :path => "/trackers" },
-        { :controller => 'trackers', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/trackers.xml" },
-        { :controller => 'trackers', :action => 'index', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/trackers" },
-        { :controller => 'trackers', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/trackers.xml" },
-        { :controller => 'trackers', :action => 'create', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/trackers/new" },
-        { :controller => 'trackers', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/trackers/new.xml" },
-        { :controller => 'trackers', :action => 'new', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/trackers/1/edit" },
-        { :controller => 'trackers', :action => 'edit', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/trackers/1" },
-        { :controller => 'trackers', :action => 'update',
-          :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/trackers/1.xml" },
-        { :controller => 'trackers', :action => 'update',
-          :format => 'xml', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/trackers/1" },
-        { :controller => 'trackers', :action => 'destroy',
-          :id => '1' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/trackers/1.xml" },
-        { :controller => 'trackers', :action => 'destroy',
-          :format => 'xml', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/trackers/fields" },
-        { :controller => 'trackers', :action => 'fields' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/trackers/fields" },
-        { :controller => 'trackers', :action => 'fields' }
-      )
-  end
-end
--- a/.svn/pristine/83/83e9bc8b42104b913718f6e8799f58710545ff76.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingDocumentsTest < ActionController::IntegrationTest
-  def test_documents_scoped_under_project
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/documents" },
-        { :controller => 'documents', :action => 'index', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/documents/new" },
-        { :controller => 'documents', :action => 'new', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/567/documents" },
-        { :controller => 'documents', :action => 'create', :project_id => '567' }
-      )
-  end
-
-  def test_documents
-    assert_routing(
-        { :method => 'get', :path => "/documents/22" },
-        { :controller => 'documents', :action => 'show', :id => '22' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/documents/22/edit" },
-        { :controller => 'documents', :action => 'edit', :id => '22' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/documents/22" },
-        { :controller => 'documents', :action => 'update', :id => '22' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/documents/22" },
-        { :controller => 'documents', :action => 'destroy', :id => '22' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/documents/22/add_attachment" },
-        { :controller => 'documents', :action => 'add_attachment', :id => '22' }
-      )
-  end
-end
--- a/.svn/pristine/84/84091f2a3428fd01f5592918d3e84fd8efa86bdf.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class DocumentCategory < Enumeration
-  has_many :documents, :foreign_key => 'category_id'
-
-  OptionName = :enumeration_doc_categories
-
-  def option_name
-    OptionName
-  end
-
-  def objects_count
-    documents.count
-  end
-
-  def transfer_relations(to)
-    documents.update_all("category_id = #{to.id}")
-  end
-
-  def self.default
-    d = super
-    d = first if d.nil?
-    d
-  end
-end
--- a/.svn/pristine/84/841186dcecffe41ae1f674267a63d3d2f8a4647b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingWatchersTest < ActionController::IntegrationTest
-  def test_watchers
-    assert_routing(
-        { :method => 'get', :path => "/watchers/new" },
-        { :controller => 'watchers', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/watchers/append" },
-        { :controller => 'watchers', :action => 'append' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/watchers" },
-        { :controller => 'watchers', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/watchers" },
-        { :controller => 'watchers', :action => 'destroy' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/watchers/autocomplete_for_user" },
-        { :controller => 'watchers', :action => 'autocomplete_for_user' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/watchers/watch" },
-        { :controller => 'watchers', :action => 'watch' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/watchers/watch" },
-        { :controller => 'watchers', :action => 'unwatch' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issues/12/watchers.xml" },
-        { :controller => 'watchers', :action => 'create',
-          :object_type => 'issue', :object_id => '12', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/issues/12/watchers/3.xml" },
-        { :controller => 'watchers', :action => 'destroy',
-          :object_type => 'issue', :object_id => '12', :user_id => '3', :format => 'xml'}
-      )
-  end
-end
--- a/.svn/pristine/84/844e1f7efcdb7d2e09fc680929a5a6cad80561f3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AuthSourceLdapTest < ActiveSupport::TestCase
-  include Redmine::I18n
-  fixtures :auth_sources
-
-  def setup
-  end
-
-  def test_create
-    a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName')
-    assert a.save
-  end
-
-  def test_should_strip_ldap_attributes
-    a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName',
-                           :attr_firstname => 'givenName ')
-    assert a.save
-    assert_equal 'givenName', a.reload.attr_firstname
-  end
-
-  def test_replace_port_zero_to_389
-    a = AuthSourceLdap.new(
-           :name => 'My LDAP', :host => 'ldap.example.net', :port => 0,
-           :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName',
-           :attr_firstname => 'givenName ')
-    assert a.save
-    assert_equal 389, a.port
-  end
-
-  def test_filter_should_be_validated
-    set_language_if_valid 'en'
-
-    a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :attr_login => 'sn')
-    a.filter = "(mail=*@redmine.org"
-    assert !a.valid?
-    assert_include "LDAP filter is invalid", a.errors.full_messages
-
-    a.filter = "(mail=*@redmine.org)"
-    assert a.valid?
-  end
-
-  if ldap_configured?
-    test '#authenticate with a valid LDAP user should return the user attributes' do
-      auth = AuthSourceLdap.find(1)
-      auth.update_attribute :onthefly_register, true
-
-      attributes =  auth.authenticate('example1','123456')
-      assert attributes.is_a?(Hash), "An hash was not returned"
-      assert_equal 'Example', attributes[:firstname]
-      assert_equal 'One', attributes[:lastname]
-      assert_equal 'example1@redmine.org', attributes[:mail]
-      assert_equal auth.id, attributes[:auth_source_id]
-      attributes.keys.each do |attribute|
-        assert User.new.respond_to?("#{attribute}="), "Unexpected :#{attribute} attribute returned"
-      end
-    end
-
-    test '#authenticate with an invalid LDAP user should return nil' do
-      auth = AuthSourceLdap.find(1)
-      assert_equal nil, auth.authenticate('nouser','123456')
-    end
-
-    test '#authenticate without a login should return nil' do
-      auth = AuthSourceLdap.find(1)
-      assert_equal nil, auth.authenticate('','123456')
-    end
-
-    test '#authenticate without a password should return nil' do
-      auth = AuthSourceLdap.find(1)
-      assert_equal nil, auth.authenticate('edavis','')
-    end
-
-    test '#authenticate without filter should return any user' do
-      auth = AuthSourceLdap.find(1)
-      assert auth.authenticate('example1','123456')
-      assert auth.authenticate('edavis', '123456')
-    end
-
-    test '#authenticate with filter should return user who matches the filter only' do
-      auth = AuthSourceLdap.find(1)
-      auth.filter = "(mail=*@redmine.org)"
-
-      assert auth.authenticate('example1','123456')
-      assert_nil auth.authenticate('edavis', '123456')
-    end
-
-    def test_authenticate_should_timeout
-      auth_source = AuthSourceLdap.find(1)
-      auth_source.timeout = 1
-      def auth_source.initialize_ldap_con(*args); sleep(5); end
-
-      assert_raise AuthSourceTimeoutException do
-        auth_source.authenticate 'example1', '123456'
-      end
-    end
-
-    def test_search_should_return_matching_entries
-      results = AuthSource.search("exa")
-      assert_equal 1, results.size
-      result = results.first
-      assert_kind_of Hash, result
-      assert_equal "example1", result[:login]
-      assert_equal "Example", result[:firstname]
-      assert_equal "One", result[:lastname]
-      assert_equal "example1@redmine.org", result[:mail]
-      assert_equal 1, result[:auth_source_id]
-    end
-
-    def test_search_with_no_match_should_return_an_empty_array
-      results = AuthSource.search("wro")
-      assert_equal [], results
-    end
-
-    def test_search_with_exception_should_return_an_empty_array
-      Net::LDAP.stubs(:new).raises(Net::LDAP::LdapError, 'Cannot connect')
-
-      results = AuthSource.search("exa")
-      assert_equal [], results
-    end
-  else
-    puts '(Test LDAP server not configured)'
-  end
-end
--- a/.svn/pristine/84/84675d4c5913f4d4787034973ce3aa888eb2ae42.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class WikisController < ApplicationController
-  menu_item :settings
-  before_filter :find_project, :authorize
-
-  # Create or update a project's wiki
-  def edit
-    @wiki = @project.wiki || Wiki.new(:project => @project)
-    @wiki.safe_attributes = params[:wiki]
-    @wiki.save if request.post?
-  end
-
-  # Delete a project's wiki
-  def destroy
-    if request.post? && params[:confirm] && @project.wiki
-      @project.wiki.destroy
-      redirect_to settings_project_path(@project, :tab => 'wiki')
-    end
-  end
-end
--- a/.svn/pristine/84/849f87222b3ad4c6513f88d2c270ccbbefd56465.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-module RedmineMenuTestHelper
-  # Assertions
-  def assert_number_of_items_in_menu(menu_name, count)
-    assert Redmine::MenuManager.items(menu_name).size >= count, "Menu has less than #{count} items"
-  end
-
-  def assert_menu_contains_item_named(menu_name, item_name)
-    assert Redmine::MenuManager.items(menu_name).collect(&:name).include?(item_name.to_sym), "Menu did not have an item named #{item_name}"
-  end
-
-  # Helpers
-  def get_menu_item(menu_name, item_name)
-    Redmine::MenuManager.items(menu_name).find {|item| item.name == item_name.to_sym}
-  end
-end
-
-class RedmineTest < ActiveSupport::TestCase
-  include RedmineMenuTestHelper
-
-  def test_top_menu
-    assert_number_of_items_in_menu :top_menu, 5
-    assert_menu_contains_item_named :top_menu, :home
-    assert_menu_contains_item_named :top_menu, :my_page
-    assert_menu_contains_item_named :top_menu, :projects
-    assert_menu_contains_item_named :top_menu, :administration
-    assert_menu_contains_item_named :top_menu, :help
-  end
-
-  def test_account_menu
-    assert_number_of_items_in_menu :account_menu, 4
-    assert_menu_contains_item_named :account_menu, :login
-    assert_menu_contains_item_named :account_menu, :register
-    assert_menu_contains_item_named :account_menu, :my_account
-    assert_menu_contains_item_named :account_menu, :logout
-  end
-
-  def test_application_menu
-    assert_number_of_items_in_menu :application_menu, 0
-  end
-
-  def test_admin_menu
-    assert_number_of_items_in_menu :admin_menu, 0
-  end
-
-  def test_project_menu
-    assert_number_of_items_in_menu :project_menu, 14
-    assert_menu_contains_item_named :project_menu, :overview
-    assert_menu_contains_item_named :project_menu, :activity
-    assert_menu_contains_item_named :project_menu, :roadmap
-    assert_menu_contains_item_named :project_menu, :issues
-    assert_menu_contains_item_named :project_menu, :new_issue
-    assert_menu_contains_item_named :project_menu, :calendar
-    assert_menu_contains_item_named :project_menu, :gantt
-    assert_menu_contains_item_named :project_menu, :news
-    assert_menu_contains_item_named :project_menu, :documents
-    assert_menu_contains_item_named :project_menu, :wiki
-    assert_menu_contains_item_named :project_menu, :boards
-    assert_menu_contains_item_named :project_menu, :files
-    assert_menu_contains_item_named :project_menu, :repository
-    assert_menu_contains_item_named :project_menu, :settings
-  end
-
-  def test_new_issue_should_have_root_as_a_parent
-    new_issue = get_menu_item(:project_menu, :new_issue)
-    assert_equal :root, new_issue.parent.name
-  end
-end
--- a/.svn/pristine/85/8519fb0f08b4338ed0712c0e2af20a32e713969e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,337 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require "digest/md5"
-require "fileutils"
-
-class Attachment < ActiveRecord::Base
-  belongs_to :container, :polymorphic => true
-  belongs_to :author, :class_name => "User", :foreign_key => "author_id"
-
-  validates_presence_of :filename, :author
-  validates_length_of :filename, :maximum => 255
-  validates_length_of :disk_filename, :maximum => 255
-  validates_length_of :description, :maximum => 255
-  validate :validate_max_file_size
-
-  acts_as_event :title => :filename,
-                :url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id, :filename => o.filename}}
-
-  acts_as_activity_provider :type => 'files',
-                            :permission => :view_files,
-                            :author_key => :author_id,
-                            :find_options => {:select => "#{Attachment.table_name}.*",
-                                              :joins => "LEFT JOIN #{Version.table_name} ON #{Attachment.table_name}.container_type='Version' AND #{Version.table_name}.id = #{Attachment.table_name}.container_id " +
-                                                        "LEFT JOIN #{Project.table_name} ON #{Version.table_name}.project_id = #{Project.table_name}.id OR ( #{Attachment.table_name}.container_type='Project' AND #{Attachment.table_name}.container_id = #{Project.table_name}.id )"}
-
-  acts_as_activity_provider :type => 'documents',
-                            :permission => :view_documents,
-                            :author_key => :author_id,
-                            :find_options => {:select => "#{Attachment.table_name}.*",
-                                              :joins => "LEFT JOIN #{Document.table_name} ON #{Attachment.table_name}.container_type='Document' AND #{Document.table_name}.id = #{Attachment.table_name}.container_id " +
-                                                        "LEFT JOIN #{Project.table_name} ON #{Document.table_name}.project_id = #{Project.table_name}.id"}
-
-  cattr_accessor :storage_path
-  @@storage_path = Redmine::Configuration['attachments_storage_path'] || File.join(Rails.root, "files")
-
-  cattr_accessor :thumbnails_storage_path
-  @@thumbnails_storage_path = File.join(Rails.root, "tmp", "thumbnails")
-
-  before_save :files_to_final_location
-  after_destroy :delete_from_disk
-
-  # Returns an unsaved copy of the attachment
-  def copy(attributes=nil)
-    copy = self.class.new
-    copy.attributes = self.attributes.dup.except("id", "downloads")
-    copy.attributes = attributes if attributes
-    copy
-  end
-
-  def validate_max_file_size
-    if @temp_file && self.filesize > Setting.attachment_max_size.to_i.kilobytes
-      errors.add(:base, l(:error_attachment_too_big, :max_size => Setting.attachment_max_size.to_i.kilobytes))
-    end
-  end
-
-  def file=(incoming_file)
-    unless incoming_file.nil?
-      @temp_file = incoming_file
-      if @temp_file.size > 0
-        if @temp_file.respond_to?(:original_filename)
-          self.filename = @temp_file.original_filename
-          self.filename.force_encoding("UTF-8") if filename.respond_to?(:force_encoding)
-        end
-        if @temp_file.respond_to?(:content_type)
-          self.content_type = @temp_file.content_type.to_s.chomp
-        end
-        if content_type.blank? && filename.present?
-          self.content_type = Redmine::MimeType.of(filename)
-        end
-        self.filesize = @temp_file.size
-      end
-    end
-  end
-
-  def file
-    nil
-  end
-
-  def filename=(arg)
-    write_attribute :filename, sanitize_filename(arg.to_s)
-    filename
-  end
-
-  # Copies the temporary file to its final location
-  # and computes its MD5 hash
-  def files_to_final_location
-    if @temp_file && (@temp_file.size > 0)
-      self.disk_directory = target_directory
-      self.disk_filename = Attachment.disk_filename(filename, disk_directory)
-      logger.info("Saving attachment '#{self.diskfile}' (#{@temp_file.size} bytes)") if logger
-      path = File.dirname(diskfile)
-      unless File.directory?(path)
-        FileUtils.mkdir_p(path)
-      end
-      md5 = Digest::MD5.new
-      File.open(diskfile, "wb") do |f|
-        if @temp_file.respond_to?(:read)
-          buffer = ""
-          while (buffer = @temp_file.read(8192))
-            f.write(buffer)
-            md5.update(buffer)
-          end
-        else
-          f.write(@temp_file)
-          md5.update(@temp_file)
-        end
-      end
-      self.digest = md5.hexdigest
-    end
-    @temp_file = nil
-    # Don't save the content type if it's longer than the authorized length
-    if self.content_type && self.content_type.length > 255
-      self.content_type = nil
-    end
-  end
-
-  # Deletes the file from the file system if it's not referenced by other attachments
-  def delete_from_disk
-    if Attachment.where("disk_filename = ? AND id <> ?", disk_filename, id).empty?
-      delete_from_disk!
-    end
-  end
-
-  # Returns file's location on disk
-  def diskfile
-    File.join(self.class.storage_path, disk_directory.to_s, disk_filename.to_s)
-  end
-
-  def title
-    title = filename.to_s
-    if description.present?
-      title << " (#{description})"
-    end
-    title
-  end
-
-  def increment_download
-    increment!(:downloads)
-  end
-
-  def project
-    container.try(:project)
-  end
-
-  def visible?(user=User.current)
-    if container_id
-      container && container.attachments_visible?(user)
-    else
-      author == user
-    end
-  end
-
-  def deletable?(user=User.current)
-    if container_id
-      container && container.attachments_deletable?(user)
-    else
-      author == user
-    end
-  end
-
-  def image?
-    !!(self.filename =~ /\.(bmp|gif|jpg|jpe|jpeg|png)$/i)
-  end
-
-  def thumbnailable?
-    image?
-  end
-
-  # Returns the full path the attachment thumbnail, or nil
-  # if the thumbnail cannot be generated.
-  def thumbnail(options={})
-    if thumbnailable? && readable?
-      size = options[:size].to_i
-      if size > 0
-        # Limit the number of thumbnails per image
-        size = (size / 50) * 50
-        # Maximum thumbnail size
-        size = 800 if size > 800
-      else
-        size = Setting.thumbnails_size.to_i
-      end
-      size = 100 unless size > 0
-      target = File.join(self.class.thumbnails_storage_path, "#{id}_#{digest}_#{size}.thumb")
-
-      begin
-        Redmine::Thumbnail.generate(self.diskfile, target, size)
-      rescue => e
-        logger.error "An error occured while generating thumbnail for #{disk_filename} to #{target}\nException was: #{e.message}" if logger
-        return nil
-      end
-    end
-  end
-
-  # Deletes all thumbnails
-  def self.clear_thumbnails
-    Dir.glob(File.join(thumbnails_storage_path, "*.thumb")).each do |file|
-      File.delete file
-    end
-  end
-
-  def is_text?
-    Redmine::MimeType.is_type?('text', filename)
-  end
-
-  def is_diff?
-    self.filename =~ /\.(patch|diff)$/i
-  end
-
-  # Returns true if the file is readable
-  def readable?
-    File.readable?(diskfile)
-  end
-
-  # Returns the attachment token
-  def token
-    "#{id}.#{digest}"
-  end
-
-  # Finds an attachment that matches the given token and that has no container
-  def self.find_by_token(token)
-    if token.to_s =~ /^(\d+)\.([0-9a-f]+)$/
-      attachment_id, attachment_digest = $1, $2
-      attachment = Attachment.where(:id => attachment_id, :digest => attachment_digest).first
-      if attachment && attachment.container.nil?
-        attachment
-      end
-    end
-  end
-
-  # Bulk attaches a set of files to an object
-  #
-  # Returns a Hash of the results:
-  # :files => array of the attached files
-  # :unsaved => array of the files that could not be attached
-  def self.attach_files(obj, attachments)
-    result = obj.save_attachments(attachments, User.current)
-    obj.attach_saved_attachments
-    result
-  end
-
-  def self.latest_attach(attachments, filename)
-    attachments.sort_by(&:created_on).reverse.detect {
-      |att| att.filename.downcase == filename.downcase
-     }
-  end
-
-  def self.prune(age=1.day)
-    Attachment.where("created_on < ? AND (container_type IS NULL OR container_type = '')", Time.now - age).destroy_all
-  end
-
-  # Moves an existing attachment to its target directory
-  def move_to_target_directory!
-    return unless !new_record? & readable?
-
-    src = diskfile
-    self.disk_directory = target_directory
-    dest = diskfile
-
-    return if src == dest
-
-    if !FileUtils.mkdir_p(File.dirname(dest))
-      logger.error "Could not create directory #{File.dirname(dest)}" if logger
-      return
-    end
-
-    if !FileUtils.mv(src, dest)
-      logger.error "Could not move attachment from #{src} to #{dest}" if logger
-      return
-    end
-
-    update_column :disk_directory, disk_directory
-  end
-
-  # Moves existing attachments that are stored at the root of the files
-  # directory (ie. created before Redmine 2.3) to their target subdirectories
-  def self.move_from_root_to_target_directory
-    Attachment.where("disk_directory IS NULL OR disk_directory = ''").find_each do |attachment|
-      attachment.move_to_target_directory!
-    end
-  end
-
-  private
-
-  # Physically deletes the file from the file system
-  def delete_from_disk!
-    if disk_filename.present? && File.exist?(diskfile)
-      File.delete(diskfile)
-    end
-  end
-
-  def sanitize_filename(value)
-    # get only the filename, not the whole path
-    just_filename = value.gsub(/\A.*(\\|\/)/m, '')
-
-    # Finally, replace invalid characters with underscore
-    @filename = just_filename.gsub(/[\/\?\%\*\:\|\"\'<>\n\r]+/, '_')
-  end
-
-  # Returns the subdirectory in which the attachment will be saved
-  def target_directory
-    time = created_on || DateTime.now
-    time.strftime("%Y/%m")
-  end
-
-  # Returns an ASCII or hashed filename that do not
-  # exists yet in the given subdirectory
-  def self.disk_filename(filename, directory=nil)
-    timestamp = DateTime.now.strftime("%y%m%d%H%M%S")
-    ascii = ''
-    if filename =~ %r{^[a-zA-Z0-9_\.\-]*$}
-      ascii = filename
-    else
-      ascii = Digest::MD5.hexdigest(filename)
-      # keep the extension if any
-      ascii << $1 if filename =~ %r{(\.[a-zA-Z0-9]+)$}
-    end
-    while File.exist?(File.join(storage_path, directory.to_s, "#{timestamp}_#{ascii}"))
-      timestamp.succ!
-    end
-    "#{timestamp}_#{ascii}"
-  end
-end
--- a/.svn/pristine/85/854825bbe47c50aa884c3809103ed51a05bc7f14.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Version < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  after_update :update_issues_from_sharing_change
-  belongs_to :project
-  has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify
-  acts_as_customizable
-  acts_as_attachable :view_permission => :view_files,
-                     :delete_permission => :manage_files
-
-  VERSION_STATUSES = %w(open locked closed)
-  VERSION_SHARINGS = %w(none descendants hierarchy tree system)
-
-  validates_presence_of :name
-  validates_uniqueness_of :name, :scope => [:project_id]
-  validates_length_of :name, :maximum => 60
-  validates :effective_date, :date => true
-  validates_inclusion_of :status, :in => VERSION_STATUSES
-  validates_inclusion_of :sharing, :in => VERSION_SHARINGS
-
-  scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
-  scope :open, lambda { where(:status => 'open') }
-  scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.first || User.current, :view_issues))
-  }
-
-  safe_attributes 'name',
-    'description',
-    'effective_date',
-    'due_date',
-    'wiki_page_title',
-    'status',
-    'sharing',
-    'custom_field_values',
-    'custom_fields'
-
-  # Returns true if +user+ or current user is allowed to view the version
-  def visible?(user=User.current)
-    user.allowed_to?(:view_issues, self.project)
-  end
-
-  # Version files have same visibility as project files
-  def attachments_visible?(*args)
-    project.present? && project.attachments_visible?(*args)
-  end
-
-  def start_date
-    @start_date ||= fixed_issues.minimum('start_date')
-  end
-
-  def due_date
-    effective_date
-  end
-
-  def due_date=(arg)
-    self.effective_date=(arg)
-  end
-
-  # Returns the total estimated time for this version
-  # (sum of leaves estimated_hours)
-  def estimated_hours
-    @estimated_hours ||= fixed_issues.leaves.sum(:estimated_hours).to_f
-  end
-
-  # Returns the total reported time for this version
-  def spent_hours
-    @spent_hours ||= TimeEntry.joins(:issue).where("#{Issue.table_name}.fixed_version_id = ?", id).sum(:hours).to_f
-  end
-
-  def closed?
-    status == 'closed'
-  end
-
-  def open?
-    status == 'open'
-  end
-
-  # Returns true if the version is completed: due date reached and no open issues
-  def completed?
-    effective_date && (effective_date < Date.today) && (open_issues_count == 0)
-  end
-
-  def behind_schedule?
-    if completed_percent == 100
-      return false
-    elsif due_date && start_date
-      done_date = start_date + ((due_date - start_date+1)* completed_percent/100).floor
-      return done_date <= Date.today
-    else
-      false # No issues so it's not late
-    end
-  end
-
-  # Returns the completion percentage of this version based on the amount of open/closed issues
-  # and the time spent on the open issues.
-  def completed_percent
-    if issues_count == 0
-      0
-    elsif open_issues_count == 0
-      100
-    else
-      issues_progress(false) + issues_progress(true)
-    end
-  end
-
-  # TODO: remove in Redmine 3.0
-  def completed_pourcent
-    ActiveSupport::Deprecation.warn "Version#completed_pourcent is deprecated and will be removed in Redmine 3.0. Please use #completed_percent instead."
-    completed_percent
-  end
-
-  # Returns the percentage of issues that have been marked as 'closed'.
-  def closed_percent
-    if issues_count == 0
-      0
-    else
-      issues_progress(false)
-    end
-  end
-
-  # TODO: remove in Redmine 3.0
-  def closed_pourcent
-    ActiveSupport::Deprecation.warn "Version#closed_pourcent is deprecated and will be removed in Redmine 3.0. Please use #closed_percent instead."
-    closed_percent
-  end
-
-  # Returns true if the version is overdue: due date reached and some open issues
-  def overdue?
-    effective_date && (effective_date < Date.today) && (open_issues_count > 0)
-  end
-
-  # Returns assigned issues count
-  def issues_count
-    load_issue_counts
-    @issue_count
-  end
-
-  # Returns the total amount of open issues for this version.
-  def open_issues_count
-    load_issue_counts
-    @open_issues_count
-  end
-
-  # Returns the total amount of closed issues for this version.
-  def closed_issues_count
-    load_issue_counts
-    @closed_issues_count
-  end
-
-  def wiki_page
-    if project.wiki && !wiki_page_title.blank?
-      @wiki_page ||= project.wiki.find_page(wiki_page_title)
-    end
-    @wiki_page
-  end
-
-  def to_s; name end
-
-  def to_s_with_project
-    "#{project} - #{name}"
-  end
-
-  # Versions are sorted by effective_date and name
-  # Those with no effective_date are at the end, sorted by name
-  def <=>(version)
-    if self.effective_date
-      if version.effective_date
-        if self.effective_date == version.effective_date
-          name == version.name ? id <=> version.id : name <=> version.name
-        else
-          self.effective_date <=> version.effective_date
-        end
-      else
-        -1
-      end
-    else
-      if version.effective_date
-        1
-      else
-        name == version.name ? id <=> version.id : name <=> version.name
-      end
-    end
-  end
-
-  def self.fields_for_order_statement(table=nil)
-    table ||= table_name
-    ["(CASE WHEN #{table}.effective_date IS NULL THEN 1 ELSE 0 END)", "#{table}.effective_date", "#{table}.name", "#{table}.id"]
-  end
-
-  scope :sorted, order(fields_for_order_statement)
-
-  # Returns the sharings that +user+ can set the version to
-  def allowed_sharings(user = User.current)
-    VERSION_SHARINGS.select do |s|
-      if sharing == s
-        true
-      else
-        case s
-        when 'system'
-          # Only admin users can set a systemwide sharing
-          user.admin?
-        when 'hierarchy', 'tree'
-          # Only users allowed to manage versions of the root project can
-          # set sharing to hierarchy or tree
-          project.nil? || user.allowed_to?(:manage_versions, project.root)
-        else
-          true
-        end
-      end
-    end
-  end
-
-  private
-
-  def load_issue_counts
-    unless @issue_count
-      @open_issues_count = 0
-      @closed_issues_count = 0
-      fixed_issues.count(:all, :group => :status).each do |status, count|
-        if status.is_closed?
-          @closed_issues_count += count
-        else
-          @open_issues_count += count
-        end
-      end
-      @issue_count = @open_issues_count + @closed_issues_count
-    end
-  end
-
-  # Update the issue's fixed versions. Used if a version's sharing changes.
-  def update_issues_from_sharing_change
-    if sharing_changed?
-      if VERSION_SHARINGS.index(sharing_was).nil? ||
-          VERSION_SHARINGS.index(sharing).nil? ||
-          VERSION_SHARINGS.index(sharing_was) > VERSION_SHARINGS.index(sharing)
-        Issue.update_versions_from_sharing_change self
-      end
-    end
-  end
-
-  # Returns the average estimated time of assigned issues
-  # or 1 if no issue has an estimated time
-  # Used to weigth unestimated issues in progress calculation
-  def estimated_average
-    if @estimated_average.nil?
-      average = fixed_issues.average(:estimated_hours).to_f
-      if average == 0
-        average = 1
-      end
-      @estimated_average = average
-    end
-    @estimated_average
-  end
-
-  # Returns the total progress of open or closed issues.  The returned percentage takes into account
-  # the amount of estimated time set for this version.
-  #
-  # Examples:
-  # issues_progress(true)   => returns the progress percentage for open issues.
-  # issues_progress(false)  => returns the progress percentage for closed issues.
-  def issues_progress(open)
-    @issues_progress ||= {}
-    @issues_progress[open] ||= begin
-      progress = 0
-      if issues_count > 0
-        ratio = open ? 'done_ratio' : 100
-
-        done = fixed_issues.open(open).sum("COALESCE(estimated_hours, #{estimated_average}) * #{ratio}").to_f
-        progress = done / (estimated_average * issues_count)
-      end
-      progress
-    end
-  end
-end
--- a/.svn/pristine/85/856339cef1bdf5f11b116c77c2ac5a76171899ce.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesDarcsControllerTest < ActionController::TestCase
-  tests RepositoriesController
-
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :repositories, :enabled_modules
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s
-  PRJ_ID = 3
-  NUM_REV = 6
-
-  def setup
-    User.current = nil
-    @project = Project.find(PRJ_ID)
-    @repository = Repository::Darcs.create(
-                        :project      => @project,
-                        :url          => REPOSITORY_PATH,
-                        :log_encoding => 'UTF-8'
-                        )
-    assert @repository
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    def test_get_new
-      @request.session[:user_id] = 1
-      @project.repository.destroy
-      get :new, :project_id => 'subproject1', :repository_scm => 'Darcs'
-      assert_response :success
-      assert_template 'new'
-      assert_kind_of Repository::Darcs, assigns(:repository)
-      assert assigns(:repository).new_record?
-    end
-
-    def test_browse_root
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal 3, assigns(:entries).size
-      assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
-    end
-
-    def test_browse_directory
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
-      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
-      assert_not_nil entry
-      assert_equal 'file', entry.kind
-      assert_equal 'images/edit.png', entry.path
-    end
-
-    def test_browse_at_given_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
-          :rev => 1
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['delete.png'], assigns(:entries).collect(&:name)
-    end
-
-    def test_changes
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :changes, :id => PRJ_ID,
-          :path => repository_path_hash(['images', 'edit.png'])[:param]
-      assert_response :success
-      assert_template 'changes'
-      assert_tag :tag => 'h2', :content => 'edit.png'
-    end
-
-    def test_diff
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      # Full diff of changeset 5
-      ['inline', 'sbs'].each do |dt|
-        get :diff, :id => PRJ_ID, :rev => 5, :type => dt
-        assert_response :success
-        assert_template 'diff'
-        # Line 22 removed
-        assert_tag :tag => 'th',
-                   :content => '22',
-                   :sibling => { :tag => 'td',
-                                 :attributes => { :class => /diff_out/ },
-                                 :content => /def remove/ }
-      end
-    end
-
-    def test_destroy_valid_repository
-      @request.session[:user_id] = 1 # admin
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-
-    def test_destroy_invalid_repository
-      @request.session[:user_id] = 1 # admin
-      @project.repository.destroy
-      @repository = Repository::Darcs.create!(
-                        :project      => @project,
-                        :url          => "/invalid",
-                        :log_encoding => 'UTF-8'
-                        )
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal 0, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-  else
-    puts "Darcs test repository NOT FOUND. Skipping functional tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/86/860e2f012a8a16391f9ed2054fc730df3d67d9c9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module AdminHelper
-  def project_status_options_for_select(selected)
-    options_for_select([[l(:label_all), ''],
-                        [l(:project_status_active), '1'],
-                        [l(:project_status_closed), '5'],
-                        [l(:project_status_archived), '9']], selected.to_s)
-  end
-end
--- a/.svn/pristine/86/86143f66fe1f5d10a7a618e2496577aaa346c237.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingProjectEnumerationsTest < ActionController::IntegrationTest
-  def test_project_enumerations
-    assert_routing(
-        { :method => 'put', :path => "/projects/64/enumerations" },
-        { :controller => 'project_enumerations', :action => 'update',
-          :project_id => '64' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/projects/64/enumerations" },
-        { :controller => 'project_enumerations', :action => 'destroy',
-          :project_id => '64' }
-      )
-  end
-end
--- a/.svn/pristine/86/862a776ed4eda62592dadbb92180115063e923b2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::CodesetUtilTest < ActiveSupport::TestCase
-
-  def test_to_utf8_by_setting_from_latin1
-    with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-      s1 = "Texte encod\xc3\xa9"
-      s2 = "Texte encod\xe9"
-      s3 = s2.dup
-      if s1.respond_to?(:force_encoding)
-        s1.force_encoding("UTF-8")
-        s2.force_encoding("ASCII-8BIT")
-        s3.force_encoding("UTF-8")
-      end
-      assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2)
-      assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3)
-    end
-  end
-
-  def test_to_utf8_by_setting_from_euc_jp
-    with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
-      s1 = "\xe3\x83\xac\xe3\x83\x83\xe3\x83\x89\xe3\x83\x9e\xe3\x82\xa4\xe3\x83\xb3"
-      s2 = "\xa5\xec\xa5\xc3\xa5\xc9\xa5\xde\xa5\xa4\xa5\xf3"
-      s3 = s2.dup
-      if s1.respond_to?(:force_encoding)
-        s1.force_encoding("UTF-8")
-        s2.force_encoding("ASCII-8BIT")
-        s3.force_encoding("UTF-8")
-      end
-      assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2)
-      assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3)
-    end
-  end
-
-  def test_to_utf8_by_setting_should_be_converted_all_latin1
-    with_settings :repositories_encodings => 'ISO-8859-1' do
-      s1 = "\xc3\x82\xc2\x80"
-      s2 = "\xC2\x80"
-      s3 = s2.dup
-      if s1.respond_to?(:force_encoding)
-        s1.force_encoding("UTF-8")
-        s2.force_encoding("ASCII-8BIT")
-        s3.force_encoding("UTF-8")
-      end
-      assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2)
-      assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3)
-    end
-  end
-
-  def test_to_utf8_by_setting_blank_string
-    assert_equal "",  Redmine::CodesetUtil.to_utf8_by_setting("")
-    assert_equal nil, Redmine::CodesetUtil.to_utf8_by_setting(nil)
-  end
-
-  def test_to_utf8_by_setting_returns_ascii_as_utf8
-    s1 = "ASCII"
-    s2 = s1.dup
-    if s1.respond_to?(:force_encoding)
-      s1.force_encoding("UTF-8")
-      s2.force_encoding("ISO-8859-1")
-    end
-    str1 = Redmine::CodesetUtil.to_utf8_by_setting(s1)
-    str2 = Redmine::CodesetUtil.to_utf8_by_setting(s2)
-    assert_equal s1, str1
-    assert_equal s1, str2
-    if s1.respond_to?(:force_encoding)
-      assert_equal "UTF-8", str1.encoding.to_s
-      assert_equal "UTF-8", str2.encoding.to_s
-    end
-  end
-
-  def test_to_utf8_by_setting_invalid_utf8_sequences_should_be_stripped
-    with_settings :repositories_encodings => '' do
-      # s1 = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
-      s1 = "Texte encod\xe9 en ISO-8859-1."
-      s1.force_encoding("ASCII-8BIT") if s1.respond_to?(:force_encoding)
-      str = Redmine::CodesetUtil.to_utf8_by_setting(s1)
-      if str.respond_to?(:force_encoding)
-        assert str.valid_encoding?
-        assert_equal "UTF-8", str.encoding.to_s
-      end
-      assert_equal "Texte encod? en ISO-8859-1.", str
-    end
-  end
-
-  def test_to_utf8_by_setting_invalid_utf8_sequences_should_be_stripped_ja_jis
-    with_settings :repositories_encodings => 'ISO-2022-JP' do
-      s1 = "test\xb5\xfetest\xb5\xfe"
-      s1.force_encoding("ASCII-8BIT") if s1.respond_to?(:force_encoding)
-      str = Redmine::CodesetUtil.to_utf8_by_setting(s1)
-      if str.respond_to?(:force_encoding)
-        assert str.valid_encoding?
-        assert_equal "UTF-8", str.encoding.to_s
-      end
-      assert_equal "test??test??", str
-    end
-  end
-end
--- a/.svn/pristine/86/868f0e4e1e397d79702a7dad295d76e1aae77f8f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1406 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class QueryTest < ActiveSupport::TestCase
-  include Redmine::I18n
-
-  fixtures :projects, :enabled_modules, :users, :members,
-           :member_roles, :roles, :trackers, :issue_statuses,
-           :issue_categories, :enumerations, :issues,
-           :watchers, :custom_fields, :custom_values, :versions,
-           :queries,
-           :projects_trackers,
-           :custom_fields_trackers
-
-  def test_query_with_roles_visibility_should_validate_roles
-    set_language_if_valid 'en'
-    query = IssueQuery.new(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES)
-    assert !query.save
-    assert_include "Roles can't be blank", query.errors.full_messages
-    query.role_ids = [1, 2]
-    assert query.save
-  end
-
-  def test_changing_roles_visibility_should_clear_roles
-    query = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES, :role_ids => [1, 2])
-    assert_equal 2, query.roles.count
-
-    query.visibility = IssueQuery::VISIBILITY_PUBLIC
-    query.save!
-    assert_equal 0, query.roles.count
-  end
-
-  def test_available_filters_should_be_ordered
-    set_language_if_valid 'en'
-    query = IssueQuery.new
-    assert_equal 0, query.available_filters.keys.index('status_id')
-    expected_order = [
-      "Status",
-      "Project",
-      "Tracker",
-      "Priority"
-    ]
-    assert_equal expected_order,
-                 (query.available_filters.values.map{|v| v[:name]} & expected_order)
-  end
-
-  def test_available_filters_with_custom_fields_should_be_ordered
-    set_language_if_valid 'en'
-    UserCustomField.create!(
-              :name => 'order test', :field_format => 'string',
-              :is_for_all => true, :is_filter => true
-            )
-    query = IssueQuery.new
-    expected_order = [
-      "Searchable field",
-      "Database",
-      "Project's Development status",
-      "Author's order test",
-      "Assignee's order test"
-    ]
-    assert_equal expected_order,
-                 (query.available_filters.values.map{|v| v[:name]} & expected_order)
-  end
-
-  def test_custom_fields_for_all_projects_should_be_available_in_global_queries
-    query = IssueQuery.new(:project => nil, :name => '_')
-    assert query.available_filters.has_key?('cf_1')
-    assert !query.available_filters.has_key?('cf_3')
-  end
-
-  def test_system_shared_versions_should_be_available_in_global_queries
-    Version.find(2).update_attribute :sharing, 'system'
-    query = IssueQuery.new(:project => nil, :name => '_')
-    assert query.available_filters.has_key?('fixed_version_id')
-    assert query.available_filters['fixed_version_id'][:values].detect {|v| v.last == '2'}
-  end
-
-  def test_project_filter_in_global_queries
-    query = IssueQuery.new(:project => nil, :name => '_')
-    project_filter = query.available_filters["project_id"]
-    assert_not_nil project_filter
-    project_ids = project_filter[:values].map{|p| p[1]}
-    assert project_ids.include?("1")  #public project
-    assert !project_ids.include?("2") #private project user cannot see
-  end
-
-  def find_issues_with_query(query)
-    Issue.includes([:assigned_to, :status, :tracker, :project, :priority]).where(
-         query.statement
-       ).all
-  end
-
-  def assert_find_issues_with_query_is_successful(query)
-    assert_nothing_raised do
-      find_issues_with_query(query)
-    end
-  end
-
-  def assert_query_statement_includes(query, condition)
-    assert_include condition, query.statement
-  end
-
-  def assert_query_result(expected, query)
-    assert_nothing_raised do
-      assert_equal expected.map(&:id).sort, query.issues.map(&:id).sort
-      assert_equal expected.size, query.issue_count
-    end
-  end
-
-  def test_query_should_allow_shared_versions_for_a_project_query
-    subproject_version = Version.find(4)
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('fixed_version_id', '=', [subproject_version.id.to_s])
-
-    assert query.statement.include?("#{Issue.table_name}.fixed_version_id IN ('4')")
-  end
-
-  def test_query_with_multiple_custom_fields
-    query = IssueQuery.find(1)
-    assert query.valid?
-    assert query.statement.include?("#{CustomValue.table_name}.value IN ('MySQL')")
-    issues = find_issues_with_query(query)
-    assert_equal 1, issues.length
-    assert_equal Issue.find(3), issues.first
-  end
-
-  def test_operator_none
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('fixed_version_id', '!*', [''])
-    query.add_filter('cf_1', '!*', [''])
-    assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL")
-    assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''")
-    find_issues_with_query(query)
-  end
-
-  def test_operator_none_for_integer
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('estimated_hours', '!*', [''])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    assert issues.all? {|i| !i.estimated_hours}
-  end
-
-  def test_operator_none_for_date
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('start_date', '!*', [''])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    assert issues.all? {|i| i.start_date.nil?}
-  end
-
-  def test_operator_none_for_string_custom_field
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('cf_2', '!*', [''])
-    assert query.has_filter?('cf_2')
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    assert issues.all? {|i| i.custom_field_value(2).blank?}
-  end
-
-  def test_operator_all
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('fixed_version_id', '*', [''])
-    query.add_filter('cf_1', '*', [''])
-    assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL")
-    assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''")
-    find_issues_with_query(query)
-  end
-
-  def test_operator_all_for_date
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('start_date', '*', [''])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    assert issues.all? {|i| i.start_date.present?}
-  end
-
-  def test_operator_all_for_string_custom_field
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('cf_2', '*', [''])
-    assert query.has_filter?('cf_2')
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    assert issues.all? {|i| i.custom_field_value(2).present?}
-  end
-
-  def test_numeric_filter_should_not_accept_non_numeric_values
-    query = IssueQuery.new(:name => '_')
-    query.add_filter('estimated_hours', '=', ['a'])
-
-    assert query.has_filter?('estimated_hours')
-    assert !query.valid?
-  end
-
-  def test_operator_is_on_float
-    Issue.update_all("estimated_hours = 171.2", "id=2")
-
-    query = IssueQuery.new(:name => '_')
-    query.add_filter('estimated_hours', '=', ['171.20'])
-    issues = find_issues_with_query(query)
-    assert_equal 1, issues.size
-    assert_equal 2, issues.first.id
-  end
-
-  def test_operator_is_on_integer_custom_field
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
-
-    query = IssueQuery.new(:name => '_')
-    query.add_filter("cf_#{f.id}", '=', ['12'])
-    issues = find_issues_with_query(query)
-    assert_equal 1, issues.size
-    assert_equal 2, issues.first.id
-  end
-
-  def test_operator_is_on_integer_custom_field_should_accept_negative_value
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
-
-    query = IssueQuery.new(:name => '_')
-    query.add_filter("cf_#{f.id}", '=', ['-12'])
-    assert query.valid?
-    issues = find_issues_with_query(query)
-    assert_equal 1, issues.size
-    assert_equal 2, issues.first.id
-  end
-
-  def test_operator_is_on_float_custom_field
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12.7')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
-
-    query = IssueQuery.new(:name => '_')
-    query.add_filter("cf_#{f.id}", '=', ['12.7'])
-    issues = find_issues_with_query(query)
-    assert_equal 1, issues.size
-    assert_equal 2, issues.first.id
-  end
-
-  def test_operator_is_on_float_custom_field_should_accept_negative_value
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'float', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7.3')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '-12.7')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
-
-    query = IssueQuery.new(:name => '_')
-    query.add_filter("cf_#{f.id}", '=', ['-12.7'])
-    assert query.valid?
-    issues = find_issues_with_query(query)
-    assert_equal 1, issues.size
-    assert_equal 2, issues.first.id
-  end
-
-  def test_operator_is_on_multi_list_custom_field
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
-      :possible_values => ['value1', 'value2', 'value3'], :multiple => true, :trackers => Tracker.all)
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
-
-    query = IssueQuery.new(:name => '_')
-    query.add_filter("cf_#{f.id}", '=', ['value1'])
-    issues = find_issues_with_query(query)
-    assert_equal [1, 3], issues.map(&:id).sort
-
-    query = IssueQuery.new(:name => '_')
-    query.add_filter("cf_#{f.id}", '=', ['value2'])
-    issues = find_issues_with_query(query)
-    assert_equal [1], issues.map(&:id).sort
-  end
-
-  def test_operator_is_not_on_multi_list_custom_field
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
-      :possible_values => ['value1', 'value2', 'value3'], :multiple => true, :trackers => Tracker.all)
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value1')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => 'value2')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => 'value1')
-
-    query = IssueQuery.new(:name => '_')
-    query.add_filter("cf_#{f.id}", '!', ['value1'])
-    issues = find_issues_with_query(query)
-    assert !issues.map(&:id).include?(1)
-    assert !issues.map(&:id).include?(3)
-
-    query = IssueQuery.new(:name => '_')
-    query.add_filter("cf_#{f.id}", '!', ['value2'])
-    issues = find_issues_with_query(query)
-    assert !issues.map(&:id).include?(1)
-    assert issues.map(&:id).include?(3)
-  end
-
-  def test_operator_is_on_is_private_field
-    # is_private filter only available for those who can set issues private
-    User.current = User.find(2)
-
-    query = IssueQuery.new(:name => '_')
-    assert query.available_filters.key?('is_private')
-
-    query.add_filter("is_private", '=', ['1'])
-    issues = find_issues_with_query(query)
-    assert issues.any?
-    assert_nil issues.detect {|issue| !issue.is_private?}
-  ensure
-    User.current = nil
-  end
-
-  def test_operator_is_not_on_is_private_field
-    # is_private filter only available for those who can set issues private
-    User.current = User.find(2)
-
-    query = IssueQuery.new(:name => '_')
-    assert query.available_filters.key?('is_private')
-
-    query.add_filter("is_private", '!', ['1'])
-    issues = find_issues_with_query(query)
-    assert issues.any?
-    assert_nil issues.detect {|issue| issue.is_private?}
-  ensure
-    User.current = nil
-  end
-
-  def test_operator_greater_than
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('done_ratio', '>=', ['40'])
-    assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40.0")
-    find_issues_with_query(query)
-  end
-
-  def test_operator_greater_than_a_float
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('estimated_hours', '>=', ['40.5'])
-    assert query.statement.include?("#{Issue.table_name}.estimated_hours >= 40.5")
-    find_issues_with_query(query)
-  end
-
-  def test_operator_greater_than_on_int_custom_field
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '12')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
-
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter("cf_#{f.id}", '>=', ['8'])
-    issues = find_issues_with_query(query)
-    assert_equal 1, issues.size
-    assert_equal 2, issues.first.id
-  end
-
-  def test_operator_lesser_than
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('done_ratio', '<=', ['30'])
-    assert query.statement.include?("#{Issue.table_name}.done_ratio <= 30.0")
-    find_issues_with_query(query)
-  end
-
-  def test_operator_lesser_than_on_custom_field
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter("cf_#{f.id}", '<=', ['30'])
-    assert_match /CAST.+ <= 30\.0/, query.statement
-    find_issues_with_query(query)
-  end
-
-  def test_operator_lesser_than_on_date_custom_field
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'date', :is_filter => true, :is_for_all => true, :trackers => Tracker.all)
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '2013-04-11')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '2013-05-14')
-    CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
-
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter("cf_#{f.id}", '<=', ['2013-05-01'])
-    issue_ids = find_issues_with_query(query).map(&:id)
-    assert_include 1, issue_ids
-    assert_not_include 2, issue_ids
-    assert_not_include 3, issue_ids
-  end
-
-  def test_operator_between
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('done_ratio', '><', ['30', '40'])
-    assert_include "#{Issue.table_name}.done_ratio BETWEEN 30.0 AND 40.0", query.statement
-    find_issues_with_query(query)
-  end
-
-  def test_operator_between_on_custom_field
-    f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter("cf_#{f.id}", '><', ['30', '40'])
-    assert_match /CAST.+ BETWEEN 30.0 AND 40.0/, query.statement
-    find_issues_with_query(query)
-  end
-
-  def test_date_filter_should_not_accept_non_date_values
-    query = IssueQuery.new(:name => '_')
-    query.add_filter('created_on', '=', ['a'])
-
-    assert query.has_filter?('created_on')
-    assert !query.valid?
-  end
-
-  def test_date_filter_should_not_accept_invalid_date_values
-    query = IssueQuery.new(:name => '_')
-    query.add_filter('created_on', '=', ['2011-01-34'])
-
-    assert query.has_filter?('created_on')
-    assert !query.valid?
-  end
-
-  def test_relative_date_filter_should_not_accept_non_integer_values
-    query = IssueQuery.new(:name => '_')
-    query.add_filter('created_on', '>t-', ['a'])
-
-    assert query.has_filter?('created_on')
-    assert !query.valid?
-  end
-
-  def test_operator_date_equals
-    query = IssueQuery.new(:name => '_')
-    query.add_filter('due_date', '=', ['2011-07-10'])
-    assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?' AND issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement
-    find_issues_with_query(query)
-  end
-
-  def test_operator_date_lesser_than
-    query = IssueQuery.new(:name => '_')
-    query.add_filter('due_date', '<=', ['2011-07-10'])
-    assert_match /issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement
-    find_issues_with_query(query)
-  end
-
-  def test_operator_date_greater_than
-    query = IssueQuery.new(:name => '_')
-    query.add_filter('due_date', '>=', ['2011-07-10'])
-    assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?'/, query.statement
-    find_issues_with_query(query)
-  end
-
-  def test_operator_date_between
-    query = IssueQuery.new(:name => '_')
-    query.add_filter('due_date', '><', ['2011-06-23', '2011-07-10'])
-    assert_match /issues\.due_date > '2011-06-22 23:59:59(\.9+)?' AND issues\.due_date <= '2011-07-10 23:59:59(\.9+)?'/, query.statement
-    find_issues_with_query(query)
-  end
-
-  def test_operator_in_more_than
-    Issue.find(7).update_attribute(:due_date, (Date.today + 15))
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', '>t+', ['15'])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    issues.each {|issue| assert(issue.due_date >= (Date.today + 15))}
-  end
-
-  def test_operator_in_less_than
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', '<t+', ['15'])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    issues.each {|issue| assert(issue.due_date <= (Date.today + 15))}
-  end
-
-  def test_operator_in_the_next_days
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', '><t+', ['15'])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))}
-  end
-
-  def test_operator_less_than_ago
-    Issue.find(7).update_attribute(:due_date, (Date.today - 3))
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', '>t-', ['3'])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    issues.each {|issue| assert(issue.due_date >= (Date.today - 3))}
-  end
-
-  def test_operator_in_the_past_days
-    Issue.find(7).update_attribute(:due_date, (Date.today - 3))
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', '><t-', ['3'])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)}
-  end
-
-  def test_operator_more_than_ago
-    Issue.find(7).update_attribute(:due_date, (Date.today - 10))
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', '<t-', ['10'])
-    assert query.statement.include?("#{Issue.table_name}.due_date <=")
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    issues.each {|issue| assert(issue.due_date <= (Date.today - 10))}
-  end
-
-  def test_operator_in
-    Issue.find(7).update_attribute(:due_date, (Date.today + 2))
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', 't+', ['2'])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)}
-  end
-
-  def test_operator_ago
-    Issue.find(7).update_attribute(:due_date, (Date.today - 3))
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', 't-', ['3'])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)}
-  end
-
-  def test_operator_today
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', 't', [''])
-    issues = find_issues_with_query(query)
-    assert !issues.empty?
-    issues.each {|issue| assert_equal Date.today, issue.due_date}
-  end
-
-  def test_operator_this_week_on_date
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', 'w', [''])
-    find_issues_with_query(query)
-  end
-
-  def test_operator_this_week_on_datetime
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('created_on', 'w', [''])
-    find_issues_with_query(query)
-  end
-
-  def test_operator_contains
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('subject', '~', ['uNable'])
-    assert query.statement.include?("LOWER(#{Issue.table_name}.subject) LIKE '%unable%'")
-    result = find_issues_with_query(query)
-    assert result.empty?
-    result.each {|issue| assert issue.subject.downcase.include?('unable') }
-  end
-
-  def test_range_for_this_week_with_week_starting_on_monday
-    I18n.locale = :fr
-    assert_equal '1', I18n.t(:general_first_day_of_week)
-
-    Date.stubs(:today).returns(Date.parse('2011-04-29'))
-
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', 'w', [''])
-    assert query.statement.match(/issues\.due_date > '2011-04-24 23:59:59(\.9+)?' AND issues\.due_date <= '2011-05-01 23:59:59(\.9+)?/), "range not found in #{query.statement}"
-    I18n.locale = :en
-  end
-
-  def test_range_for_this_week_with_week_starting_on_sunday
-    I18n.locale = :en
-    assert_equal '7', I18n.t(:general_first_day_of_week)
-
-    Date.stubs(:today).returns(Date.parse('2011-04-29'))
-
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('due_date', 'w', [''])
-    assert query.statement.match(/issues\.due_date > '2011-04-23 23:59:59(\.9+)?' AND issues\.due_date <= '2011-04-30 23:59:59(\.9+)?/), "range not found in #{query.statement}"
-  end
-
-  def test_operator_does_not_contains
-    query = IssueQuery.new(:project => Project.find(1), :name => '_')
-    query.add_filter('subject', '!~', ['uNable'])
-    assert query.statement.include?("LOWER(#{Issue.table_name}.subject) NOT LIKE '%unable%'")
-    find_issues_with_query(query)
-  end
-
-  def test_filter_assigned_to_me
-    user = User.find(2)
-    group = Group.find(10)
-    User.current = user
-    i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
-    i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
-    i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => Group.find(11))
-    group.users << user
-
-    query = IssueQuery.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
-    result = query.issues
-    assert_equal Issue.visible.where(:assigned_to_id => ([2] + user.reload.group_ids)).sort_by(&:id), result.sort_by(&:id)
-
-    assert result.include?(i1)
-    assert result.include?(i2)
-    assert !result.include?(i3)
-  end
-
-  def test_user_custom_field_filtered_on_me
-    User.current = User.find(2)
-    cf = IssueCustomField.create!(:field_format => 'user', :is_for_all => true, :is_filter => true, :name => 'User custom field', :tracker_ids => [1])
-    issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '2'}, :subject => 'Test', :author_id => 1)
-    issue2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {cf.id.to_s => '3'})
-
-    query = IssueQuery.new(:name => '_', :project => Project.find(1))
-    filter = query.available_filters["cf_#{cf.id}"]
-    assert_not_nil filter
-    assert_include 'me', filter[:values].map{|v| v[1]}
-
-    query.filters = { "cf_#{cf.id}" => {:operator => '=', :values => ['me']}}
-    result = query.issues
-    assert_equal 1, result.size
-    assert_equal issue1, result.first
-  end
-
-  def test_filter_my_projects
-    User.current = User.find(2)
-    query = IssueQuery.new(:name => '_')
-    filter = query.available_filters['project_id']
-    assert_not_nil filter
-    assert_include 'mine', filter[:values].map{|v| v[1]}
-
-    query.filters = { 'project_id' => {:operator => '=', :values => ['mine']}}
-    result = query.issues
-    assert_nil result.detect {|issue| !User.current.member_of?(issue.project)}
-  end
-
-  def test_filter_watched_issues
-    User.current = User.find(1)
-    query = IssueQuery.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}})
-    result = find_issues_with_query(query)
-    assert_not_nil result
-    assert !result.empty?
-    assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
-    User.current = nil
-  end
-
-  def test_filter_unwatched_issues
-    User.current = User.find(1)
-    query = IssueQuery.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}})
-    result = find_issues_with_query(query)
-    assert_not_nil result
-    assert !result.empty?
-    assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size)
-    User.current = nil
-  end
-
-  def test_filter_on_custom_field_should_ignore_projects_with_field_disabled
-    field = IssueCustomField.generate!(:trackers => Tracker.all, :project_ids => [1, 3, 4], :is_filter => true)
-    Issue.generate!(:project_id => 3, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
-    Issue.generate!(:project_id => 4, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
-
-    query = IssueQuery.new(:name => '_', :project => Project.find(1))
-    query.filters = {"cf_#{field.id}" => {:operator => '=', :values => ['Foo']}}
-    assert_equal 2, find_issues_with_query(query).size
-
-    field.project_ids = [1, 3] # Disable the field for project 4
-    field.save!
-    assert_equal 1, find_issues_with_query(query).size
-  end
-
-  def test_filter_on_custom_field_should_ignore_trackers_with_field_disabled
-    field = IssueCustomField.generate!(:tracker_ids => [1, 2], :is_for_all => true, :is_filter => true)
-    Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id.to_s => 'Foo'})
-    Issue.generate!(:project_id => 1, :tracker_id => 2, :custom_field_values => {field.id.to_s => 'Foo'})
-
-    query = IssueQuery.new(:name => '_', :project => Project.find(1))
-    query.filters = {"cf_#{field.id}" => {:operator => '=', :values => ['Foo']}}
-    assert_equal 2, find_issues_with_query(query).size
-
-    field.tracker_ids = [1] # Disable the field for tracker 2
-    field.save!
-    assert_equal 1, find_issues_with_query(query).size
-  end
-
-  def test_filter_on_project_custom_field
-    field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
-    CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
-    CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
-
-    query = IssueQuery.new(:name => '_')
-    filter_name = "project.cf_#{field.id}"
-    assert_include filter_name, query.available_filters.keys
-    query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
-    assert_equal [3, 5], find_issues_with_query(query).map(&:project_id).uniq.sort
-  end
-
-  def test_filter_on_author_custom_field
-    field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
-    CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
-
-    query = IssueQuery.new(:name => '_')
-    filter_name = "author.cf_#{field.id}"
-    assert_include filter_name, query.available_filters.keys
-    query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
-    assert_equal [3], find_issues_with_query(query).map(&:author_id).uniq.sort
-  end
-
-  def test_filter_on_assigned_to_custom_field
-    field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
-    CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
-
-    query = IssueQuery.new(:name => '_')
-    filter_name = "assigned_to.cf_#{field.id}"
-    assert_include filter_name, query.available_filters.keys
-    query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
-    assert_equal [3], find_issues_with_query(query).map(&:assigned_to_id).uniq.sort
-  end
-
-  def test_filter_on_fixed_version_custom_field
-    field = VersionCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
-    CustomValue.create!(:custom_field => field, :customized => Version.find(2), :value => 'Foo')
-
-    query = IssueQuery.new(:name => '_')
-    filter_name = "fixed_version.cf_#{field.id}"
-    assert_include filter_name, query.available_filters.keys
-    query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
-    assert_equal [2], find_issues_with_query(query).map(&:fixed_version_id).uniq.sort
-  end
-
-  def test_filter_on_relations_with_a_specific_issue
-    IssueRelation.delete_all
-    IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
-    IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {"relates" => {:operator => '=', :values => ['1']}}
-    assert_equal [2, 3], find_issues_with_query(query).map(&:id).sort
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {"relates" => {:operator => '=', :values => ['2']}}
-    assert_equal [1], find_issues_with_query(query).map(&:id).sort
-  end
-
-  def test_filter_on_relations_with_any_issues_in_a_project
-    IssueRelation.delete_all
-    with_settings :cross_project_issue_relations => '1' do
-      IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
-      IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(2).issues.first)
-      IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first)
-    end
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {"relates" => {:operator => '=p', :values => ['2']}}
-    assert_equal [1, 2], find_issues_with_query(query).map(&:id).sort
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {"relates" => {:operator => '=p', :values => ['3']}}
-    assert_equal [1], find_issues_with_query(query).map(&:id).sort
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {"relates" => {:operator => '=p', :values => ['4']}}
-    assert_equal [], find_issues_with_query(query).map(&:id).sort
-  end
-
-  def test_filter_on_relations_with_any_issues_not_in_a_project
-    IssueRelation.delete_all
-    with_settings :cross_project_issue_relations => '1' do
-      IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
-      #IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(1).issues.first)
-      IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(3).issues.first)
-    end
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {"relates" => {:operator => '=!p', :values => ['1']}}
-    assert_equal [1], find_issues_with_query(query).map(&:id).sort
-  end
-
-  def test_filter_on_relations_with_no_issues_in_a_project
-    IssueRelation.delete_all
-    with_settings :cross_project_issue_relations => '1' do
-      IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
-      IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(3).issues.first)
-      IssueRelation.create!(:relation_type => "relates", :issue_to => Project.find(2).issues.first, :issue_from => Issue.find(3))
-    end
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {"relates" => {:operator => '!p', :values => ['2']}}
-    ids = find_issues_with_query(query).map(&:id).sort
-    assert_include 2, ids
-    assert_not_include 1, ids
-    assert_not_include 3, ids
-  end
-
-  def test_filter_on_relations_with_no_issues
-    IssueRelation.delete_all
-    IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
-    IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {"relates" => {:operator => '!*', :values => ['']}}
-    ids = find_issues_with_query(query).map(&:id)
-    assert_equal [], ids & [1, 2, 3]
-    assert_include 4, ids
-  end
-
-  def test_filter_on_relations_with_any_issues
-    IssueRelation.delete_all
-    IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
-    IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(3), :issue_to => Issue.find(1))
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {"relates" => {:operator => '*', :values => ['']}}
-    assert_equal [1, 2, 3], find_issues_with_query(query).map(&:id).sort
-  end
-
-  def test_filter_on_relations_should_not_ignore_other_filter
-    issue = Issue.generate!
-    issue1 = Issue.generate!(:status_id => 1)
-    issue2 = Issue.generate!(:status_id => 2)
-    IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue1)
-    IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue2)
-
-    query = IssueQuery.new(:name => '_')
-    query.filters = {
-      "status_id" => {:operator => '=', :values => ['1']},
-      "relates" => {:operator => '=', :values => [issue.id.to_s]}
-    }
-    assert_equal [issue1], find_issues_with_query(query)
-  end
-
-  def test_statement_should_be_nil_with_no_filters
-    q = IssueQuery.new(:name => '_')
-    q.filters = {}
-
-    assert q.valid?
-    assert_nil q.statement
-  end
-
-  def test_default_columns
-    q = IssueQuery.new
-    assert q.columns.any?
-    assert q.inline_columns.any?
-    assert q.block_columns.empty?
-  end
-
-  def test_set_column_names
-    q = IssueQuery.new
-    q.column_names = ['tracker', :subject, '', 'unknonw_column']
-    assert_equal [:id, :tracker, :subject], q.columns.collect {|c| c.name}
-  end
-
-  def test_has_column_should_accept_a_column_name
-    q = IssueQuery.new
-    q.column_names = ['tracker', :subject]
-    assert q.has_column?(:tracker)
-    assert !q.has_column?(:category)
-  end
-
-  def test_has_column_should_accept_a_column
-    q = IssueQuery.new
-    q.column_names = ['tracker', :subject]
-
-    tracker_column = q.available_columns.detect {|c| c.name==:tracker}
-    assert_kind_of QueryColumn, tracker_column
-    category_column = q.available_columns.detect {|c| c.name==:category}
-    assert_kind_of QueryColumn, category_column
-
-    assert q.has_column?(tracker_column)
-    assert !q.has_column?(category_column)
-  end
-
-  def test_inline_and_block_columns
-    q = IssueQuery.new
-    q.column_names = ['subject', 'description', 'tracker']
-
-    assert_equal [:id, :subject, :tracker], q.inline_columns.map(&:name)
-    assert_equal [:description], q.block_columns.map(&:name)
-  end
-
-  def test_custom_field_columns_should_be_inline
-    q = IssueQuery.new
-    columns = q.available_columns.select {|column| column.is_a? QueryCustomFieldColumn}
-    assert columns.any?
-    assert_nil columns.detect {|column| !column.inline?}
-  end
-
-  def test_query_should_preload_spent_hours
-    q = IssueQuery.new(:name => '_', :column_names => [:subject, :spent_hours])
-    assert q.has_column?(:spent_hours)
-    issues = q.issues
-    assert_not_nil issues.first.instance_variable_get("@spent_hours")
-  end
-
-  def test_groupable_columns_should_include_custom_fields
-    q = IssueQuery.new
-    column = q.groupable_columns.detect {|c| c.name == :cf_1}
-    assert_not_nil column
-    assert_kind_of QueryCustomFieldColumn, column
-  end
-
-  def test_groupable_columns_should_not_include_multi_custom_fields
-    field = CustomField.find(1)
-    field.update_attribute :multiple, true
-
-    q = IssueQuery.new
-    column = q.groupable_columns.detect {|c| c.name == :cf_1}
-    assert_nil column
-  end
-
-  def test_groupable_columns_should_include_user_custom_fields
-    cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'user')
-
-    q = IssueQuery.new
-    assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym}
-  end
-
-  def test_groupable_columns_should_include_version_custom_fields
-    cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1], :field_format => 'version')
-
-    q = IssueQuery.new
-    assert q.groupable_columns.detect {|c| c.name == "cf_#{cf.id}".to_sym}
-  end
-
-  def test_grouped_with_valid_column
-    q = IssueQuery.new(:group_by => 'status')
-    assert q.grouped?
-    assert_not_nil q.group_by_column
-    assert_equal :status, q.group_by_column.name
-    assert_not_nil q.group_by_statement
-    assert_equal 'status', q.group_by_statement
-  end
-
-  def test_grouped_with_invalid_column
-    q = IssueQuery.new(:group_by => 'foo')
-    assert !q.grouped?
-    assert_nil q.group_by_column
-    assert_nil q.group_by_statement
-  end
-
-  def test_sortable_columns_should_sort_assignees_according_to_user_format_setting
-    with_settings :user_format => 'lastname_coma_firstname' do
-      q = IssueQuery.new
-      assert q.sortable_columns.has_key?('assigned_to')
-      assert_equal %w(users.lastname users.firstname users.id), q.sortable_columns['assigned_to']
-    end
-  end
-
-  def test_sortable_columns_should_sort_authors_according_to_user_format_setting
-    with_settings :user_format => 'lastname_coma_firstname' do
-      q = IssueQuery.new
-      assert q.sortable_columns.has_key?('author')
-      assert_equal %w(authors.lastname authors.firstname authors.id), q.sortable_columns['author']
-    end
-  end
-
-  def test_sortable_columns_should_include_custom_field
-    q = IssueQuery.new
-    assert q.sortable_columns['cf_1']
-  end
-
-  def test_sortable_columns_should_not_include_multi_custom_field
-    field = CustomField.find(1)
-    field.update_attribute :multiple, true
-
-    q = IssueQuery.new
-    assert !q.sortable_columns['cf_1']
-  end
-
-  def test_default_sort
-    q = IssueQuery.new
-    assert_equal [], q.sort_criteria
-  end
-
-  def test_set_sort_criteria_with_hash
-    q = IssueQuery.new
-    q.sort_criteria = {'0' => ['priority', 'desc'], '2' => ['tracker']}
-    assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
-  end
-
-  def test_set_sort_criteria_with_array
-    q = IssueQuery.new
-    q.sort_criteria = [['priority', 'desc'], 'tracker']
-    assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
-  end
-
-  def test_create_query_with_sort
-    q = IssueQuery.new(:name => 'Sorted')
-    q.sort_criteria = [['priority', 'desc'], 'tracker']
-    assert q.save
-    q.reload
-    assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
-  end
-
-  def test_sort_by_string_custom_field_asc
-    q = IssueQuery.new
-    c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
-    assert c
-    assert c.sortable
-    issues = q.issues(:order => "#{c.sortable} ASC")
-    values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
-    assert !values.empty?
-    assert_equal values.sort, values
-  end
-
-  def test_sort_by_string_custom_field_desc
-    q = IssueQuery.new
-    c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
-    assert c
-    assert c.sortable
-    issues = q.issues(:order => "#{c.sortable} DESC")
-    values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
-    assert !values.empty?
-    assert_equal values.sort.reverse, values
-  end
-
-  def test_sort_by_float_custom_field_asc
-    q = IssueQuery.new
-    c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' }
-    assert c
-    assert c.sortable
-    issues = q.issues(:order => "#{c.sortable} ASC")
-    values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact
-    assert !values.empty?
-    assert_equal values.sort, values
-  end
-
-  def test_invalid_query_should_raise_query_statement_invalid_error
-    q = IssueQuery.new
-    assert_raise Query::StatementInvalid do
-      q.issues(:conditions => "foo = 1")
-    end
-  end
-
-  def test_issue_count
-    q = IssueQuery.new(:name => '_')
-    issue_count = q.issue_count
-    assert_equal q.issues.size, issue_count
-  end
-
-  def test_issue_count_with_archived_issues
-    p = Project.generate! do |project|
-      project.status = Project::STATUS_ARCHIVED
-    end
-    i = Issue.generate!( :project => p, :tracker => p.trackers.first )
-    assert !i.visible?
-
-    test_issue_count
-  end
-
-  def test_issue_count_by_association_group
-    q = IssueQuery.new(:name => '_', :group_by => 'assigned_to')
-    count_by_group = q.issue_count_by_group
-    assert_kind_of Hash, count_by_group
-    assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
-    assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
-    assert count_by_group.has_key?(User.find(3))
-  end
-
-  def test_issue_count_by_list_custom_field_group
-    q = IssueQuery.new(:name => '_', :group_by => 'cf_1')
-    count_by_group = q.issue_count_by_group
-    assert_kind_of Hash, count_by_group
-    assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
-    assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
-    assert count_by_group.has_key?('MySQL')
-  end
-
-  def test_issue_count_by_date_custom_field_group
-    q = IssueQuery.new(:name => '_', :group_by => 'cf_8')
-    count_by_group = q.issue_count_by_group
-    assert_kind_of Hash, count_by_group
-    assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
-    assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
-  end
-
-  def test_issue_count_with_nil_group_only
-    Issue.update_all("assigned_to_id = NULL")
-
-    q = IssueQuery.new(:name => '_', :group_by => 'assigned_to')
-    count_by_group = q.issue_count_by_group
-    assert_kind_of Hash, count_by_group
-    assert_equal 1, count_by_group.keys.size
-    assert_nil count_by_group.keys.first
-  end
-
-  def test_issue_ids
-    q = IssueQuery.new(:name => '_')
-    order = "issues.subject, issues.id"
-    issues = q.issues(:order => order)
-    assert_equal issues.map(&:id), q.issue_ids(:order => order)
-  end
-
-  def test_label_for
-    set_language_if_valid 'en'
-    q = IssueQuery.new
-    assert_equal 'Assignee', q.label_for('assigned_to_id')
-  end
-
-  def test_label_for_fr
-    set_language_if_valid 'fr'
-    q = IssueQuery.new
-    s = "Assign\xc3\xa9 \xc3\xa0"
-    s.force_encoding('UTF-8') if s.respond_to?(:force_encoding)
-    assert_equal s, q.label_for('assigned_to_id')
-  end
-
-  def test_editable_by
-    admin = User.find(1)
-    manager = User.find(2)
-    developer = User.find(3)
-
-    # Public query on project 1
-    q = IssueQuery.find(1)
-    assert q.editable_by?(admin)
-    assert q.editable_by?(manager)
-    assert !q.editable_by?(developer)
-
-    # Private query on project 1
-    q = IssueQuery.find(2)
-    assert q.editable_by?(admin)
-    assert !q.editable_by?(manager)
-    assert q.editable_by?(developer)
-
-    # Private query for all projects
-    q = IssueQuery.find(3)
-    assert q.editable_by?(admin)
-    assert !q.editable_by?(manager)
-    assert q.editable_by?(developer)
-
-    # Public query for all projects
-    q = IssueQuery.find(4)
-    assert q.editable_by?(admin)
-    assert !q.editable_by?(manager)
-    assert !q.editable_by?(developer)
-  end
-
-  def test_visible_scope
-    query_ids = IssueQuery.visible(User.anonymous).map(&:id)
-
-    assert query_ids.include?(1), 'public query on public project was not visible'
-    assert query_ids.include?(4), 'public query for all projects was not visible'
-    assert !query_ids.include?(2), 'private query on public project was visible'
-    assert !query_ids.include?(3), 'private query for all projects was visible'
-    assert !query_ids.include?(7), 'public query on private project was visible'
-  end
-
-  def test_query_with_public_visibility_should_be_visible_to_anyone
-    q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_PUBLIC)
-
-    assert q.visible?(User.anonymous)
-    assert IssueQuery.visible(User.anonymous).find_by_id(q.id)
-
-    assert q.visible?(User.find(7))
-    assert IssueQuery.visible(User.find(7)).find_by_id(q.id)
-
-    assert q.visible?(User.find(2))
-    assert IssueQuery.visible(User.find(2)).find_by_id(q.id)
-
-    assert q.visible?(User.find(1))
-    assert IssueQuery.visible(User.find(1)).find_by_id(q.id)
-  end
-
-  def test_query_with_roles_visibility_should_be_visible_to_user_with_role
-    q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_ROLES, :role_ids => [1,2])
-
-    assert !q.visible?(User.anonymous)
-    assert_nil IssueQuery.visible(User.anonymous).find_by_id(q.id)
-
-    assert !q.visible?(User.find(7))
-    assert_nil IssueQuery.visible(User.find(7)).find_by_id(q.id)
-
-    assert q.visible?(User.find(2))
-    assert IssueQuery.visible(User.find(2)).find_by_id(q.id)
-
-    assert q.visible?(User.find(1))
-    assert IssueQuery.visible(User.find(1)).find_by_id(q.id)
-  end
-
-  def test_query_with_private_visibility_should_be_visible_to_owner
-    q = IssueQuery.create!(:name => 'Query', :visibility => IssueQuery::VISIBILITY_PRIVATE, :user => User.find(7))
-
-    assert !q.visible?(User.anonymous)
-    assert_nil IssueQuery.visible(User.anonymous).find_by_id(q.id)
-
-    assert q.visible?(User.find(7))
-    assert IssueQuery.visible(User.find(7)).find_by_id(q.id)
-
-    assert !q.visible?(User.find(2))
-    assert_nil IssueQuery.visible(User.find(2)).find_by_id(q.id)
-
-    assert q.visible?(User.find(1))
-    assert_nil IssueQuery.visible(User.find(1)).find_by_id(q.id)
-  end
-
-  test "#available_filters should include users of visible projects in cross-project view" do
-    users = IssueQuery.new.available_filters["assigned_to_id"]
-    assert_not_nil users
-    assert users[:values].map{|u|u[1]}.include?("3")
-  end
-
-  test "#available_filters should include users of subprojects" do
-    user1 = User.generate!
-    user2 = User.generate!
-    project = Project.find(1)
-    Member.create!(:principal => user1, :project => project.children.visible.first, :role_ids => [1])
-
-    users = IssueQuery.new(:project => project).available_filters["assigned_to_id"]
-    assert_not_nil users
-    assert users[:values].map{|u|u[1]}.include?(user1.id.to_s)
-    assert !users[:values].map{|u|u[1]}.include?(user2.id.to_s)
-  end
-
-  test "#available_filters should include visible projects in cross-project view" do
-    projects = IssueQuery.new.available_filters["project_id"]
-    assert_not_nil projects
-    assert projects[:values].map{|u|u[1]}.include?("1")
-  end
-
-  test "#available_filters should include 'member_of_group' filter" do
-    query = IssueQuery.new
-    assert query.available_filters.keys.include?("member_of_group")
-    assert_equal :list_optional, query.available_filters["member_of_group"][:type]
-    assert query.available_filters["member_of_group"][:values].present?
-    assert_equal Group.all.sort.map {|g| [g.name, g.id.to_s]},
-      query.available_filters["member_of_group"][:values].sort
-  end
-
-  test "#available_filters should include 'assigned_to_role' filter" do
-    query = IssueQuery.new
-    assert query.available_filters.keys.include?("assigned_to_role")
-    assert_equal :list_optional, query.available_filters["assigned_to_role"][:type]
-
-    assert query.available_filters["assigned_to_role"][:values].include?(['Manager','1'])
-    assert query.available_filters["assigned_to_role"][:values].include?(['Developer','2'])
-    assert query.available_filters["assigned_to_role"][:values].include?(['Reporter','3'])
-
-    assert ! query.available_filters["assigned_to_role"][:values].include?(['Non member','4'])
-    assert ! query.available_filters["assigned_to_role"][:values].include?(['Anonymous','5'])
-  end
-
-  def test_available_filters_should_include_custom_field_according_to_user_visibility
-    visible_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => true)
-    hidden_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => false, :role_ids => [1])
-
-    with_current_user User.find(3) do
-      query = IssueQuery.new
-      assert_include "cf_#{visible_field.id}", query.available_filters.keys
-      assert_not_include "cf_#{hidden_field.id}", query.available_filters.keys
-    end
-  end
-
-  def test_available_columns_should_include_custom_field_according_to_user_visibility
-    visible_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => true)
-    hidden_field = IssueCustomField.generate!(:is_for_all => true, :is_filter => true, :visible => false, :role_ids => [1])
-
-    with_current_user User.find(3) do
-      query = IssueQuery.new
-      assert_include :"cf_#{visible_field.id}", query.available_columns.map(&:name)
-      assert_not_include :"cf_#{hidden_field.id}", query.available_columns.map(&:name)
-    end
-  end
-
-  context "#statement" do
-    context "with 'member_of_group' filter" do
-      setup do
-        Group.destroy_all # No fixtures
-        @user_in_group = User.generate!
-        @second_user_in_group = User.generate!
-        @user_in_group2 = User.generate!
-        @user_not_in_group = User.generate!
-
-        @group = Group.generate!.reload
-        @group.users << @user_in_group
-        @group.users << @second_user_in_group
-
-        @group2 = Group.generate!.reload
-        @group2.users << @user_in_group2
-
-      end
-
-      should "search assigned to for users in the group" do
-        @query = IssueQuery.new(:name => '_')
-        @query.add_filter('member_of_group', '=', [@group.id.to_s])
-
-        assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@group.id}')"
-        assert_find_issues_with_query_is_successful @query
-      end
-
-      should "search not assigned to any group member (none)" do
-        @query = IssueQuery.new(:name => '_')
-        @query.add_filter('member_of_group', '!*', [''])
-
-        # Users not in a group
-        assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IS NULL OR #{Issue.table_name}.assigned_to_id NOT IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@user_in_group2.id}','#{@group.id}','#{@group2.id}')"
-        assert_find_issues_with_query_is_successful @query
-      end
-
-      should "search assigned to any group member (all)" do
-        @query = IssueQuery.new(:name => '_')
-        @query.add_filter('member_of_group', '*', [''])
-
-        # Only users in a group
-        assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@user_in_group2.id}','#{@group.id}','#{@group2.id}')"
-        assert_find_issues_with_query_is_successful @query
-      end
-
-      should "return an empty set with = empty group" do
-        @empty_group = Group.generate!
-        @query = IssueQuery.new(:name => '_')
-        @query.add_filter('member_of_group', '=', [@empty_group.id.to_s])
-
-        assert_equal [], find_issues_with_query(@query)
-      end
-
-      should "return issues with ! empty group" do
-        @empty_group = Group.generate!
-        @query = IssueQuery.new(:name => '_')
-        @query.add_filter('member_of_group', '!', [@empty_group.id.to_s])
-
-        assert_find_issues_with_query_is_successful @query
-      end
-    end
-
-    context "with 'assigned_to_role' filter" do
-      setup do
-        @manager_role = Role.find_by_name('Manager')
-        @developer_role = Role.find_by_name('Developer')
-
-        @project = Project.generate!
-        @manager = User.generate!
-        @developer = User.generate!
-        @boss = User.generate!
-        @guest = User.generate!
-        User.add_to_project(@manager, @project, @manager_role)
-        User.add_to_project(@developer, @project, @developer_role)
-        User.add_to_project(@boss, @project, [@manager_role, @developer_role])
-
-        @issue1 = Issue.generate!(:project => @project, :assigned_to_id => @manager.id)
-        @issue2 = Issue.generate!(:project => @project, :assigned_to_id => @developer.id)
-        @issue3 = Issue.generate!(:project => @project, :assigned_to_id => @boss.id)
-        @issue4 = Issue.generate!(:project => @project, :assigned_to_id => @guest.id)
-        @issue5 = Issue.generate!(:project => @project)
-      end
-
-      should "search assigned to for users with the Role" do
-        @query = IssueQuery.new(:name => '_', :project => @project)
-        @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
-
-        assert_query_result [@issue1, @issue3], @query
-      end
-
-      should "search assigned to for users with the Role on the issue project" do
-        other_project = Project.generate!
-        User.add_to_project(@developer, other_project, @manager_role)
-
-        @query = IssueQuery.new(:name => '_', :project => @project)
-        @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
-
-        assert_query_result [@issue1, @issue3], @query
-      end
-
-      should "return an empty set with empty role" do
-        @empty_role = Role.generate!
-        @query = IssueQuery.new(:name => '_', :project => @project)
-        @query.add_filter('assigned_to_role', '=', [@empty_role.id.to_s])
-
-        assert_query_result [], @query
-      end
-
-      should "search assigned to for users without the Role" do
-        @query = IssueQuery.new(:name => '_', :project => @project)
-        @query.add_filter('assigned_to_role', '!', [@manager_role.id.to_s])
-
-        assert_query_result [@issue2, @issue4, @issue5], @query
-      end
-
-      should "search assigned to for users not assigned to any Role (none)" do
-        @query = IssueQuery.new(:name => '_', :project => @project)
-        @query.add_filter('assigned_to_role', '!*', [''])
-
-        assert_query_result [@issue4, @issue5], @query
-      end
-
-      should "search assigned to for users assigned to any Role (all)" do
-        @query = IssueQuery.new(:name => '_', :project => @project)
-        @query.add_filter('assigned_to_role', '*', [''])
-
-        assert_query_result [@issue1, @issue2, @issue3], @query
-      end
-
-      should "return issues with ! empty role" do
-        @empty_role = Role.generate!
-        @query = IssueQuery.new(:name => '_', :project => @project)
-        @query.add_filter('assigned_to_role', '!', [@empty_role.id.to_s])
-
-        assert_query_result [@issue1, @issue2, @issue3, @issue4, @issue5], @query
-      end
-    end
-  end
-end
--- a/.svn/pristine/87/871ab69c9430fd870a684b73b2e5c6c68ed7f0f1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module CalendarsHelper
-  def link_to_previous_month(year, month, options={})
-    target_year, target_month = if month == 1
-                                  [year - 1, 12]
-                                else
-                                  [year, month - 1]
-                                end
-
-    name = if target_month == 12
-             "#{month_name(target_month)} #{target_year}"
-           else
-             "#{month_name(target_month)}"
-           end
-
-    # \xc2\xab(utf-8) = &#171;
-    link_to_month(("\xc2\xab " + name), target_year, target_month, options)
-  end
-
-  def link_to_next_month(year, month, options={})
-    target_year, target_month = if month == 12
-                                  [year + 1, 1]
-                                else
-                                  [year, month + 1]
-                                end
-
-    name = if target_month == 1
-             "#{month_name(target_month)} #{target_year}"
-           else
-             "#{month_name(target_month)}"
-           end
-
-    # \xc2\xbb(utf-8) = &#187;
-    link_to_month((name + " \xc2\xbb"), target_year, target_month, options)
-  end
-
-  def link_to_month(link_name, year, month, options={})
-    link_to_content_update(h(link_name), params.merge(:year => year, :month => month))
-  end
-end
--- a/.svn/pristine/89/8937afa1653ec0053686c11b0489477d9550a47d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class WorkflowTransition < WorkflowRule
-  validates_presence_of :new_status
-
-  # Returns workflow transitions count by tracker and role
-  def self.count_by_tracker_and_role
-    counts = connection.select_all("SELECT role_id, tracker_id, count(id) AS c FROM #{table_name} WHERE type = 'WorkflowTransition' GROUP BY role_id, tracker_id")
-    roles = Role.sorted.all
-    trackers = Tracker.sorted.all
-
-    result = []
-    trackers.each do |tracker|
-      t = []
-      roles.each do |role|
-        row = counts.detect {|c| c['role_id'].to_s == role.id.to_s && c['tracker_id'].to_s == tracker.id.to_s}
-        t << [role, (row.nil? ? 0 : row['c'].to_i)]
-      end
-      result << [tracker, t]
-    end
-
-    result
-  end
-end
--- a/.svn/pristine/89/89f2f1de1b0c1a744af1b4d7a2c5c156ca193d25.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Board < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  belongs_to :project
-  has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC"
-  has_many :messages, :dependent => :destroy, :order => "#{Message.table_name}.created_on DESC"
-  belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id
-  acts_as_tree :dependent => :nullify
-  acts_as_list :scope => '(project_id = #{project_id} AND parent_id #{parent_id ? "= #{parent_id}" : "IS NULL"})'
-  acts_as_watchable
-
-  validates_presence_of :name, :description
-  validates_length_of :name, :maximum => 30
-  validates_length_of :description, :maximum => 255
-  validate :validate_board
-
-  scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
-  }
-
-  safe_attributes 'name', 'description', 'parent_id', 'move_to'
-
-  def visible?(user=User.current)
-    !user.nil? && user.allowed_to?(:view_messages, project)
-  end
-
-  def reload(*args)
-    @valid_parents = nil
-    super
-  end
-
-  def to_s
-    name
-  end
-
-  def valid_parents
-    @valid_parents ||= project.boards - self_and_descendants
-  end
-
-  def reset_counters!
-    self.class.reset_counters!(id)
-  end
-
-  # Updates topics_count, messages_count and last_message_id attributes for +board_id+
-  def self.reset_counters!(board_id)
-    board_id = board_id.to_i
-    update_all("topics_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id} AND parent_id IS NULL)," +
-               " messages_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id})," +
-               " last_message_id = (SELECT MAX(id) FROM #{Message.table_name} WHERE board_id=#{board_id})",
-               ["id = ?", board_id])
-  end
-
-  def self.board_tree(boards, parent_id=nil, level=0)
-    tree = []
-    boards.select {|board| board.parent_id == parent_id}.sort_by(&:position).each do |board|
-      tree << [board, level]
-      tree += board_tree(boards, board.id, level+1)
-    end
-    if block_given?
-      tree.each do |board, level|
-        yield board, level
-      end
-    end
-    tree
-  end
-
-  protected
-
-  def validate_board
-    if parent_id && parent_id_changed?
-      errors.add(:parent_id, :invalid) unless valid_parents.include?(parent)
-    end
-  end
-end
--- a/.svn/pristine/8a/8a339bcd7d20e6ca60eea513a81446d12d132459.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module IssueRelationsHelper
-  def collection_for_relation_type_select
-    values = IssueRelation::TYPES
-    values.keys.sort{|x,y| values[x][:order] <=> values[y][:order]}.collect{|k| [l(values[k][:name]), k]}
-  end
-end
--- a/.svn/pristine/8a/8ab4630ebd77e09c1eecc6ce7e00d173fda9baab.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::HttpBasicLoginTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def setup
-    Setting.rest_api_enabled = '1'
-    Setting.login_required = '1'
-  end
-
-  def teardown
-    Setting.rest_api_enabled = '0'
-    Setting.login_required = '0'
-  end
-
-  # Using the NewsController because it's a simple API.
-  context "get /news" do
-    setup do
-      project = Project.find('onlinestore')
-      EnabledModule.create(:project => project, :name => 'news')
-    end
-
-    context "in :xml format" do
-      should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.xml")
-    end
-
-    context "in :json format" do
-      should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.json")
-    end
-  end
-end
--- a/.svn/pristine/8a/8ad0e856fe663028d1a8b29da96008e903c9b16e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class CustomFieldsControllerTest < ActionController::TestCase
-  fixtures :custom_fields, :custom_values, :trackers, :users, :projects
-
-  def setup
-    @request.session[:user_id] = 1
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-  end
-
-  def test_new
-    custom_field_classes.each do |klass|
-      get :new, :type => klass.name
-      assert_response :success
-      assert_template 'new'
-      assert_kind_of klass, assigns(:custom_field)
-      assert_select 'form#custom_field_form' do
-        assert_select 'select#custom_field_field_format[name=?]', 'custom_field[field_format]'
-        assert_select 'input[type=hidden][name=type][value=?]', klass.name
-      end
-    end
-  end
-
-  def test_new_issue_custom_field
-    get :new, :type => 'IssueCustomField'
-    assert_response :success
-    assert_template 'new'
-    assert_select 'form#custom_field_form' do
-      assert_select 'select#custom_field_field_format[name=?]', 'custom_field[field_format]' do
-        assert_select 'option[value=user]', :text => 'User'
-        assert_select 'option[value=version]', :text => 'Version'
-      end
-      assert_select 'input[type=checkbox][name=?]', 'custom_field[project_ids][]', Project.count
-      assert_select 'input[type=hidden][name=?]', 'custom_field[project_ids][]', 1
-      assert_select 'input[type=hidden][name=type][value=IssueCustomField]'
-    end
-  end
-
-  def test_new_time_entry_custom_field_should_not_show_trackers_and_projects
-    get :new, :type => 'TimeEntryCustomField'
-    assert_response :success
-    assert_template 'new'
-    assert_select 'form#custom_field_form' do
-      assert_select 'input[name=?]', 'custom_field[tracker_ids][]', 0
-      assert_select 'input[name=?]', 'custom_field[project_ids][]', 0
-    end
-  end
-
-  def test_default_value_should_be_an_input_for_string_custom_field
-    get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'string'}
-    assert_response :success
-    assert_select 'input[name=?]', 'custom_field[default_value]'
-  end
-
-  def test_default_value_should_be_a_textarea_for_text_custom_field
-    get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'text'}
-    assert_response :success
-    assert_select 'textarea[name=?]', 'custom_field[default_value]'
-  end
-
-  def test_default_value_should_be_a_checkbox_for_bool_custom_field
-    get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'bool'}
-    assert_response :success
-    assert_select 'input[name=?][type=checkbox]', 'custom_field[default_value]'
-  end
-
-  def test_default_value_should_not_be_present_for_user_custom_field
-    get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'user'}
-    assert_response :success
-    assert_select '[name=?]', 'custom_field[default_value]', 0
-  end
-
-  def test_new_js
-    get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'list'}, :format => 'js'
-    assert_response :success
-    assert_template 'new'
-    assert_equal 'text/javascript', response.content_type
-
-    field = assigns(:custom_field)
-    assert_equal 'list', field.field_format
-  end
-
-  def test_new_with_invalid_custom_field_class_should_render_404
-    get :new, :type => 'UnknownCustomField'
-    assert_response 404
-  end
-
-  def test_create_list_custom_field
-    assert_difference 'CustomField.count' do
-      post :create, :type => "IssueCustomField",
-                 :custom_field => {:name => "test_post_new_list",
-                                   :default_value => "",
-                                   :min_length => "0",
-                                   :searchable => "0",
-                                   :regexp => "",
-                                   :is_for_all => "1",
-                                   :possible_values => "0.1\n0.2\n",
-                                   :max_length => "0",
-                                   :is_filter => "0",
-                                   :is_required =>"0",
-                                   :field_format => "list",
-                                   :tracker_ids => ["1", ""]}
-    end
-    assert_redirected_to '/custom_fields?tab=IssueCustomField'
-    field = IssueCustomField.find_by_name('test_post_new_list')
-    assert_not_nil field
-    assert_equal ["0.1", "0.2"], field.possible_values
-    assert_equal 1, field.trackers.size
-  end
-
-  def test_create_with_project_ids
-    assert_difference 'CustomField.count' do
-      post :create, :type => "IssueCustomField", :custom_field => {
-        :name => "foo", :field_format => "string", :is_for_all => "0", :project_ids => ["1", "3", ""]
-      }
-      assert_response 302
-    end
-    field = IssueCustomField.order("id desc").first
-    assert_equal [1, 3], field.projects.map(&:id).sort
-  end
-
-  def test_create_with_failure
-    assert_no_difference 'CustomField.count' do
-      post :create, :type => "IssueCustomField", :custom_field => {:name => ''}
-    end
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_edit
-    get :edit, :id => 1
-    assert_response :success
-    assert_template 'edit'
-    assert_tag 'input', :attributes => {:name => 'custom_field[name]', :value => 'Database'}
-  end
-
-  def test_edit_invalid_custom_field_should_render_404
-    get :edit, :id => 99
-    assert_response 404
-  end
-
-  def test_update
-    put :update, :id => 1, :custom_field => {:name => 'New name'}
-    assert_redirected_to '/custom_fields?tab=IssueCustomField'
-
-    field = CustomField.find(1)
-    assert_equal 'New name', field.name
-  end
-
-  def test_update_with_failure
-    put :update, :id => 1, :custom_field => {:name => ''}
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_destroy
-    custom_values_count = CustomValue.where(:custom_field_id => 1).count
-    assert custom_values_count > 0
-
-    assert_difference 'CustomField.count', -1 do
-      assert_difference 'CustomValue.count', - custom_values_count do
-        delete :destroy, :id => 1
-      end
-    end
-
-    assert_redirected_to '/custom_fields?tab=IssueCustomField'
-    assert_nil CustomField.find_by_id(1)
-    assert_nil CustomValue.find_by_custom_field_id(1)
-  end
-
-  def custom_field_classes
-    files = Dir.glob(File.join(Rails.root, 'app/models/*_custom_field.rb')).map {|f| File.basename(f).sub(/\.rb$/, '') }
-    classes = files.map(&:classify).map(&:constantize)
-    assert classes.size > 0
-    classes
-  end
-end
--- a/.svn/pristine/8b/8b54895a280a4b6be2315b819f9e36a6caaa65f2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class TimeEntryCustomField < CustomField
-  def type_name
-    :label_spent_time
-  end
-end
-
--- a/.svn/pristine/8b/8b6b9cb4de924997fd5c8d066cf49e5fb943de93.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class CalendarsController < ApplicationController
-  menu_item :calendar
-  before_filter :find_optional_project
-
-  rescue_from Query::StatementInvalid, :with => :query_statement_invalid
-
-  helper :issues
-  helper :projects
-  helper :queries
-  include QueriesHelper
-  helper :sort
-  include SortHelper
-
-  def show
-    if params[:year] and params[:year].to_i > 1900
-      @year = params[:year].to_i
-      if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
-        @month = params[:month].to_i
-      end
-    end
-    @year ||= Date.today.year
-    @month ||= Date.today.month
-
-    @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month)
-    retrieve_query
-    @query.group_by = nil
-    if @query.valid?
-      events = []
-      events += @query.issues(:include => [:tracker, :assigned_to, :priority],
-                              :conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
-                              )
-      events += @query.versions(:conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
-
-      @calendar.events = events
-    end
-
-    render :action => 'show', :layout => false if request.xhr?
-  end
-end
--- a/.svn/pristine/8b/8b8a4a4fb98bb4ad97ae1d153aef221af93fc010.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-desc <<-END_DESC
-Send reminders about issues due in the next days.
-
-Available options:
-  * days     => number of days to remind about (defaults to 7)
-  * tracker  => id of tracker (defaults to all trackers)
-  * project  => id or identifier of project (defaults to all projects)
-  * users    => comma separated list of user/group ids who should be reminded
-
-Example:
-  rake redmine:send_reminders days=7 users="1,23, 56" RAILS_ENV="production"
-END_DESC
-
-namespace :redmine do
-  task :send_reminders => :environment do
-    options = {}
-    options[:days] = ENV['days'].to_i if ENV['days']
-    options[:project] = ENV['project'] if ENV['project']
-    options[:tracker] = ENV['tracker'].to_i if ENV['tracker']
-    options[:users] = (ENV['users'] || '').split(',').each(&:strip!)
-
-    Mailer.with_synched_deliveries do
-      Mailer.reminders(options)
-    end
-  end
-end
--- a/.svn/pristine/8b/8b8ba498cf3cdcb76cdc45e1ecf9d424b5e9b3cc.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module MyHelper
-  def calendar_items(startdt, enddt)
-    Issue.visible.
-      where(:project_id => User.current.projects.map(&:id)).
-      where("(start_date>=? and start_date<=?) or (due_date>=? and due_date<=?)", startdt, enddt, startdt, enddt).
-      includes(:project, :tracker, :priority, :assigned_to).
-      all
-  end
-
-  def documents_items
-    Document.visible.order("#{Document.table_name}.created_on DESC").limit(10).all
-  end
-
-  def issuesassignedtome_items
-    Issue.visible.open.
-      where(:assigned_to_id => ([User.current.id] + User.current.group_ids)).
-      limit(10).
-      includes(:status, :project, :tracker, :priority).
-      order("#{IssuePriority.table_name}.position DESC, #{Issue.table_name}.updated_on DESC").
-      all
-  end
-
-  def issuesreportedbyme_items
-    Issue.visible.
-      where(:author_id => User.current.id).
-      limit(10).
-      includes(:status, :project, :tracker).
-      order("#{Issue.table_name}.updated_on DESC").
-      all
-  end
-
-  def issueswatched_items
-    Issue.visible.on_active_project.watched_by(User.current.id).recently_updated.limit(10).all
-  end
-
-  def news_items
-    News.visible.
-      where(:project_id => User.current.projects.map(&:id)).
-      limit(10).
-      includes(:project, :author).
-      order("#{News.table_name}.created_on DESC").
-      all
-  end
-
-  def timelog_items
-    TimeEntry.
-      where("#{TimeEntry.table_name}.user_id = ? AND #{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", User.current.id, Date.today - 6, Date.today).
-      includes(:activity, :project, {:issue => [:tracker, :status]}).
-      order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.position ASC, #{Issue.table_name}.id ASC").
-      all
-  end
-end
--- a/.svn/pristine/8b/8bf2ae2c5468c4bc357e9e242162af0247815ad9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class ContextMenusController < ApplicationController
-  helper :watchers
-  helper :issues
-
-  before_filter :find_issues, :only => :issues
-
-  def issues
-    if (@issues.size == 1)
-      @issue = @issues.first
-    end
-    @issue_ids = @issues.map(&:id).sort
-
-    @allowed_statuses = @issues.map(&:new_statuses_allowed_to).reduce(:&)
-
-    @can = {:edit => User.current.allowed_to?(:edit_issues, @projects),
-            :log_time => (@project && User.current.allowed_to?(:log_time, @project)),
-            :update => (User.current.allowed_to?(:edit_issues, @projects) || (User.current.allowed_to?(:change_status, @projects) && !@allowed_statuses.blank?)),
-            :move => (@project && User.current.allowed_to?(:move_issues, @project)),
-            :copy => (@issue && @project.trackers.include?(@issue.tracker) && User.current.allowed_to?(:add_issues, @project)),
-            :delete => User.current.allowed_to?(:delete_issues, @projects)
-            }
-    if @project
-      if @issue
-        @assignables = @issue.assignable_users
-      else
-        @assignables = @project.assignable_users
-      end
-      @trackers = @project.trackers
-    else
-      #when multiple projects, we only keep the intersection of each set
-      @assignables = @projects.map(&:assignable_users).reduce(:&)
-      @trackers = @projects.map(&:trackers).reduce(:&)
-    end
-    @versions = @projects.map {|p| p.shared_versions.open}.reduce(:&)
-
-    @priorities = IssuePriority.active.reverse
-    @back = back_url
-
-    @options_by_custom_field = {}
-    if @can[:edit]
-      custom_fields = @issues.map(&:available_custom_fields).reduce(:&).select do |f|
-        %w(bool list user version).include?(f.field_format) && !f.multiple?
-      end
-      custom_fields.each do |field|
-        values = field.possible_values_options(@projects)
-        if values.any?
-          @options_by_custom_field[field] = values
-        end
-      end
-    end
-
-    @safe_attributes = @issues.map(&:safe_attribute_names).reduce(:&)
-    render :layout => false
-  end
-
-  def time_entries
-    @time_entries = TimeEntry.where(:id => params[:ids]).preload(:project).to_a
-    (render_404; return) unless @time_entries.present?
-
-    @projects = @time_entries.collect(&:project).compact.uniq
-    @project = @projects.first if @projects.size == 1
-    @activities = TimeEntryActivity.shared.active
-    @can = {:edit   => User.current.allowed_to?(:edit_time_entries, @projects),
-            :delete => User.current.allowed_to?(:edit_time_entries, @projects)
-            }
-    @back = back_url
-    render :layout => false
-  end
-end
--- a/.svn/pristine/8c/8c1d2e96303e1f62e53705f1a07477a847f9fb94.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class TimeEntryTest < ActiveSupport::TestCase
-  fixtures :issues, :projects, :users, :time_entries,
-           :members, :roles, :member_roles,
-           :trackers, :issue_statuses,
-           :projects_trackers,
-           :journals, :journal_details,
-           :issue_categories, :enumerations,
-           :groups_users,
-           :enabled_modules
-
-  def test_hours_format
-    assertions = { "2"      => 2.0,
-                   "21.1"   => 21.1,
-                   "2,1"    => 2.1,
-                   "1,5h"   => 1.5,
-                   "7:12"   => 7.2,
-                   "10h"    => 10.0,
-                   "10 h"   => 10.0,
-                   "45m"    => 0.75,
-                   "45 m"   => 0.75,
-                   "3h15"   => 3.25,
-                   "3h 15"  => 3.25,
-                   "3 h 15"   => 3.25,
-                   "3 h 15m"  => 3.25,
-                   "3 h 15 m" => 3.25,
-                   "3 hours"  => 3.0,
-                   "12min"    => 0.2,
-                   "12 Min"    => 0.2,
-                  }
-
-    assertions.each do |k, v|
-      t = TimeEntry.new(:hours => k)
-      assert_equal v, t.hours, "Converting #{k} failed:"
-    end
-  end
-
-  def test_hours_should_default_to_nil
-    assert_nil TimeEntry.new.hours
-  end
-
-  def test_spent_on_with_blank
-    c = TimeEntry.new
-    c.spent_on = ''
-    assert_nil c.spent_on
-  end
-
-  def test_spent_on_with_nil
-    c = TimeEntry.new
-    c.spent_on = nil
-    assert_nil c.spent_on
-  end
-
-  def test_spent_on_with_string
-    c = TimeEntry.new
-    c.spent_on = "2011-01-14"
-    assert_equal Date.parse("2011-01-14"), c.spent_on
-  end
-
-  def test_spent_on_with_invalid_string
-    c = TimeEntry.new
-    c.spent_on = "foo"
-    assert_nil c.spent_on
-  end
-
-  def test_spent_on_with_date
-    c = TimeEntry.new
-    c.spent_on = Date.today
-    assert_equal Date.today, c.spent_on
-  end
-
-  def test_spent_on_with_time
-    c = TimeEntry.new
-    c.spent_on = Time.now
-    assert_equal Date.today, c.spent_on
-  end
-
-  def test_validate_time_entry
-    anon     = User.anonymous
-    project  = Project.find(1)
-    issue    = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => anon.id, :status_id => 1,
-                         :priority => IssuePriority.all.first, :subject => 'test_create',
-                         :description => 'IssueTest#test_create', :estimated_hours => '1:30')
-    assert issue.save
-    activity = TimeEntryActivity.find_by_name('Design')
-    te = TimeEntry.create(:spent_on => '2010-01-01',
-                          :hours    => 100000,
-                          :issue    => issue,
-                          :project  => project,
-                          :user     => anon,
-                          :activity => activity)
-    assert_equal 1, te.errors.count
-  end
-
-  def test_spent_on_with_2_digits_year_should_not_be_valid
-    entry = TimeEntry.new(:project => Project.find(1), :user => User.find(1), :activity => TimeEntryActivity.first, :hours => 1)
-    entry.spent_on = "09-02-04"
-    assert !entry.valid?
-    assert_include I18n.translate('activerecord.errors.messages.not_a_date'), entry.errors[:spent_on]
-  end
-
-  def test_set_project_if_nil
-    anon     = User.anonymous
-    project  = Project.find(1)
-    issue    = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => anon.id, :status_id => 1,
-                         :priority => IssuePriority.all.first, :subject => 'test_create',
-                         :description => 'IssueTest#test_create', :estimated_hours => '1:30')
-    assert issue.save
-    activity = TimeEntryActivity.find_by_name('Design')
-    te = TimeEntry.create(:spent_on => '2010-01-01',
-                          :hours    => 10,
-                          :issue    => issue,
-                          :user     => anon,
-                          :activity => activity)
-    assert_equal project.id, te.project.id
-  end
-end
--- a/.svn/pristine/8c/8c56aede35efde6338d434d4d231eb2b6c6fcfdd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'net/imap'
-
-module Redmine
-  module IMAP
-    class << self
-      def check(imap_options={}, options={})
-        host = imap_options[:host] || '127.0.0.1'
-        port = imap_options[:port] || '143'
-        ssl = !imap_options[:ssl].nil?
-        folder = imap_options[:folder] || 'INBOX'
-
-        imap = Net::IMAP.new(host, port, ssl)
-        imap.login(imap_options[:username], imap_options[:password]) unless imap_options[:username].nil?
-        imap.select(folder)
-        imap.uid_search(['NOT', 'SEEN']).each do |uid|
-          msg = imap.uid_fetch(uid,'RFC822')[0].attr['RFC822']
-          logger.debug "Receiving message #{uid}" if logger && logger.debug?
-          if MailHandler.receive(msg, options)
-            logger.debug "Message #{uid} successfully received" if logger && logger.debug?
-            if imap_options[:move_on_success]
-              imap.uid_copy(uid, imap_options[:move_on_success])
-            end
-            imap.uid_store(uid, "+FLAGS", [:Seen, :Deleted])
-          else
-            logger.debug "Message #{uid} can not be processed" if logger && logger.debug?
-            imap.uid_store(uid, "+FLAGS", [:Seen])
-            if imap_options[:move_on_failure]
-              imap.uid_copy(uid, imap_options[:move_on_failure])
-              imap.uid_store(uid, "+FLAGS", [:Deleted])
-            end
-          end
-        end
-        imap.expunge
-        imap.logout
-        imap.disconnect
-      end
-
-      private
-
-      def logger
-        ::Rails.logger
-      end
-    end
-  end
-end
--- a/.svn/pristine/8c/8cbb18f9615aba75e56d4a85191eb4770033c6ee.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module WikiFormatting
-    module Textile
-      module Helper
-        def wikitoolbar_for(field_id)
-          heads_for_wiki_formatter
-          # Is there a simple way to link to a public resource?
-          url = "#{Redmine::Utils.relative_url_root}/help/#{current_language.to_s.downcase}/wiki_syntax.html"
-          javascript_tag("var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); wikiToolbar.setHelpLink('#{escape_javascript url}'); wikiToolbar.draw();")
-        end
-
-        def initial_page_content(page)
-          "h1. #{@page.pretty_title}"
-        end
-
-        def heads_for_wiki_formatter
-          unless @heads_for_wiki_formatter_included
-            content_for :header_tags do
-              javascript_include_tag('jstoolbar/jstoolbar-textile.min') +
-              javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language.to_s.downcase}") +
-              stylesheet_link_tag('jstoolbar')
-            end
-            @heads_for_wiki_formatter_included = true
-          end
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/8d/8d49dae3dcbe3c33e8ba68468bf87f82d0d0b226.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class MembersControllerTest < ActionController::TestCase
-  fixtures :projects, :members, :member_roles, :roles, :users
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 2
-  end
-
-  def test_create
-    assert_difference 'Member.count' do
-      post :create, :project_id => 1, :membership => {:role_ids => [1], :user_id => 7}
-    end
-    assert_redirected_to '/projects/ecookbook/settings/members'
-    assert User.find(7).member_of?(Project.find(1))
-  end
-
-  def test_create_multiple
-    assert_difference 'Member.count', 3 do
-      post :create, :project_id => 1, :membership => {:role_ids => [1], :user_ids => [7, 8, 9]}
-    end
-    assert_redirected_to '/projects/ecookbook/settings/members'
-    assert User.find(7).member_of?(Project.find(1))
-  end
-
-  def test_xhr_create
-    assert_difference 'Member.count', 3 do
-      xhr :post, :create, :project_id => 1, :membership => {:role_ids => [1], :user_ids => [7, 8, 9]}
-      assert_response :success
-      assert_template 'create'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert User.find(7).member_of?(Project.find(1))
-    assert User.find(8).member_of?(Project.find(1))
-    assert User.find(9).member_of?(Project.find(1))
-    assert_include 'tab-content-members', response.body
-  end
-
-  def test_xhr_create_with_failure
-    assert_no_difference 'Member.count' do
-      xhr :post, :create, :project_id => 1, :membership => {:role_ids => [], :user_ids => [7, 8, 9]}
-      assert_response :success
-      assert_template 'create'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_match /alert/, response.body, "Alert message not sent"
-  end
-
-  def test_edit
-    assert_no_difference 'Member.count' do
-      put :update, :id => 2, :membership => {:role_ids => [1], :user_id => 3}
-    end
-    assert_redirected_to '/projects/ecookbook/settings/members'
-  end
-
-  def test_xhr_edit
-    assert_no_difference 'Member.count' do
-      xhr :put, :update, :id => 2, :membership => {:role_ids => [1], :user_id => 3}
-      assert_response :success
-      assert_template 'update'
-      assert_equal 'text/javascript', response.content_type
-    end
-    member = Member.find(2)
-    assert_equal [1], member.role_ids
-    assert_equal 3, member.user_id
-    assert_include 'tab-content-members', response.body
-  end
-
-  def test_destroy
-    assert_difference 'Member.count', -1 do
-      delete :destroy, :id => 2
-    end
-    assert_redirected_to '/projects/ecookbook/settings/members'
-    assert !User.find(3).member_of?(Project.find(1))
-  end
-
-  def test_xhr_destroy
-    assert_difference 'Member.count', -1 do
-      xhr :delete, :destroy, :id => 2
-      assert_response :success
-      assert_template 'destroy'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_nil Member.find_by_id(2)
-    assert_include 'tab-content-members', response.body
-  end
-
-  def test_autocomplete
-    get :autocomplete, :project_id => 1, :q => 'mis', :format => 'js'
-    assert_response :success
-    assert_include 'User Misc', response.body
-  end
-end
--- a/.svn/pristine/8e/8e8e8287a74b0335843089c614a9c33ed22e75db.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueCategoryTest < ActiveSupport::TestCase
-  fixtures :issue_categories, :issues, :users, :groups_users
-
-  def setup
-    @category = IssueCategory.find(1)
-  end
-
-  def test_create
-    assert IssueCategory.new(:project_id => 2, :name => 'New category').save
-    category = IssueCategory.first(:order => 'id DESC')
-    assert_equal 'New category', category.name
-  end
-
-  def test_create_with_group_assignment
-    assert IssueCategory.new(:project_id => 2, :name => 'Group assignment', :assigned_to_id => 11).save
-    category = IssueCategory.first(:order => 'id DESC')
-    assert_kind_of Group, category.assigned_to
-    assert_equal Group.find(11), category.assigned_to
-  end
-
-  def test_destroy
-    issue = @category.issues.first
-    @category.destroy
-    # Make sure the category was nullified on the issue
-    assert_nil issue.reload.category
-  end
-
-  def test_destroy_with_reassign
-    issue = @category.issues.first
-    reassign_to = IssueCategory.find(2)
-    @category.destroy(reassign_to)
-    # Make sure the issue was reassigned
-    assert_equal reassign_to, issue.reload.category
-  end
-end
--- a/.svn/pristine/8e/8ea06d22d8f2b1998d7e2d84f7804f12208c49ad.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module ContextMenusHelper
-  def context_menu_link(name, url, options={})
-    options[:class] ||= ''
-    if options.delete(:selected)
-      options[:class] << ' icon-checked disabled'
-      options[:disabled] = true
-    end
-    if options.delete(:disabled)
-      options.delete(:method)
-      options.delete(:data)
-      options[:onclick] = 'return false;'
-      options[:class] << ' disabled'
-      url = '#'
-    end
-    link_to h(name), url, options
-  end
-
-  def bulk_update_custom_field_context_menu_link(field, text, value)
-    context_menu_link h(text),
-      bulk_update_issues_path(:ids => @issue_ids, :issue => {'custom_field_values' => {field.id => value}}, :back_url => @back),
-      :method => :post,
-      :selected => (@issue && @issue.custom_field_value(field) == value)
-  end
-end
--- a/.svn/pristine/8f/8f979a2960a289ab9a4542dc8883cce7d74526d2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1562 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Issue < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  include Redmine::Utils::DateCalculation
-  include Redmine::I18n
-
-  belongs_to :project
-  belongs_to :tracker
-  belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
-  belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
-  belongs_to :assigned_to, :class_name => 'Principal', :foreign_key => 'assigned_to_id'
-  belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
-  belongs_to :priority, :class_name => 'IssuePriority', :foreign_key => 'priority_id'
-  belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
-
-  has_many :journals, :as => :journalized, :dependent => :destroy
-  has_many :visible_journals,
-    :class_name => 'Journal',
-    :as => :journalized,
-    :conditions => Proc.new { 
-      ["(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(User.current, :view_private_notes)}))", false]
-    },
-    :readonly => true
-
-  has_many :time_entries, :dependent => :delete_all
-  has_and_belongs_to_many :changesets, :order => "#{Changeset.table_name}.committed_on ASC, #{Changeset.table_name}.id ASC"
-
-  has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all
-  has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
-
-  acts_as_nested_set :scope => 'root_id', :dependent => :destroy
-  acts_as_attachable :after_add => :attachment_added, :after_remove => :attachment_removed
-  acts_as_customizable
-  acts_as_watchable
-  acts_as_searchable :columns => ['subject', "#{table_name}.description", "#{Journal.table_name}.notes"],
-                     :include => [:project, :visible_journals],
-                     # sort by id so that limited eager loading doesn't break with postgresql
-                     :order_column => "#{table_name}.id"
-  acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id} (#{o.status}): #{o.subject}"},
-                :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}},
-                :type => Proc.new {|o| 'issue' + (o.closed? ? ' closed' : '') }
-
-  acts_as_activity_provider :find_options => {:include => [:project, :author, :tracker]},
-                            :author_key => :author_id
-
-  DONE_RATIO_OPTIONS = %w(issue_field issue_status)
-
-  attr_reader :current_journal
-  delegate :notes, :notes=, :private_notes, :private_notes=, :to => :current_journal, :allow_nil => true
-
-  validates_presence_of :subject, :priority, :project, :tracker, :author, :status
-
-  validates_length_of :subject, :maximum => 255
-  validates_inclusion_of :done_ratio, :in => 0..100
-  validates :estimated_hours, :numericality => {:greater_than_or_equal_to => 0, :allow_nil => true, :message => :invalid}
-  validates :start_date, :date => true
-  validates :due_date, :date => true
-  validate :validate_issue, :validate_required_fields
-
-  scope :visible, lambda {|*args|
-    includes(:project).where(Issue.visible_condition(args.shift || User.current, *args))
-  }
-
-  scope :open, lambda {|*args|
-    is_closed = args.size > 0 ? !args.first : false
-    includes(:status).where("#{IssueStatus.table_name}.is_closed = ?", is_closed)
-  }
-
-  scope :recently_updated, lambda { order("#{Issue.table_name}.updated_on DESC") }
-  scope :on_active_project, lambda {
-    includes(:status, :project, :tracker).where("#{Project.table_name}.status = ?", Project::STATUS_ACTIVE)
-  }
-  scope :fixed_version, lambda {|versions|
-    ids = [versions].flatten.compact.map {|v| v.is_a?(Version) ? v.id : v}
-    ids.any? ? where(:fixed_version_id => ids) : where('1=0')
-  }
-
-  before_create :default_assign
-  before_save :close_duplicates, :update_done_ratio_from_issue_status,
-              :force_updated_on_change, :update_closed_on, :set_assigned_to_was
-  after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?} 
-  after_save :reschedule_following_issues, :update_nested_set_attributes,
-             :update_parent_attributes, :create_journal
-  # Should be after_create but would be called before previous after_save callbacks
-  after_save :after_create_from_copy
-  after_destroy :update_parent_attributes
-  after_create :send_notification
-  # Keep it at the end of after_save callbacks
-  after_save :clear_assigned_to_was
-
-  # Returns a SQL conditions string used to find all issues visible by the specified user
-  def self.visible_condition(user, options={})
-    Project.allowed_to_condition(user, :view_issues, options) do |role, user|
-      if user.logged?
-        case role.issues_visibility
-        when 'all'
-          nil
-        when 'default'
-          user_ids = [user.id] + user.groups.map(&:id).compact
-          "(#{table_name}.is_private = #{connection.quoted_false} OR #{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
-        when 'own'
-          user_ids = [user.id] + user.groups.map(&:id).compact
-          "(#{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
-        else
-          '1=0'
-        end
-      else
-        "(#{table_name}.is_private = #{connection.quoted_false})"
-      end
-    end
-  end
-
-  # Returns true if usr or current user is allowed to view the issue
-  def visible?(usr=nil)
-    (usr || User.current).allowed_to?(:view_issues, self.project) do |role, user|
-      if user.logged?
-        case role.issues_visibility
-        when 'all'
-          true
-        when 'default'
-          !self.is_private? || (self.author == user || user.is_or_belongs_to?(assigned_to))
-        when 'own'
-          self.author == user || user.is_or_belongs_to?(assigned_to)
-        else
-          false
-        end
-      else
-        !self.is_private?
-      end
-    end
-  end
-
-  # Returns true if user or current user is allowed to edit or add a note to the issue
-  def editable?(user=User.current)
-    user.allowed_to?(:edit_issues, project) || user.allowed_to?(:add_issue_notes, project)
-  end
-
-  def initialize(attributes=nil, *args)
-    super
-    if new_record?
-      # set default values for new records only
-      self.status ||= IssueStatus.default
-      self.priority ||= IssuePriority.default
-      self.watcher_user_ids = []
-    end
-  end
-
-  def create_or_update
-    super
-  ensure
-    @status_was = nil
-  end
-  private :create_or_update
-
-  # AR#Persistence#destroy would raise and RecordNotFound exception
-  # if the issue was already deleted or updated (non matching lock_version).
-  # This is a problem when bulk deleting issues or deleting a project
-  # (because an issue may already be deleted if its parent was deleted
-  # first).
-  # The issue is reloaded by the nested_set before being deleted so
-  # the lock_version condition should not be an issue but we handle it.
-  def destroy
-    super
-  rescue ActiveRecord::RecordNotFound
-    # Stale or already deleted
-    begin
-      reload
-    rescue ActiveRecord::RecordNotFound
-      # The issue was actually already deleted
-      @destroyed = true
-      return freeze
-    end
-    # The issue was stale, retry to destroy
-    super
-  end
-
-  alias :base_reload :reload
-  def reload(*args)
-    @workflow_rule_by_attribute = nil
-    @assignable_versions = nil
-    @relations = nil
-    base_reload(*args)
-  end
-
-  # Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
-  def available_custom_fields
-    (project && tracker) ? (project.all_issue_custom_fields & tracker.custom_fields.all) : []
-  end
-
-  def visible_custom_field_values(user=nil)
-    user_real = user || User.current
-    custom_field_values.select do |value|
-      value.custom_field.visible_by?(project, user_real)
-    end
-  end
-
-  # Copies attributes from another issue, arg can be an id or an Issue
-  def copy_from(arg, options={})
-    issue = arg.is_a?(Issue) ? arg : Issue.visible.find(arg)
-    self.attributes = issue.attributes.dup.except("id", "root_id", "parent_id", "lft", "rgt", "created_on", "updated_on")
-    self.custom_field_values = issue.custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
-    self.status = issue.status
-    self.author = User.current
-    unless options[:attachments] == false
-      self.attachments = issue.attachments.map do |attachement| 
-        attachement.copy(:container => self)
-      end
-    end
-    @copied_from = issue
-    @copy_options = options
-    self
-  end
-
-  # Returns an unsaved copy of the issue
-  def copy(attributes=nil, copy_options={})
-    copy = self.class.new.copy_from(self, copy_options)
-    copy.attributes = attributes if attributes
-    copy
-  end
-
-  # Returns true if the issue is a copy
-  def copy?
-    @copied_from.present?
-  end
-
-  # Moves/copies an issue to a new project and tracker
-  # Returns the moved/copied issue on success, false on failure
-  def move_to_project(new_project, new_tracker=nil, options={})
-    ActiveSupport::Deprecation.warn "Issue#move_to_project is deprecated, use #project= instead."
-
-    if options[:copy]
-      issue = self.copy
-    else
-      issue = self
-    end
-
-    issue.init_journal(User.current, options[:notes])
-
-    # Preserve previous behaviour
-    # #move_to_project doesn't change tracker automatically
-    issue.send :project=, new_project, true
-    if new_tracker
-      issue.tracker = new_tracker
-    end
-    # Allow bulk setting of attributes on the issue
-    if options[:attributes]
-      issue.attributes = options[:attributes]
-    end
-
-    issue.save ? issue : false
-  end
-
-  def status_id=(sid)
-    self.status = nil
-    result = write_attribute(:status_id, sid)
-    @workflow_rule_by_attribute = nil
-    result
-  end
-
-  def priority_id=(pid)
-    self.priority = nil
-    write_attribute(:priority_id, pid)
-  end
-
-  def category_id=(cid)
-    self.category = nil
-    write_attribute(:category_id, cid)
-  end
-
-  def fixed_version_id=(vid)
-    self.fixed_version = nil
-    write_attribute(:fixed_version_id, vid)
-  end
-
-  def tracker_id=(tid)
-    self.tracker = nil
-    result = write_attribute(:tracker_id, tid)
-    @custom_field_values = nil
-    @workflow_rule_by_attribute = nil
-    result
-  end
-
-  def project_id=(project_id)
-    if project_id.to_s != self.project_id.to_s
-      self.project = (project_id.present? ? Project.find_by_id(project_id) : nil)
-    end
-  end
-
-  def project=(project, keep_tracker=false)
-    project_was = self.project
-    write_attribute(:project_id, project ? project.id : nil)
-    association_instance_set('project', project)
-    if project_was && project && project_was != project
-      @assignable_versions = nil
-
-      unless keep_tracker || project.trackers.include?(tracker)
-        self.tracker = project.trackers.first
-      end
-      # Reassign to the category with same name if any
-      if category
-        self.category = project.issue_categories.find_by_name(category.name)
-      end
-      # Keep the fixed_version if it's still valid in the new_project
-      if fixed_version && fixed_version.project != project && !project.shared_versions.include?(fixed_version)
-        self.fixed_version = nil
-      end
-      # Clear the parent task if it's no longer valid
-      unless valid_parent_project?
-        self.parent_issue_id = nil
-      end
-      @custom_field_values = nil
-    end
-  end
-
-  def description=(arg)
-    if arg.is_a?(String)
-      arg = arg.gsub(/(\r\n|\n|\r)/, "\r\n")
-    end
-    write_attribute(:description, arg)
-  end
-
-  # Overrides assign_attributes so that project and tracker get assigned first
-  def assign_attributes_with_project_and_tracker_first(new_attributes, *args)
-    return if new_attributes.nil?
-    attrs = new_attributes.dup
-    attrs.stringify_keys!
-
-    %w(project project_id tracker tracker_id).each do |attr|
-      if attrs.has_key?(attr)
-        send "#{attr}=", attrs.delete(attr)
-      end
-    end
-    send :assign_attributes_without_project_and_tracker_first, attrs, *args
-  end
-  # Do not redefine alias chain on reload (see #4838)
-  alias_method_chain(:assign_attributes, :project_and_tracker_first) unless method_defined?(:assign_attributes_without_project_and_tracker_first)
-
-  def estimated_hours=(h)
-    write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h)
-  end
-
-  safe_attributes 'project_id',
-    :if => lambda {|issue, user|
-      if issue.new_record?
-        issue.copy?
-      elsif user.allowed_to?(:move_issues, issue.project)
-        Issue.allowed_target_projects_on_move.count > 1
-      end
-    }
-
-  safe_attributes 'tracker_id',
-    'status_id',
-    'category_id',
-    'assigned_to_id',
-    'priority_id',
-    'fixed_version_id',
-    'subject',
-    'description',
-    'start_date',
-    'due_date',
-    'done_ratio',
-    'estimated_hours',
-    'custom_field_values',
-    'custom_fields',
-    'lock_version',
-    'notes',
-    :if => lambda {|issue, user| issue.new_record? || user.allowed_to?(:edit_issues, issue.project) }
-
-  safe_attributes 'status_id',
-    'assigned_to_id',
-    'fixed_version_id',
-    'done_ratio',
-    'lock_version',
-    'notes',
-    :if => lambda {|issue, user| issue.new_statuses_allowed_to(user).any? }
-
-  safe_attributes 'notes',
-    :if => lambda {|issue, user| user.allowed_to?(:add_issue_notes, issue.project)}
-
-  safe_attributes 'private_notes',
-    :if => lambda {|issue, user| !issue.new_record? && user.allowed_to?(:set_notes_private, issue.project)} 
-
-  safe_attributes 'watcher_user_ids',
-    :if => lambda {|issue, user| issue.new_record? && user.allowed_to?(:add_issue_watchers, issue.project)} 
-
-  safe_attributes 'is_private',
-    :if => lambda {|issue, user|
-      user.allowed_to?(:set_issues_private, issue.project) ||
-        (issue.author == user && user.allowed_to?(:set_own_issues_private, issue.project))
-    }
-
-  safe_attributes 'parent_issue_id',
-    :if => lambda {|issue, user| (issue.new_record? || user.allowed_to?(:edit_issues, issue.project)) &&
-      user.allowed_to?(:manage_subtasks, issue.project)}
-
-  def safe_attribute_names(user=nil)
-    names = super
-    names -= disabled_core_fields
-    names -= read_only_attribute_names(user)
-    names
-  end
-
-  # Safely sets attributes
-  # Should be called from controllers instead of #attributes=
-  # attr_accessible is too rough because we still want things like
-  # Issue.new(:project => foo) to work
-  def safe_attributes=(attrs, user=User.current)
-    return unless attrs.is_a?(Hash)
-
-    attrs = attrs.dup
-
-    # Project and Tracker must be set before since new_statuses_allowed_to depends on it.
-    if (p = attrs.delete('project_id')) && safe_attribute?('project_id')
-      if allowed_target_projects(user).where(:id => p.to_i).exists?
-        self.project_id = p
-      end
-    end
-
-    if (t = attrs.delete('tracker_id')) && safe_attribute?('tracker_id')
-      self.tracker_id = t
-    end
-
-    if (s = attrs.delete('status_id')) && safe_attribute?('status_id')
-      if new_statuses_allowed_to(user).collect(&:id).include?(s.to_i)
-        self.status_id = s
-      end
-    end
-
-    attrs = delete_unsafe_attributes(attrs, user)
-    return if attrs.empty?
-
-    unless leaf?
-      attrs.reject! {|k,v| %w(priority_id done_ratio start_date due_date estimated_hours).include?(k)}
-    end
-
-    if attrs['parent_issue_id'].present?
-      s = attrs['parent_issue_id'].to_s
-      unless (m = s.match(%r{\A#?(\d+)\z})) && (m[1] == parent_id.to_s || Issue.visible(user).exists?(m[1]))
-        @invalid_parent_issue_id = attrs.delete('parent_issue_id')
-      end
-    end
-
-    if attrs['custom_field_values'].present?
-      editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s}
-      # TODO: use #select when ruby1.8 support is dropped
-      attrs['custom_field_values'] = attrs['custom_field_values'].reject {|k, v| !editable_custom_field_ids.include?(k.to_s)}
-    end
-
-    if attrs['custom_fields'].present?
-      editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s}
-      # TODO: use #select when ruby1.8 support is dropped
-      attrs['custom_fields'] = attrs['custom_fields'].reject {|c| !editable_custom_field_ids.include?(c['id'].to_s)}
-    end
-
-    # mass-assignment security bypass
-    assign_attributes attrs, :without_protection => true
-  end
-
-  def disabled_core_fields
-    tracker ? tracker.disabled_core_fields : []
-  end
-
-  # Returns the custom_field_values that can be edited by the given user
-  def editable_custom_field_values(user=nil)
-    visible_custom_field_values(user).reject do |value|
-      read_only_attribute_names(user).include?(value.custom_field_id.to_s)
-    end
-  end
-
-  # Returns the names of attributes that are read-only for user or the current user
-  # For users with multiple roles, the read-only fields are the intersection of
-  # read-only fields of each role
-  # The result is an array of strings where sustom fields are represented with their ids
-  #
-  # Examples:
-  #   issue.read_only_attribute_names # => ['due_date', '2']
-  #   issue.read_only_attribute_names(user) # => []
-  def read_only_attribute_names(user=nil)
-    workflow_rule_by_attribute(user).reject {|attr, rule| rule != 'readonly'}.keys
-  end
-
-  # Returns the names of required attributes for user or the current user
-  # For users with multiple roles, the required fields are the intersection of
-  # required fields of each role
-  # The result is an array of strings where sustom fields are represented with their ids
-  #
-  # Examples:
-  #   issue.required_attribute_names # => ['due_date', '2']
-  #   issue.required_attribute_names(user) # => []
-  def required_attribute_names(user=nil)
-    workflow_rule_by_attribute(user).reject {|attr, rule| rule != 'required'}.keys
-  end
-
-  # Returns true if the attribute is required for user
-  def required_attribute?(name, user=nil)
-    required_attribute_names(user).include?(name.to_s)
-  end
-
-  # Returns a hash of the workflow rule by attribute for the given user
-  #
-  # Examples:
-  #   issue.workflow_rule_by_attribute # => {'due_date' => 'required', 'start_date' => 'readonly'}
-  def workflow_rule_by_attribute(user=nil)
-    return @workflow_rule_by_attribute if @workflow_rule_by_attribute && user.nil?
-
-    user_real = user || User.current
-    roles = user_real.admin ? Role.all : user_real.roles_for_project(project)
-    return {} if roles.empty?
-
-    result = {}
-    workflow_permissions = WorkflowPermission.where(:tracker_id => tracker_id, :old_status_id => status_id, :role_id => roles.map(&:id)).all
-    if workflow_permissions.any?
-      workflow_rules = workflow_permissions.inject({}) do |h, wp|
-        h[wp.field_name] ||= []
-        h[wp.field_name] << wp.rule
-        h
-      end
-      workflow_rules.each do |attr, rules|
-        next if rules.size < roles.size
-        uniq_rules = rules.uniq
-        if uniq_rules.size == 1
-          result[attr] = uniq_rules.first
-        else
-          result[attr] = 'required'
-        end
-      end
-    end
-    @workflow_rule_by_attribute = result if user.nil?
-    result
-  end
-  private :workflow_rule_by_attribute
-
-  def done_ratio
-    if Issue.use_status_for_done_ratio? && status && status.default_done_ratio
-      status.default_done_ratio
-    else
-      read_attribute(:done_ratio)
-    end
-  end
-
-  def self.use_status_for_done_ratio?
-    Setting.issue_done_ratio == 'issue_status'
-  end
-
-  def self.use_field_for_done_ratio?
-    Setting.issue_done_ratio == 'issue_field'
-  end
-
-  def validate_issue
-    if due_date && start_date && (start_date_changed? || due_date_changed?) && due_date < start_date
-      errors.add :due_date, :greater_than_start_date
-    end
-
-    if start_date && start_date_changed? && soonest_start && start_date < soonest_start
-      errors.add :start_date, :earlier_than_minimum_start_date, :date => format_date(soonest_start)
-    end
-
-    if fixed_version
-      if !assignable_versions.include?(fixed_version)
-        errors.add :fixed_version_id, :inclusion
-      elsif reopened? && fixed_version.closed?
-        errors.add :base, I18n.t(:error_can_not_reopen_issue_on_closed_version)
-      end
-    end
-
-    # Checks that the issue can not be added/moved to a disabled tracker
-    if project && (tracker_id_changed? || project_id_changed?)
-      unless project.trackers.include?(tracker)
-        errors.add :tracker_id, :inclusion
-      end
-    end
-
-    # Checks parent issue assignment
-    if @invalid_parent_issue_id.present?
-      errors.add :parent_issue_id, :invalid
-    elsif @parent_issue
-      if !valid_parent_project?(@parent_issue)
-        errors.add :parent_issue_id, :invalid
-      elsif (@parent_issue != parent) && (all_dependent_issues.include?(@parent_issue) || @parent_issue.all_dependent_issues.include?(self))
-        errors.add :parent_issue_id, :invalid
-      elsif !new_record?
-        # moving an existing issue
-        if @parent_issue.root_id != root_id
-          # we can always move to another tree
-        elsif move_possible?(@parent_issue)
-          # move accepted inside tree
-        else
-          errors.add :parent_issue_id, :invalid
-        end
-      end
-    end
-  end
-
-  # Validates the issue against additional workflow requirements
-  def validate_required_fields
-    user = new_record? ? author : current_journal.try(:user)
-
-    required_attribute_names(user).each do |attribute|
-      if attribute =~ /^\d+$/
-        attribute = attribute.to_i
-        v = custom_field_values.detect {|v| v.custom_field_id == attribute }
-        if v && v.value.blank?
-          errors.add :base, v.custom_field.name + ' ' + l('activerecord.errors.messages.blank')
-        end
-      else
-        if respond_to?(attribute) && send(attribute).blank?
-          errors.add attribute, :blank
-        end
-      end
-    end
-  end
-
-  # Set the done_ratio using the status if that setting is set.  This will keep the done_ratios
-  # even if the user turns off the setting later
-  def update_done_ratio_from_issue_status
-    if Issue.use_status_for_done_ratio? && status && status.default_done_ratio
-      self.done_ratio = status.default_done_ratio
-    end
-  end
-
-  def init_journal(user, notes = "")
-    @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes)
-    if new_record?
-      @current_journal.notify = false
-    else
-      @attributes_before_change = attributes.dup
-      @custom_values_before_change = {}
-      self.custom_field_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
-    end
-    @current_journal
-  end
-
-  # Returns the id of the last journal or nil
-  def last_journal_id
-    if new_record?
-      nil
-    else
-      journals.maximum(:id)
-    end
-  end
-
-  # Returns a scope for journals that have an id greater than journal_id
-  def journals_after(journal_id)
-    scope = journals.reorder("#{Journal.table_name}.id ASC")
-    if journal_id.present?
-      scope = scope.where("#{Journal.table_name}.id > ?", journal_id.to_i)
-    end
-    scope
-  end
-
-  # Returns the initial status of the issue
-  # Returns nil for a new issue
-  def status_was
-    if status_id_was && status_id_was.to_i > 0
-      @status_was ||= IssueStatus.find_by_id(status_id_was)
-    end
-  end
-
-  # Return true if the issue is closed, otherwise false
-  def closed?
-    self.status.is_closed?
-  end
-
-  # Return true if the issue is being reopened
-  def reopened?
-    if !new_record? && status_id_changed?
-      status_was = IssueStatus.find_by_id(status_id_was)
-      status_new = IssueStatus.find_by_id(status_id)
-      if status_was && status_new && status_was.is_closed? && !status_new.is_closed?
-        return true
-      end
-    end
-    false
-  end
-
-  # Return true if the issue is being closed
-  def closing?
-    if !new_record? && status_id_changed?
-      if status_was && status && !status_was.is_closed? && status.is_closed?
-        return true
-      end
-    end
-    false
-  end
-
-  # Returns true if the issue is overdue
-  def overdue?
-    !due_date.nil? && (due_date < Date.today) && !status.is_closed?
-  end
-
-  # Is the amount of work done less than it should for the due date
-  def behind_schedule?
-    return false if start_date.nil? || due_date.nil?
-    done_date = start_date + ((due_date - start_date + 1) * done_ratio / 100).floor
-    return done_date <= Date.today
-  end
-
-  # Does this issue have children?
-  def children?
-    !leaf?
-  end
-
-  # Users the issue can be assigned to
-  def assignable_users
-    users = project.assignable_users
-    users << author if author
-    users << assigned_to if assigned_to
-    users.uniq.sort
-  end
-
-  # Versions that the issue can be assigned to
-  def assignable_versions
-    return @assignable_versions if @assignable_versions
-
-    versions = project.shared_versions.open.all
-    if fixed_version
-      if fixed_version_id_changed?
-        # nothing to do
-      elsif project_id_changed?
-        if project.shared_versions.include?(fixed_version)
-          versions << fixed_version
-        end
-      else
-        versions << fixed_version
-      end
-    end
-    @assignable_versions = versions.uniq.sort
-  end
-
-  # Returns true if this issue is blocked by another issue that is still open
-  def blocked?
-    !relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
-  end
-
-  # Returns an array of statuses that user is able to apply
-  def new_statuses_allowed_to(user=User.current, include_default=false)
-    if new_record? && @copied_from
-      [IssueStatus.default, @copied_from.status].compact.uniq.sort
-    else
-      initial_status = nil
-      if new_record?
-        initial_status = IssueStatus.default
-      elsif status_id_was
-        initial_status = IssueStatus.find_by_id(status_id_was)
-      end
-      initial_status ||= status
-
-      initial_assigned_to_id = assigned_to_id_changed? ? assigned_to_id_was : assigned_to_id
-      assignee_transitions_allowed = initial_assigned_to_id.present? && 
-        (user.id == initial_assigned_to_id || user.group_ids.include?(initial_assigned_to_id))
-
-      statuses = initial_status.find_new_statuses_allowed_to(
-        user.admin ? Role.all : user.roles_for_project(project),
-        tracker,
-        author == user,
-        assignee_transitions_allowed
-        )
-      statuses << initial_status unless statuses.empty?
-      statuses << IssueStatus.default if include_default
-      statuses = statuses.compact.uniq.sort
-      blocked? ? statuses.reject {|s| s.is_closed?} : statuses
-    end
-  end
-
-  # Returns the previous assignee if changed
-  def assigned_to_was
-    # assigned_to_id_was is reset before after_save callbacks
-    user_id = @previous_assigned_to_id || assigned_to_id_was
-    if user_id && user_id != assigned_to_id
-      @assigned_to_was ||= User.find_by_id(user_id)
-    end
-  end
-
-  # Returns the users that should be notified
-  def notified_users
-    notified = []
-    # Author and assignee are always notified unless they have been
-    # locked or don't want to be notified
-    notified << author if author
-    if assigned_to
-      notified += (assigned_to.is_a?(Group) ? assigned_to.users : [assigned_to])
-    end
-    if assigned_to_was
-      notified += (assigned_to_was.is_a?(Group) ? assigned_to_was.users : [assigned_to_was])
-    end
-    notified = notified.select {|u| u.active? && u.notify_about?(self)}
-
-    notified += project.notified_users
-    notified.uniq!
-    # Remove users that can not view the issue
-    notified.reject! {|user| !visible?(user)}
-    notified
-  end
-
-  # Returns the email addresses that should be notified
-  def recipients
-    notified_users.collect(&:mail)
-  end
-
-  def each_notification(users, &block)
-    if users.any?
-      if custom_field_values.detect {|value| !value.custom_field.visible?}
-        users_by_custom_field_visibility = users.group_by do |user|
-          visible_custom_field_values(user).map(&:custom_field_id).sort
-        end
-        users_by_custom_field_visibility.values.each do |users|
-          yield(users)
-        end
-      else
-        yield(users)
-      end
-    end
-  end
-
-  # Returns the number of hours spent on this issue
-  def spent_hours
-    @spent_hours ||= time_entries.sum(:hours) || 0
-  end
-
-  # Returns the total number of hours spent on this issue and its descendants
-  #
-  # Example:
-  #   spent_hours => 0.0
-  #   spent_hours => 50.2
-  def total_spent_hours
-    @total_spent_hours ||= self_and_descendants.sum("#{TimeEntry.table_name}.hours",
-      :joins => "LEFT JOIN #{TimeEntry.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id").to_f || 0.0
-  end
-
-  def relations
-    @relations ||= IssueRelation::Relations.new(self, (relations_from + relations_to).sort)
-  end
-
-  # Preloads relations for a collection of issues
-  def self.load_relations(issues)
-    if issues.any?
-      relations = IssueRelation.where("issue_from_id IN (:ids) OR issue_to_id IN (:ids)", :ids => issues.map(&:id)).all
-      issues.each do |issue|
-        issue.instance_variable_set "@relations", relations.select {|r| r.issue_from_id == issue.id || r.issue_to_id == issue.id}
-      end
-    end
-  end
-
-  # Preloads visible spent time for a collection of issues
-  def self.load_visible_spent_hours(issues, user=User.current)
-    if issues.any?
-      hours_by_issue_id = TimeEntry.visible(user).group(:issue_id).sum(:hours)
-      issues.each do |issue|
-        issue.instance_variable_set "@spent_hours", (hours_by_issue_id[issue.id] || 0)
-      end
-    end
-  end
-
-  # Preloads visible relations for a collection of issues
-  def self.load_visible_relations(issues, user=User.current)
-    if issues.any?
-      issue_ids = issues.map(&:id)
-      # Relations with issue_from in given issues and visible issue_to
-      relations_from = IssueRelation.includes(:issue_to => [:status, :project]).where(visible_condition(user)).where(:issue_from_id => issue_ids).all
-      # Relations with issue_to in given issues and visible issue_from
-      relations_to = IssueRelation.includes(:issue_from => [:status, :project]).where(visible_condition(user)).where(:issue_to_id => issue_ids).all
-
-      issues.each do |issue|
-        relations =
-          relations_from.select {|relation| relation.issue_from_id == issue.id} +
-          relations_to.select {|relation| relation.issue_to_id == issue.id}
-
-        issue.instance_variable_set "@relations", IssueRelation::Relations.new(issue, relations.sort)
-      end
-    end
-  end
-
-  # Finds an issue relation given its id.
-  def find_relation(relation_id)
-    IssueRelation.where("issue_to_id = ? OR issue_from_id = ?", id, id).find(relation_id)
-  end
-
-  # Returns all the other issues that depend on the issue
-  # The algorithm is a modified breadth first search (bfs)
-  def all_dependent_issues(except=[])
-    # The found dependencies
-    dependencies = []
-
-    # The visited flag for every node (issue) used by the breadth first search
-    eNOT_DISCOVERED         = 0       # The issue is "new" to the algorithm, it has not seen it before.
-
-    ePROCESS_ALL            = 1       # The issue is added to the queue. Process both children and relations of
-                                      # the issue when it is processed.
-
-    ePROCESS_RELATIONS_ONLY = 2       # The issue was added to the queue and will be output as dependent issue,
-                                      # but its children will not be added to the queue when it is processed.
-
-    eRELATIONS_PROCESSED    = 3       # The related issues, the parent issue and the issue itself have been added to
-                                      # the queue, but its children have not been added.
-
-    ePROCESS_CHILDREN_ONLY  = 4       # The relations and the parent of the issue have been added to the queue, but
-                                      # the children still need to be processed.
-
-    eALL_PROCESSED          = 5       # The issue and all its children, its parent and its related issues have been
-                                      # added as dependent issues. It needs no further processing.
-
-    issue_status = Hash.new(eNOT_DISCOVERED)
-
-    # The queue
-    queue = []
-
-    # Initialize the bfs, add start node (self) to the queue
-    queue << self
-    issue_status[self] = ePROCESS_ALL
-
-    while (!queue.empty?) do
-      current_issue = queue.shift
-      current_issue_status = issue_status[current_issue]
-      dependencies << current_issue
-
-      # Add parent to queue, if not already in it.
-      parent = current_issue.parent
-      parent_status = issue_status[parent]
-
-      if parent && (parent_status == eNOT_DISCOVERED) && !except.include?(parent)
-        queue << parent
-        issue_status[parent] = ePROCESS_RELATIONS_ONLY
-      end
-
-      # Add children to queue, but only if they are not already in it and
-      # the children of the current node need to be processed.
-      if (current_issue_status == ePROCESS_CHILDREN_ONLY || current_issue_status == ePROCESS_ALL)
-        current_issue.children.each do |child|
-          next if except.include?(child)
-
-          if (issue_status[child] == eNOT_DISCOVERED)
-            queue << child
-            issue_status[child] = ePROCESS_ALL
-          elsif (issue_status[child] == eRELATIONS_PROCESSED)
-            queue << child
-            issue_status[child] = ePROCESS_CHILDREN_ONLY
-          elsif (issue_status[child] == ePROCESS_RELATIONS_ONLY)
-            queue << child
-            issue_status[child] = ePROCESS_ALL
-          end
-        end
-      end
-
-      # Add related issues to the queue, if they are not already in it.
-      current_issue.relations_from.map(&:issue_to).each do |related_issue|
-        next if except.include?(related_issue)
-
-        if (issue_status[related_issue] == eNOT_DISCOVERED)
-          queue << related_issue
-          issue_status[related_issue] = ePROCESS_ALL
-        elsif (issue_status[related_issue] == eRELATIONS_PROCESSED)
-          queue << related_issue
-          issue_status[related_issue] = ePROCESS_CHILDREN_ONLY
-        elsif (issue_status[related_issue] == ePROCESS_RELATIONS_ONLY)
-          queue << related_issue
-          issue_status[related_issue] = ePROCESS_ALL
-        end
-      end
-
-      # Set new status for current issue
-      if (current_issue_status == ePROCESS_ALL) || (current_issue_status == ePROCESS_CHILDREN_ONLY)
-        issue_status[current_issue] = eALL_PROCESSED
-      elsif (current_issue_status == ePROCESS_RELATIONS_ONLY)
-        issue_status[current_issue] = eRELATIONS_PROCESSED
-      end
-    end # while
-
-    # Remove the issues from the "except" parameter from the result array
-    dependencies -= except
-    dependencies.delete(self)
-
-    dependencies
-  end
-
-  # Returns an array of issues that duplicate this one
-  def duplicates
-    relations_to.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.issue_from}
-  end
-
-  # Returns the due date or the target due date if any
-  # Used on gantt chart
-  def due_before
-    due_date || (fixed_version ? fixed_version.effective_date : nil)
-  end
-
-  # Returns the time scheduled for this issue.
-  #
-  # Example:
-  #   Start Date: 2/26/09, End Date: 3/04/09
-  #   duration => 6
-  def duration
-    (start_date && due_date) ? due_date - start_date : 0
-  end
-
-  # Returns the duration in working days
-  def working_duration
-    (start_date && due_date) ? working_days(start_date, due_date) : 0
-  end
-
-  def soonest_start(reload=false)
-    @soonest_start = nil if reload
-    @soonest_start ||= (
-        relations_to(reload).collect{|relation| relation.successor_soonest_start} +
-        [(@parent_issue || parent).try(:soonest_start)]
-      ).compact.max
-  end
-
-  # Sets start_date on the given date or the next working day
-  # and changes due_date to keep the same working duration.
-  def reschedule_on(date)
-    wd = working_duration
-    date = next_working_date(date)
-    self.start_date = date
-    self.due_date = add_working_days(date, wd)
-  end
-
-  # Reschedules the issue on the given date or the next working day and saves the record.
-  # If the issue is a parent task, this is done by rescheduling its subtasks.
-  def reschedule_on!(date)
-    return if date.nil?
-    if leaf?
-      if start_date.nil? || start_date != date
-        if start_date && start_date > date
-          # Issue can not be moved earlier than its soonest start date
-          date = [soonest_start(true), date].compact.max
-        end
-        reschedule_on(date)
-        begin
-          save
-        rescue ActiveRecord::StaleObjectError
-          reload
-          reschedule_on(date)
-          save
-        end
-      end
-    else
-      leaves.each do |leaf|
-        if leaf.start_date
-          # Only move subtask if it starts at the same date as the parent
-          # or if it starts before the given date
-          if start_date == leaf.start_date || date > leaf.start_date 
-            leaf.reschedule_on!(date)
-          end
-        else
-          leaf.reschedule_on!(date)
-        end
-      end
-    end
-  end
-
-  def <=>(issue)
-    if issue.nil?
-      -1
-    elsif root_id != issue.root_id
-      (root_id || 0) <=> (issue.root_id || 0)
-    else
-      (lft || 0) <=> (issue.lft || 0)
-    end
-  end
-
-  def to_s
-    "#{tracker} ##{id}: #{subject}"
-  end
-
-  # Returns a string of css classes that apply to the issue
-  def css_classes(user=User.current)
-    s = "issue tracker-#{tracker_id} status-#{status_id} #{priority.try(:css_classes)}"
-    s << ' closed' if closed?
-    s << ' overdue' if overdue?
-    s << ' child' if child?
-    s << ' parent' unless leaf?
-    s << ' private' if is_private?
-    if user.logged?
-      s << ' created-by-me' if author_id == user.id
-      s << ' assigned-to-me' if assigned_to_id == user.id
-      s << ' assigned-to-my-group' if user.groups.any? {|g| g.id = assigned_to_id}
-    end
-    s
-  end
-
-  # Unassigns issues from +version+ if it's no longer shared with issue's project
-  def self.update_versions_from_sharing_change(version)
-    # Update issues assigned to the version
-    update_versions(["#{Issue.table_name}.fixed_version_id = ?", version.id])
-  end
-
-  # Unassigns issues from versions that are no longer shared
-  # after +project+ was moved
-  def self.update_versions_from_hierarchy_change(project)
-    moved_project_ids = project.self_and_descendants.reload.collect(&:id)
-    # Update issues of the moved projects and issues assigned to a version of a moved project
-    Issue.update_versions(["#{Version.table_name}.project_id IN (?) OR #{Issue.table_name}.project_id IN (?)", moved_project_ids, moved_project_ids])
-  end
-
-  def parent_issue_id=(arg)
-    s = arg.to_s.strip.presence
-    if s && (m = s.match(%r{\A#?(\d+)\z})) && (@parent_issue = Issue.find_by_id(m[1]))
-      @parent_issue.id
-      @invalid_parent_issue_id = nil
-    elsif s.blank?
-      @parent_issue = nil
-      @invalid_parent_issue_id = nil
-    else
-      @parent_issue = nil
-      @invalid_parent_issue_id = arg
-    end
-  end
-
-  def parent_issue_id
-    if @invalid_parent_issue_id
-      @invalid_parent_issue_id
-    elsif instance_variable_defined? :@parent_issue
-      @parent_issue.nil? ? nil : @parent_issue.id
-    else
-      parent_id
-    end
-  end
-
-  # Returns true if issue's project is a valid
-  # parent issue project
-  def valid_parent_project?(issue=parent)
-    return true if issue.nil? || issue.project_id == project_id
-
-    case Setting.cross_project_subtasks
-    when 'system'
-      true
-    when 'tree'
-      issue.project.root == project.root
-    when 'hierarchy'
-      issue.project.is_or_is_ancestor_of?(project) || issue.project.is_descendant_of?(project)
-    when 'descendants'
-      issue.project.is_or_is_ancestor_of?(project)
-    else
-      false
-    end
-  end
-
-  # Extracted from the ReportsController.
-  def self.by_tracker(project)
-    count_and_group_by(:project => project,
-                       :field => 'tracker_id',
-                       :joins => Tracker.table_name)
-  end
-
-  def self.by_version(project)
-    count_and_group_by(:project => project,
-                       :field => 'fixed_version_id',
-                       :joins => Version.table_name)
-  end
-
-  def self.by_priority(project)
-    count_and_group_by(:project => project,
-                       :field => 'priority_id',
-                       :joins => IssuePriority.table_name)
-  end
-
-  def self.by_category(project)
-    count_and_group_by(:project => project,
-                       :field => 'category_id',
-                       :joins => IssueCategory.table_name)
-  end
-
-  def self.by_assigned_to(project)
-    count_and_group_by(:project => project,
-                       :field => 'assigned_to_id',
-                       :joins => User.table_name)
-  end
-
-  def self.by_author(project)
-    count_and_group_by(:project => project,
-                       :field => 'author_id',
-                       :joins => User.table_name)
-  end
-
-  def self.by_subproject(project)
-    ActiveRecord::Base.connection.select_all("select    s.id as status_id, 
-                                                s.is_closed as closed, 
-                                                #{Issue.table_name}.project_id as project_id,
-                                                count(#{Issue.table_name}.id) as total 
-                                              from 
-                                                #{Issue.table_name}, #{Project.table_name}, #{IssueStatus.table_name} s
-                                              where 
-                                                #{Issue.table_name}.status_id=s.id
-                                                and #{Issue.table_name}.project_id = #{Project.table_name}.id
-                                                and #{visible_condition(User.current, :project => project, :with_subprojects => true)}
-                                                and #{Issue.table_name}.project_id <> #{project.id}
-                                              group by s.id, s.is_closed, #{Issue.table_name}.project_id") if project.descendants.active.any?
-  end
-  # End ReportsController extraction
-
-  # Returns a scope of projects that user can assign the issue to
-  def allowed_target_projects(user=User.current)
-    if new_record?
-      Project.where(Project.allowed_to_condition(user, :add_issues))
-    else
-      self.class.allowed_target_projects_on_move(user)
-    end
-  end
-
-  # Returns a scope of projects that user can move issues to
-  def self.allowed_target_projects_on_move(user=User.current)
-    Project.where(Project.allowed_to_condition(user, :move_issues))
-  end
-
-  private
-
-  def after_project_change
-    # Update project_id on related time entries
-    TimeEntry.update_all(["project_id = ?", project_id], {:issue_id => id})
-
-    # Delete issue relations
-    unless Setting.cross_project_issue_relations?
-      relations_from.clear
-      relations_to.clear
-    end
-
-    # Move subtasks that were in the same project
-    children.each do |child|
-      next unless child.project_id == project_id_was
-      # Change project and keep project
-      child.send :project=, project, true
-      unless child.save
-        raise ActiveRecord::Rollback
-      end
-    end
-  end
-
-  # Callback for after the creation of an issue by copy
-  # * adds a "copied to" relation with the copied issue
-  # * copies subtasks from the copied issue
-  def after_create_from_copy
-    return unless copy? && !@after_create_from_copy_handled
-
-    if (@copied_from.project_id == project_id || Setting.cross_project_issue_relations?) && @copy_options[:link] != false
-      relation = IssueRelation.new(:issue_from => @copied_from, :issue_to => self, :relation_type => IssueRelation::TYPE_COPIED_TO)
-      unless relation.save
-        logger.error "Could not create relation while copying ##{@copied_from.id} to ##{id} due to validation errors: #{relation.errors.full_messages.join(', ')}" if logger
-      end
-    end
-
-    unless @copied_from.leaf? || @copy_options[:subtasks] == false
-      copy_options = (@copy_options || {}).merge(:subtasks => false)
-      copied_issue_ids = {@copied_from.id => self.id}
-      @copied_from.reload.descendants.reorder("#{Issue.table_name}.lft").each do |child|
-        # Do not copy self when copying an issue as a descendant of the copied issue
-        next if child == self
-        # Do not copy subtasks of issues that were not copied
-        next unless copied_issue_ids[child.parent_id]
-        # Do not copy subtasks that are not visible to avoid potential disclosure of private data
-        unless child.visible?
-          logger.error "Subtask ##{child.id} was not copied during ##{@copied_from.id} copy because it is not visible to the current user" if logger
-          next
-        end
-        copy = Issue.new.copy_from(child, copy_options)
-        copy.author = author
-        copy.project = project
-        copy.parent_issue_id = copied_issue_ids[child.parent_id]
-        unless copy.save
-          logger.error "Could not copy subtask ##{child.id} while copying ##{@copied_from.id} to ##{id} due to validation errors: #{copy.errors.full_messages.join(', ')}" if logger
-          next
-        end
-        copied_issue_ids[child.id] = copy.id
-      end
-    end
-    @after_create_from_copy_handled = true
-  end
-
-  def update_nested_set_attributes
-    if root_id.nil?
-      # issue was just created
-      self.root_id = (@parent_issue.nil? ? id : @parent_issue.root_id)
-      set_default_left_and_right
-      Issue.update_all(["root_id = ?, lft = ?, rgt = ?", root_id, lft, rgt], ["id = ?", id])
-      if @parent_issue
-        move_to_child_of(@parent_issue)
-      end
-    elsif parent_issue_id != parent_id
-      update_nested_set_attributes_on_parent_change
-    end
-    remove_instance_variable(:@parent_issue) if instance_variable_defined?(:@parent_issue)
-  end
-
-  # Updates the nested set for when an existing issue is moved
-  def update_nested_set_attributes_on_parent_change
-    former_parent_id = parent_id
-    # moving an existing issue
-    if @parent_issue && @parent_issue.root_id == root_id
-      # inside the same tree
-      move_to_child_of(@parent_issue)
-    else
-      # to another tree
-      unless root?
-        move_to_right_of(root)
-      end
-      old_root_id = root_id
-      self.root_id = (@parent_issue.nil? ? id : @parent_issue.root_id )
-      target_maxright = nested_set_scope.maximum(right_column_name) || 0
-      offset = target_maxright + 1 - lft
-      Issue.update_all(["root_id = ?, lft = lft + ?, rgt = rgt + ?", root_id, offset, offset],
-                        ["root_id = ? AND lft >= ? AND rgt <= ? ", old_root_id, lft, rgt])
-      self[left_column_name] = lft + offset
-      self[right_column_name] = rgt + offset
-      if @parent_issue
-        move_to_child_of(@parent_issue)
-      end
-    end
-    # delete invalid relations of all descendants
-    self_and_descendants.each do |issue|
-      issue.relations.each do |relation|
-        relation.destroy unless relation.valid?
-      end
-    end
-    # update former parent
-    recalculate_attributes_for(former_parent_id) if former_parent_id
-  end
-
-  def update_parent_attributes
-    recalculate_attributes_for(parent_id) if parent_id
-  end
-
-  def recalculate_attributes_for(issue_id)
-    if issue_id && p = Issue.find_by_id(issue_id)
-      # priority = highest priority of children
-      if priority_position = p.children.maximum("#{IssuePriority.table_name}.position", :joins => :priority)
-        p.priority = IssuePriority.find_by_position(priority_position)
-      end
-
-      # start/due dates = lowest/highest dates of children
-      p.start_date = p.children.minimum(:start_date)
-      p.due_date = p.children.maximum(:due_date)
-      if p.start_date && p.due_date && p.due_date < p.start_date
-        p.start_date, p.due_date = p.due_date, p.start_date
-      end
-
-      # done ratio = weighted average ratio of leaves
-      unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
-        leaves_count = p.leaves.count
-        if leaves_count > 0
-          average = p.leaves.average(:estimated_hours).to_f
-          if average == 0
-            average = 1
-          end
-          done = p.leaves.sum("COALESCE(CASE WHEN estimated_hours > 0 THEN estimated_hours ELSE NULL END, #{average}) " +
-			"* (CASE WHEN is_closed = #{connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)", :joins => :status).to_f
-          progress = done / (average * leaves_count)
-          p.done_ratio = progress.round
-        end
-      end
-
-      # estimate = sum of leaves estimates
-      p.estimated_hours = p.leaves.sum(:estimated_hours).to_f
-      p.estimated_hours = nil if p.estimated_hours == 0.0
-
-      # ancestors will be recursively updated
-      p.save(:validate => false)
-    end
-  end
-
-  # Update issues so their versions are not pointing to a
-  # fixed_version that is not shared with the issue's project
-  def self.update_versions(conditions=nil)
-    # Only need to update issues with a fixed_version from
-    # a different project and that is not systemwide shared
-    Issue.includes(:project, :fixed_version).
-      where("#{Issue.table_name}.fixed_version_id IS NOT NULL" +
-        " AND #{Issue.table_name}.project_id <> #{Version.table_name}.project_id" +
-        " AND #{Version.table_name}.sharing <> 'system'").
-      where(conditions).each do |issue|
-      next if issue.project.nil? || issue.fixed_version.nil?
-      unless issue.project.shared_versions.include?(issue.fixed_version)
-        issue.init_journal(User.current)
-        issue.fixed_version = nil
-        issue.save
-      end
-    end
-  end
-
-  # Callback on file attachment
-  def attachment_added(obj)
-    if @current_journal && !obj.new_record?
-      @current_journal.details << JournalDetail.new(:property => 'attachment', :prop_key => obj.id, :value => obj.filename)
-    end
-  end
-
-  # Callback on attachment deletion
-  def attachment_removed(obj)
-    if @current_journal && !obj.new_record?
-      @current_journal.details << JournalDetail.new(:property => 'attachment', :prop_key => obj.id, :old_value => obj.filename)
-      @current_journal.save
-    end
-  end
-
-  # Default assignment based on category
-  def default_assign
-    if assigned_to.nil? && category && category.assigned_to
-      self.assigned_to = category.assigned_to
-    end
-  end
-
-  # Updates start/due dates of following issues
-  def reschedule_following_issues
-    if start_date_changed? || due_date_changed?
-      relations_from.each do |relation|
-        relation.set_issue_to_dates
-      end
-    end
-  end
-
-  # Closes duplicates if the issue is being closed
-  def close_duplicates
-    if closing?
-      duplicates.each do |duplicate|
-        # Reload is need in case the duplicate was updated by a previous duplicate
-        duplicate.reload
-        # Don't re-close it if it's already closed
-        next if duplicate.closed?
-        # Same user and notes
-        if @current_journal
-          duplicate.init_journal(@current_journal.user, @current_journal.notes)
-        end
-        duplicate.update_attribute :status, self.status
-      end
-    end
-  end
-
-  # Make sure updated_on is updated when adding a note and set updated_on now
-  # so we can set closed_on with the same value on closing
-  def force_updated_on_change
-    if @current_journal || changed?
-      self.updated_on = current_time_from_proper_timezone
-      if new_record?
-        self.created_on = updated_on
-      end
-    end
-  end
-
-  # Callback for setting closed_on when the issue is closed.
-  # The closed_on attribute stores the time of the last closing
-  # and is preserved when the issue is reopened.
-  def update_closed_on
-    if closing? || (new_record? && closed?)
-      self.closed_on = updated_on
-    end
-  end
-
-  # Saves the changes in a Journal
-  # Called after_save
-  def create_journal
-    if @current_journal
-      # attributes changes
-      if @attributes_before_change
-        (Issue.column_names - %w(id root_id lft rgt lock_version created_on updated_on closed_on)).each {|c|
-          before = @attributes_before_change[c]
-          after = send(c)
-          next if before == after || (before.blank? && after.blank?)
-          @current_journal.details << JournalDetail.new(:property => 'attr',
-                                                        :prop_key => c,
-                                                        :old_value => before,
-                                                        :value => after)
-        }
-      end
-      if @custom_values_before_change
-        # custom fields changes
-        custom_field_values.each {|c|
-          before = @custom_values_before_change[c.custom_field_id]
-          after = c.value
-          next if before == after || (before.blank? && after.blank?)
-          
-          if before.is_a?(Array) || after.is_a?(Array)
-            before = [before] unless before.is_a?(Array)
-            after = [after] unless after.is_a?(Array)
-            
-            # values removed
-            (before - after).reject(&:blank?).each do |value|
-              @current_journal.details << JournalDetail.new(:property => 'cf',
-                                                            :prop_key => c.custom_field_id,
-                                                            :old_value => value,
-                                                            :value => nil)
-            end
-            # values added
-            (after - before).reject(&:blank?).each do |value|
-              @current_journal.details << JournalDetail.new(:property => 'cf',
-                                                            :prop_key => c.custom_field_id,
-                                                            :old_value => nil,
-                                                            :value => value)
-            end
-          else
-            @current_journal.details << JournalDetail.new(:property => 'cf',
-                                                          :prop_key => c.custom_field_id,
-                                                          :old_value => before,
-                                                          :value => after)
-          end
-        }
-      end
-      @current_journal.save
-      # reset current journal
-      init_journal @current_journal.user, @current_journal.notes
-    end
-  end
-
-  def send_notification
-    if Setting.notified_events.include?('issue_added')
-      Mailer.deliver_issue_add(self)
-    end
-  end
-
-  # Stores the previous assignee so we can still have access
-  # to it during after_save callbacks (assigned_to_id_was is reset)
-  def set_assigned_to_was
-    @previous_assigned_to_id = assigned_to_id_was
-  end
-
-  # Clears the previous assignee at the end of after_save callbacks
-  def clear_assigned_to_was
-    @assigned_to_was = nil
-    @previous_assigned_to_id = nil
-  end
-
-  # Query generator for selecting groups of issue counts for a project
-  # based on specific criteria
-  #
-  # Options
-  # * project - Project to search in.
-  # * field - String. Issue field to key off of in the grouping.
-  # * joins - String. The table name to join against.
-  def self.count_and_group_by(options)
-    project = options.delete(:project)
-    select_field = options.delete(:field)
-    joins = options.delete(:joins)
-
-    where = "#{Issue.table_name}.#{select_field}=j.id"
-
-    ActiveRecord::Base.connection.select_all("select    s.id as status_id, 
-                                                s.is_closed as closed, 
-                                                j.id as #{select_field},
-                                                count(#{Issue.table_name}.id) as total 
-                                              from 
-                                                  #{Issue.table_name}, #{Project.table_name}, #{IssueStatus.table_name} s, #{joins} j
-                                              where 
-                                                #{Issue.table_name}.status_id=s.id 
-                                                and #{where}
-                                                and #{Issue.table_name}.project_id=#{Project.table_name}.id
-                                                and #{visible_condition(User.current, :project => project)}
-                                              group by s.id, s.is_closed, j.id")
-  end
-end
--- a/.svn/pristine/8f/8f9f9a92c19e3920a1c97c78a5493f483781cbcd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-source 'https://rubygems.org'
-
-gem "rails", "3.2.16"
-gem "jquery-rails", "~> 2.0.2"
-gem "coderay", "~> 1.1.0"
-gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
-gem "builder", "3.0.0"
-
-# Optional gem for LDAP authentication
-group :ldap do
-  gem "net-ldap", "~> 0.3.1"
-end
-
-# Optional gem for OpenID authentication
-group :openid do
-  gem "ruby-openid", "~> 2.3.0", :require => "openid"
-  gem "rack-openid"
-end
-
-# Optional gem for exporting the gantt to a PNG file, not supported with jruby
-platforms :mri, :mingw do
-  group :rmagick do
-    # RMagick 2 supports ruby 1.9
-    # RMagick 1 would be fine for ruby 1.8 but Bundler does not support
-    # different requirements for the same gem on different platforms
-    gem "rmagick", ">= 2.0.0"
-  end
-end
-
-platforms :jruby do
-  # jruby-openssl is bundled with JRuby 1.7.0
-  gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
-  gem "activerecord-jdbc-adapter", "~> 1.3.2"
-end
-
-# Include database gems for the adapters found in the database
-# configuration file
-require 'erb'
-require 'yaml'
-database_file = File.join(File.dirname(__FILE__), "config/database.yml")
-if File.exist?(database_file)
-  database_config = YAML::load(ERB.new(IO.read(database_file)).result)
-  adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
-  if adapters.any?
-    adapters.each do |adapter|
-      case adapter
-      when 'mysql2'
-        gem "mysql2", "~> 0.3.11", :platforms => [:mri, :mingw]
-        gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
-      when 'mysql'
-        gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw]
-        gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
-      when /postgresql/
-        gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw]
-        gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
-      when /sqlite3/
-        gem "sqlite3", :platforms => [:mri, :mingw]
-        gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
-      when /sqlserver/
-        gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw]
-        gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
-      else
-        warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
-      end
-    end
-  else
-    warn("No adapter found in config/database.yml, please configure it first")
-  end
-else
-  warn("Please configure your config/database.yml first")
-end
-
-group :development do
-  gem "rdoc", ">= 2.4.2"
-  gem "yard"
-end
-
-group :test do
-  gem "shoulda", "~> 3.3.2"
-  gem "mocha", ">= 0.14", :require => 'mocha/api'
-  if RUBY_VERSION >= '1.9.3'
-    gem "capybara", "~> 2.1.0"
-    gem "selenium-webdriver"
-    gem "database_cleaner"
-  end
-end
-
-local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
-if File.exists?(local_gemfile)
-  puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v`
-  instance_eval File.read(local_gemfile)
-end
-
-# Load plugins' Gemfiles
-Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
-  puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
-  #TODO: switch to "eval_gemfile file" when bundler >= 1.2.0 will be required (rails 4)
-  instance_eval File.read(file), file
-end
--- a/.svn/pristine/90/901740a4f156c3558f585b467304885cb6b1e403.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,609 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
-
-  class GitAdapterTest < ActiveSupport::TestCase
-    REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
-
-    FELIX_HEX  = "Felix Sch\xC3\xA4fer"
-    CHAR_1_HEX = "\xc3\x9c"
-
-    ## Git, Mercurial and CVS path encodings are binary.
-    ## Subversion supports URL encoding for path.
-    ## Redmine Mercurial adapter and extension use URL encoding.
-    ## Git accepts only binary path in command line parameter.
-    ## So, there is no way to use binary command line parameter in JRuby.
-    JRUBY_SKIP     = (RUBY_PLATFORM == 'java')
-    JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
-
-    if File.directory?(REPOSITORY_PATH)
-      ## Ruby uses ANSI api to fork a process on Windows.
-      ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
-      ## and these are incompatible with ASCII.
-      ## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10
-      ## http://code.google.com/p/msysgit/issues/detail?id=80
-      ## So, Latin-1 path tests fail on Japanese Windows
-      WINDOWS_PASS = (Redmine::Platform.mswin? &&
-                      Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10]))
-      WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10"
-
-      def setup
-        adapter_class = Redmine::Scm::Adapters::GitAdapter
-        assert adapter_class
-        assert adapter_class.client_command
-        assert_equal true, adapter_class.client_available
-        assert_equal true, adapter_class.client_version_above?([1])
-        assert_equal true, adapter_class.client_version_above?([1, 0])
-
-        @adapter = Redmine::Scm::Adapters::GitAdapter.new(
-                      REPOSITORY_PATH,
-                      nil,
-                      nil,
-                      nil,
-                      'ISO-8859-1'
-                   )
-        assert @adapter
-        @char_1 = CHAR_1_HEX.dup
-        @str_felix_hex  = FELIX_HEX.dup
-        if @char_1.respond_to?(:force_encoding)
-          @char_1.force_encoding('UTF-8')
-          @str_felix_hex.force_encoding('ASCII-8BIT')
-        end
-      end
-
-      def test_scm_version
-        to_test = { "git version 1.7.3.4\n"             => [1,7,3,4],
-                    "1.6.1\n1.7\n1.8"                   => [1,6,1],
-                    "1.6.2\r\n1.8.1\r\n1.9.1"           => [1,6,2]}
-        to_test.each do |s, v|
-          test_scm_version_for(s, v)
-        end
-      end
-
-      def test_branches
-        brs = []
-        @adapter.branches.each do |b|
-          brs << b
-        end
-        assert_equal 6, brs.length
-        br_issue_8857 = brs[0]
-        assert_equal 'issue-8857', br_issue_8857.to_s 
-        assert_equal '2a682156a3b6e77a8bf9cd4590e8db757f3c6c78', br_issue_8857.revision
-        assert_equal br_issue_8857.scmid, br_issue_8857.revision
-        assert_equal false, br_issue_8857.is_default
-        br_latin_1_path = brs[1]
-        assert_equal 'latin-1-path-encoding', br_latin_1_path.to_s 
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', br_latin_1_path.revision
-        assert_equal br_latin_1_path.scmid, br_latin_1_path.revision
-        assert_equal false, br_latin_1_path.is_default
-        br_master = brs[2]
-        assert_equal 'master', br_master.to_s
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master.revision
-        assert_equal br_master.scmid, br_master.revision
-        assert_equal false, br_master.is_default
-        br_master_20120212 = brs[3]
-        assert_equal 'master-20120212', br_master_20120212.to_s
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master_20120212.revision
-        assert_equal br_master_20120212.scmid, br_master_20120212.revision
-        assert_equal true, br_master_20120212.is_default
-        br_latin_1 = brs[-2]
-        assert_equal 'test-latin-1', br_latin_1.to_s
-        assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', br_latin_1.revision
-        assert_equal br_latin_1.scmid, br_latin_1.revision
-        assert_equal false, br_latin_1.is_default
-        br_test = brs[-1]
-        assert_equal 'test_branch', br_test.to_s
-        assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', br_test.revision
-        assert_equal br_test.scmid, br_test.revision
-        assert_equal false, br_test.is_default
-      end
-
-      def test_default_branch
-        assert_equal 'master-20120212', @adapter.default_branch
-      end
-
-      def test_tags
-        assert_equal  [
-              "tag00.lightweight",
-              "tag01.annotated",
-            ], @adapter.tags
-      end
-
-      def test_revisions_master_all
-        revs1 = []
-        @adapter.revisions('', nil, "master",{}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 15, revs1.length
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 0].identifier
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
-
-        revs2 = []
-        @adapter.revisions('', nil, "master",
-                           {:reverse => true}) do |rev|
-          revs2 << rev
-        end
-        assert_equal 15, revs2.length
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
-      end
-
-      def test_revisions_master_merged_rev
-        revs1 = []
-        @adapter.revisions('',
-                           "713f4944648826f558cf548222f813dabe7cbb04",
-                           "master",
-                           {:reverse => true}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 8, revs1.length
-        assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', revs1[ 0].identifier
-        assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 1].identifier
-        # 4a07fe31b is not a child of 713f49446
-        assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 2].identifier
-        # Merged revision
-        assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 3].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
-
-        revs2 = []
-        @adapter.revisions('',
-                           "fba357b886984ee71185ad2065e65fc0417d9b92",
-                           "master",
-                           {:reverse => true}) do |rev|
-          revs2 << rev
-        end
-        assert_equal 7, revs2.length
-        assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs2[ 0].identifier
-        # 4a07fe31b is not a child of fba357b8869
-        assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs2[ 1].identifier
-        # Merged revision
-        assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs2[ 2].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
-      end
-
-      def test_revisions_branch_latin_1_path_encoding_all
-        revs1 = []
-        @adapter.revisions('', nil, "latin-1-path-encoding",{}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 8, revs1.length
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[ 0].identifier
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
-
-        revs2 = []
-        @adapter.revisions('', nil, "latin-1-path-encoding",
-                           {:reverse => true}) do |rev|
-          revs2 << rev
-        end
-        assert_equal 8, revs2.length
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
-      end
-
-      def test_revisions_branch_latin_1_path_encoding_with_rev
-        revs1 = []
-        @adapter.revisions('',
-                           '7234cb2750b63f47bff735edc50a1c0a433c2518',
-                           "latin-1-path-encoding",
-                           {:reverse => true}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 7, revs1.length
-        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 0].identifier
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
-
-        revs2 = []
-        @adapter.revisions('',
-                           '57ca437c0acbbcb749821fdf3726a1367056d364',
-                           "latin-1-path-encoding",
-                           {:reverse => true}) do |rev|
-          revs2 << rev
-        end
-        assert_equal 3, revs2.length
-        assert_equal '4fc55c43bf3d3dc2efb66145365ddc17639ce81e', revs2[ 0].identifier
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
-      end
-
-      def test_revisions_invalid_rev
-        assert_equal [], @adapter.revisions('', '1234abcd', "master")
-        assert_raise Redmine::Scm::Adapters::CommandFailed do
-          revs1 = []
-          @adapter.revisions('',
-                           '1234abcd',
-                           "master",
-                           {:reverse => true}) do |rev|
-            revs1 << rev
-          end
-        end
-      end
-
-      def test_revisions_includes_master_two_revs
-        revs1 = []
-        @adapter.revisions('', nil, nil,
-                           {:reverse => true,
-                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
-                            :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43']}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 2, revs1.length
-        assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
-      end
-
-      def test_revisions_includes_master_two_revs_from_origin
-        revs1 = []
-        @adapter.revisions('', nil, nil,
-                           {:reverse => true,
-                            :includes => ['899a15dba03a3b350b89c3f537e4bbe02a03cdc9'],
-                            :excludes => []}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 2, revs1.length
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier
-        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 1].identifier
-      end
-
-      def test_revisions_includes_merged_revs
-        revs1 = []
-        @adapter.revisions('', nil, nil,
-                           {:reverse => true,
-                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
-                            :excludes => ['fba357b886984ee71185ad2065e65fc0417d9b92']}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 7, revs1.length
-        assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 0].identifier
-        assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 1].identifier
-        assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 2].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
-      end
-
-      def test_revisions_includes_two_heads
-        revs1 = []
-        @adapter.revisions('', nil, nil,
-                           {:reverse => true,
-                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
-                                          '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127'],
-                            :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43',
-                                          '4fc55c43bf3d3dc2efb66145365ddc17639ce81e']}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 4, revs1.length
-        assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
-        assert_equal '64f1f3e89ad1cb57976ff0ad99a107012ba3481d', revs1[-2].identifier
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
-      end
-
-      def test_revisions_disjointed_histories_revisions
-        revs1 = []
-        @adapter.revisions('', nil, nil,
-                           {:reverse => true,
-                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
-                                          '92397af84d22f27389c822848ecd5b463c181583'],
-                            :excludes => ['95488a44bc25f7d1f97d775a31359539ff333a63',
-                                          '4f26664364207fa8b1af9f8722647ab2d4ac5d43'] }) do |rev|
-          revs1 << rev
-        end
-        assert_equal 4, revs1.length
-        assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
-        assert_equal 'bc201c95999c4f10d018b0aa03b541cd6a2ff0ee', revs1[-2].identifier
-        assert_equal '92397af84d22f27389c822848ecd5b463c181583', revs1[-1].identifier
-      end
-
-      def test_revisions_invalid_rev_excludes
-        assert_equal [],
-                     @adapter.revisions('', nil, nil,
-                                        {:reverse => true,
-                                         :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
-                                         :excludes => ['0123abcd4567']})
-        assert_raise Redmine::Scm::Adapters::CommandFailed do
-          revs1 = []
-          @adapter.revisions('', nil, nil,
-                             {:reverse => true,
-                              :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
-                              :excludes => ['0123abcd4567']}) do |rev|
-            revs1 << rev
-          end
-        end
-      end
-
-      def test_getting_revisions_with_spaces_in_filename
-        assert_equal 1, @adapter.revisions("filemane with spaces.txt",
-                                           nil, "master").length
-      end
-
-      def test_parents
-        revs1 = []
-        @adapter.revisions('',
-                           nil,
-                           "master",
-                           {:reverse => true}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 15, revs1.length
-        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
-                     revs1[0].identifier
-        assert_equal nil, revs1[0].parents
-        assert_equal "899a15dba03a3b350b89c3f537e4bbe02a03cdc9",
-                     revs1[1].identifier
-        assert_equal 1, revs1[1].parents.length
-        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
-                     revs1[1].parents[0]
-        assert_equal "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
-                     revs1[10].identifier
-        assert_equal 2, revs1[10].parents.length
-        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8",
-                     revs1[10].parents[0]
-        assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da",
-                     revs1[10].parents[1]
-      end
-
-      def test_getting_revisions_with_leading_and_trailing_spaces_in_filename
-        assert_equal " filename with a leading space.txt ",
-           @adapter.revisions(" filename with a leading space.txt ",
-                               nil, "master")[0].paths[0][:path]
-      end
-
-      def test_getting_entries_with_leading_and_trailing_spaces_in_filename
-        assert_equal " filename with a leading space.txt ",
-           @adapter.entries('',
-                   '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name
-      end
-
-      def test_annotate
-        annotate = @adapter.annotate('sources/watchers_controller.rb')
-        assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
-        assert_equal 41, annotate.lines.size
-        assert_equal "# This program is free software; you can redistribute it and/or",
-                     annotate.lines[4].strip
-        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
-                      annotate.revisions[4].identifier
-        assert_equal "jsmith", annotate.revisions[4].author
-      end
-
-      def test_annotate_moved_file
-        annotate = @adapter.annotate('renamed_test.txt')
-        assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
-        assert_equal 2, annotate.lines.size
-      end
-
-      def test_last_rev
-        last_rev = @adapter.lastrev("README",
-                                    "4f26664364207fa8b1af9f8722647ab2d4ac5d43")
-        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid
-        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier
-        assert_equal "Adam Soltys <asoltys@gmail.com>", last_rev.author
-        assert_equal "2009-06-24 05:27:38".to_time, last_rev.time
-      end
-
-      def test_last_rev_with_spaces_in_filename
-        last_rev = @adapter.lastrev("filemane with spaces.txt",
-                                    "ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
-        last_rev_author = last_rev.author
-        assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
-        assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
-        assert_equal "#{@str_felix_hex} <felix@fachschaften.org>",
-                       last_rev.author
-        assert_equal "2010-09-18 19:59:46".to_time, last_rev.time
-      end
-
-      def test_latin_1_path
-        if WINDOWS_PASS
-          puts WINDOWS_SKIP_STR
-        elsif JRUBY_SKIP
-          puts JRUBY_SKIP_STR
-        else
-          p2 = "latin-1-dir/test-#{@char_1}-2.txt"
-          ['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1|
-            assert @adapter.diff(p2, r1)
-            assert @adapter.cat(p2, r1)
-            assert_equal 1, @adapter.annotate(p2, r1).lines.length
-            ['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2|
-              assert @adapter.diff(p2, r1, r2)
-            end
-          end
-        end
-      end
-
-      def test_latin_1_user_annotate
-        ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', '83ca5fd546063a'].each do |r1|
-          annotate = @adapter.annotate(" filename with a leading space.txt ", r1)
-          assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
-          assert_equal 1, annotate.lines.size
-          assert_equal "And this is a file with a leading and trailing space...",
-                       annotate.lines[0].strip
-          assert_equal "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
-                       annotate.revisions[0].identifier
-          assert_equal @str_felix_hex, annotate.revisions[0].author
-        end
-      end
-
-      def test_entries_tag
-        entries1 = @adapter.entries(nil, 'tag01.annotated',
-                                    options = {:report_last_commit => true})
-        assert entries1
-        assert_equal 3, entries1.size
-        assert_equal 'sources', entries1[1].name
-        assert_equal 'sources', entries1[1].path
-        assert_equal 'dir', entries1[1].kind
-        readme = entries1[2]
-        assert_equal 'README', readme.name
-        assert_equal 'README', readme.path
-        assert_equal 'file', readme.kind
-        assert_equal 27, readme.size
-        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier
-        assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
-      end
-
-      def test_entries_branch
-        entries1 = @adapter.entries(nil, 'test_branch',
-                                    options = {:report_last_commit => true})
-        assert entries1
-        assert_equal 4, entries1.size
-        assert_equal 'sources', entries1[1].name
-        assert_equal 'sources', entries1[1].path
-        assert_equal 'dir', entries1[1].kind
-        readme = entries1[2]
-        assert_equal 'README', readme.name
-        assert_equal 'README', readme.path
-        assert_equal 'file', readme.kind
-        assert_equal 159, readme.size
-        assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier
-        assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time
-      end
-
-      def test_entries_wrong_path_encoding
-        adpt = Redmine::Scm::Adapters::GitAdapter.new(
-                      REPOSITORY_PATH,
-                      nil,
-                      nil,
-                      nil,
-                      'EUC-JP'
-                   )
-        entries1 = adpt.entries('latin-1-dir', '64f1f3e8')
-        assert entries1
-        assert_equal 3, entries1.size
-        f1 = entries1[1]
-        assert_equal nil, f1.name
-        assert_equal nil, f1.path
-        assert_equal 'file', f1.kind
-      end
-
-      def test_entries_latin_1_files
-        entries1 = @adapter.entries('latin-1-dir', '64f1f3e8')
-        assert entries1
-        assert_equal 3, entries1.size
-        f1 = entries1[1]
-        assert_equal "test-#{@char_1}-2.txt", f1.name
-        assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path
-        assert_equal 'file', f1.kind
-      end
-
-      def test_entries_latin_1_dir
-        if WINDOWS_PASS
-          puts WINDOWS_SKIP_STR
-        elsif JRUBY_SKIP
-          puts JRUBY_SKIP_STR
-        else
-          entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir",
-                                      '1ca7f5ed')
-          assert entries1
-          assert_equal 3, entries1.size
-          f1 = entries1[1]
-          assert_equal "test-#{@char_1}-2.txt", f1.name
-          assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path
-          assert_equal 'file', f1.kind
-        end
-      end
-
-      def test_entry
-        entry = @adapter.entry()
-        assert_equal "", entry.path
-        assert_equal "dir", entry.kind
-        entry = @adapter.entry('')
-        assert_equal "", entry.path
-        assert_equal "dir", entry.kind
-        assert_nil @adapter.entry('invalid')
-        assert_nil @adapter.entry('/invalid')
-        assert_nil @adapter.entry('/invalid/')
-        assert_nil @adapter.entry('invalid/invalid')
-        assert_nil @adapter.entry('invalid/invalid/')
-        assert_nil @adapter.entry('/invalid/invalid')
-        assert_nil @adapter.entry('/invalid/invalid/')
-        ["README", "/README"].each do |path|
-          entry = @adapter.entry(path, '7234cb2750b63f')
-          assert_equal "README", entry.path
-          assert_equal "file", entry.kind
-        end
-        ["sources", "/sources", "/sources/"].each do |path|
-          entry = @adapter.entry(path, '7234cb2750b63f')
-          assert_equal "sources", entry.path
-          assert_equal "dir", entry.kind
-        end
-        ["sources/watchers_controller.rb", "/sources/watchers_controller.rb"].each do |path|
-          entry = @adapter.entry(path, '7234cb2750b63f')
-          assert_equal "sources/watchers_controller.rb", entry.path
-          assert_equal "file", entry.kind
-        end
-      end
-
-      def test_path_encoding_default_utf8
-        adpt1 = Redmine::Scm::Adapters::GitAdapter.new(
-                                  REPOSITORY_PATH
-                                )
-        assert_equal "UTF-8", adpt1.path_encoding
-        adpt2 = Redmine::Scm::Adapters::GitAdapter.new(
-                                  REPOSITORY_PATH,
-                                  nil,
-                                  nil,
-                                  nil,
-                                  ""
-                                )
-        assert_equal "UTF-8", adpt2.path_encoding
-      end
-
-      def test_cat_path_invalid
-        assert_nil @adapter.cat('invalid')
-      end
-
-      def test_cat_revision_invalid
-        assert     @adapter.cat('README')
-        assert_nil @adapter.cat('README', '1234abcd5678')
-      end
-
-      def test_diff_path_invalid
-        assert_equal [], @adapter.diff('invalid', '713f4944648826f5')
-      end
-
-      def test_diff_revision_invalid
-        assert_nil @adapter.diff(nil, '1234abcd5678')
-        assert_nil @adapter.diff(nil, '713f4944648826f5', '1234abcd5678')
-        assert_nil @adapter.diff(nil, '1234abcd5678', '713f4944648826f5')
-      end
-
-      def test_annotate_path_invalid
-        assert_nil @adapter.annotate('invalid')
-      end
-
-      def test_annotate_revision_invalid
-        assert     @adapter.annotate('README')
-        assert_nil @adapter.annotate('README', '1234abcd5678')
-      end
-
-      private
-
-      def test_scm_version_for(scm_command_version, version)
-        @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
-        assert_equal version, @adapter.class.scm_command_version
-      end
-
-    else
-      puts "Git test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
-    end
-  end
-
-rescue LoadError
-  class GitMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
-  end
-end
--- a/.svn/pristine/90/90614dcc50db90b38ba908659a9cd6e4367e61ab.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'net/pop'
-
-module Redmine
-  module POP3
-    class << self
-      def check(pop_options={}, options={})
-        host = pop_options[:host] || '127.0.0.1'
-        port = pop_options[:port] || '110'
-        apop = (pop_options[:apop].to_s == '1')
-        delete_unprocessed = (pop_options[:delete_unprocessed].to_s == '1')
-
-        pop = Net::POP3.APOP(apop).new(host,port)
-        logger.debug "Connecting to #{host}..." if logger && logger.debug?
-        pop.start(pop_options[:username], pop_options[:password]) do |pop_session|
-          if pop_session.mails.empty?
-            logger.debug "No email to process" if logger && logger.debug?
-          else
-            logger.debug "#{pop_session.mails.size} email(s) to process..." if logger && logger.debug?
-            pop_session.each_mail do |msg|
-              message = msg.pop
-              message_id = (message =~ /^Message-I[dD]: (.*)/ ? $1 : '').strip
-              if MailHandler.receive(message, options)
-                msg.delete
-                logger.debug "--> Message #{message_id} processed and deleted from the server" if logger && logger.debug?
-              else
-                if delete_unprocessed
-                  msg.delete
-                  logger.debug "--> Message #{message_id} NOT processed and deleted from the server" if logger && logger.debug?
-                else
-                  logger.debug "--> Message #{message_id} NOT processed and left on the server" if logger && logger.debug?
-                end
-              end
-            end
-          end
-        end
-      end
-
-      private
-
-      def logger
-        ::Rails.logger
-      end
-    end
-  end
-end
--- a/.svn/pristine/92/9200969636fc087a7427e652c085c04fee498c33.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class QueriesHelperTest < ActionView::TestCase
-  include QueriesHelper
-  include Redmine::I18n
-
-  fixtures :projects, :enabled_modules, :users, :members,
-           :member_roles, :roles, :trackers, :issue_statuses,
-           :issue_categories, :enumerations, :issues,
-           :watchers, :custom_fields, :custom_values, :versions,
-           :queries,
-           :projects_trackers,
-           :custom_fields_trackers
-
-  def test_filters_options_has_empty_item
-    query = IssueQuery.new
-    filter_count = query.available_filters.size
-    fo = filters_options(query)
-    assert_equal filter_count + 1, fo.size
-    assert_equal [], fo[0]
-  end
-end
--- a/.svn/pristine/92/92e79cf48ee767b10d559c8d0bc187ea50742a7c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingIssueRelationsTest < ActionController::IntegrationTest
-  def test_issue_relations
-    assert_routing(
-        { :method => 'get', :path => "/issues/1/relations" },
-        { :controller => 'issue_relations', :action => 'index',
-          :issue_id => '1' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/1/relations.xml" },
-        { :controller => 'issue_relations', :action => 'index',
-          :issue_id => '1', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/1/relations.json" },
-        { :controller => 'issue_relations', :action => 'index',
-          :issue_id => '1', :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issues/1/relations" },
-        { :controller => 'issue_relations', :action => 'create',
-          :issue_id => '1' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issues/1/relations.xml" },
-        { :controller => 'issue_relations', :action => 'create',
-          :issue_id => '1', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issues/1/relations.json" },
-        { :controller => 'issue_relations', :action => 'create',
-          :issue_id => '1', :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/relations/23" },
-        { :controller => 'issue_relations', :action => 'show', :id => '23' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/relations/23.xml" },
-        { :controller => 'issue_relations', :action => 'show', :id => '23',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/relations/23.json" },
-        { :controller => 'issue_relations', :action => 'show', :id => '23',
-          :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/relations/23" },
-        { :controller => 'issue_relations', :action => 'destroy', :id => '23' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/relations/23.xml" },
-        { :controller => 'issue_relations', :action => 'destroy', :id => '23',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/relations/23.json" },
-        { :controller => 'issue_relations', :action => 'destroy', :id => '23',
-          :format => 'json' }
-      )
-  end
-end
--- a/.svn/pristine/93/93670bab9f61b2b691063ad9fe7c015dfa58e59c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::MimeTypeTest < ActiveSupport::TestCase
-
-  def test_of
-    to_test = {'test.unk' => nil,
-               'test.txt' => 'text/plain',
-               'test.c' => 'text/x-c',
-               }
-    to_test.each do |name, expected|
-      assert_equal expected, Redmine::MimeType.of(name)
-    end
-  end
-
-  def test_css_class_of
-    to_test = {'test.unk' => nil,
-               'test.txt' => 'text-plain',
-               'test.c' => 'text-x-c',
-               }
-    to_test.each do |name, expected|
-      assert_equal expected, Redmine::MimeType.css_class_of(name)
-    end
-  end
-
-  def test_main_mimetype_of
-    to_test = {'test.unk' => nil,
-               'test.txt' => 'text',
-               'test.c' => 'text',
-               }
-    to_test.each do |name, expected|
-      assert_equal expected, Redmine::MimeType.main_mimetype_of(name)
-    end
-  end
-
-  def test_is_type
-    to_test = {['text', 'test.unk'] => false,
-               ['text', 'test.txt'] => true,
-               ['text', 'test.c'] => true,
-               }
-    to_test.each do |args, expected|
-      assert_equal expected, Redmine::MimeType.is_type?(*args)
-    end
-  end
-end
--- a/.svn/pristine/93/939cceaf70f6f951d3ca40822110175a73d3a953.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingNewsTest < ActionController::IntegrationTest
-  def test_news_index
-    assert_routing(
-        { :method => 'get', :path => "/news" },
-        { :controller => 'news', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/news.atom" },
-        { :controller => 'news', :action => 'index', :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/news.xml" },
-        { :controller => 'news', :action => 'index', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/news.json" },
-        { :controller => 'news', :action => 'index', :format => 'json' }
-      )
-  end
-
-  def test_news
-    assert_routing(
-        { :method => 'get', :path => "/news/2" },
-        { :controller => 'news', :action => 'show', :id => '2' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/news/234" },
-        { :controller => 'news', :action => 'show', :id => '234' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/news/567/edit" },
-        { :controller => 'news', :action => 'edit', :id => '567' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/news/567" },
-        { :controller => 'news', :action => 'update', :id => '567' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/news/567" },
-        { :controller => 'news', :action => 'destroy', :id => '567' }
-      )
-  end
-
-  def test_news_scoped_under_project
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/news" },
-        { :controller => 'news', :action => 'index', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/news.atom" },
-        { :controller => 'news', :action => 'index', :format => 'atom',
-          :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/news.xml" },
-        { :controller => 'news', :action => 'index', :format => 'xml',
-          :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/news.json" },
-        { :controller => 'news', :action => 'index', :format => 'json',
-          :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/news/new" },
-        { :controller => 'news', :action => 'new', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/567/news" },
-        { :controller => 'news', :action => 'create', :project_id => '567' }
-      )
-  end
-end
--- a/.svn/pristine/93/93a376c27a710917c3458387b07a830523557ad3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingSettingsTest < ActionController::IntegrationTest
-  def test_settings
-    assert_routing(
-        { :method => 'get', :path => "/settings" },
-        { :controller => 'settings', :action => 'index' }
-      )
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/settings/edit" },
-          { :controller => 'settings', :action => 'edit' }
-        )
-    end
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/settings/plugin/testid" },
-          { :controller => 'settings', :action => 'plugin',
-            :id => 'testid' }
-        )
-    end
-  end
-end
--- a/.svn/pristine/93/93f85fbfa5d1803a533dc2903452408ac582b22a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::PaginationTest < ActiveSupport::TestCase
-
-  def setup
-    @klass = Redmine::Pagination::Paginator
-  end
-
-  def test_count_is_zero
-    p = @klass.new 0, 10, 1
-
-    assert_equal 0, p.offset
-    assert_equal 10, p.per_page
-    %w(first_page previous_page next_page last_page).each do |method|
-      assert_nil p.send(method), "#{method} was not nil"
-    end
-    assert_equal 0, p.first_item
-    assert_equal 0, p.last_item
-    assert_equal [], p.linked_pages
-  end
-
-  def test_count_is_less_than_per_page
-    p = @klass.new 7, 10, 1
-
-    assert_equal 0, p.offset
-    assert_equal 10, p.per_page
-    assert_equal 1, p.first_page
-    assert_nil p.previous_page
-    assert_nil p.next_page
-    assert_equal 1, p.last_page
-    assert_equal 1, p.first_item
-    assert_equal 7, p.last_item
-    assert_equal [], p.linked_pages
-  end
-
-  def test_count_is_equal_to_per_page
-    p = @klass.new 10, 10, 1
-
-    assert_equal 0, p.offset
-    assert_equal 10, p.per_page
-    assert_equal 1, p.first_page
-    assert_nil p.previous_page
-    assert_nil p.next_page
-    assert_equal 1, p.last_page
-    assert_equal 1, p.first_item
-    assert_equal 10, p.last_item
-    assert_equal [], p.linked_pages
-  end
-
-  def test_2_pages
-    p = @klass.new 16, 10, 1
-
-    assert_equal 0, p.offset
-    assert_equal 10, p.per_page
-    assert_equal 1, p.first_page
-    assert_nil p.previous_page
-    assert_equal 2, p.next_page
-    assert_equal 2, p.last_page
-    assert_equal 1, p.first_item
-    assert_equal 10, p.last_item
-    assert_equal [1, 2], p.linked_pages
-  end
-
-  def test_many_pages
-    p = @klass.new 155, 10, 1
-
-    assert_equal 0, p.offset
-    assert_equal 10, p.per_page
-    assert_equal 1, p.first_page
-    assert_nil p.previous_page
-    assert_equal 2, p.next_page
-    assert_equal 16, p.last_page
-    assert_equal 1, p.first_item
-    assert_equal 10, p.last_item
-    assert_equal [1, 2, 3, 16], p.linked_pages
-  end
-end
--- a/.svn/pristine/94/94765944a40a57c939e4d5db59efec674343d66e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,662 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesGitControllerTest < ActionController::TestCase
-  tests RepositoriesController
-
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :repositories, :enabled_modules
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
-  REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
-  PRJ_ID     = 3
-  CHAR_1_HEX = "\xc3\x9c"
-  FELIX_HEX  = "Felix Sch\xC3\xA4fer"
-  NUM_REV = 28
-
-  ## Git, Mercurial and CVS path encodings are binary.
-  ## Subversion supports URL encoding for path.
-  ## Redmine Mercurial adapter and extension use URL encoding.
-  ## Git accepts only binary path in command line parameter.
-  ## So, there is no way to use binary command line parameter in JRuby.
-  JRUBY_SKIP     = (RUBY_PLATFORM == 'java')
-  JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
-
-  def setup
-    @ruby19_non_utf8_pass =
-      (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
-
-    User.current = nil
-    @project    = Project.find(PRJ_ID)
-    @repository = Repository::Git.create(
-                      :project       => @project,
-                      :url           => REPOSITORY_PATH,
-                      :path_encoding => 'ISO-8859-1'
-                      )
-    assert @repository
-    @char_1        = CHAR_1_HEX.dup
-    @felix_utf8  = FELIX_HEX.dup
-    if @char_1.respond_to?(:force_encoding)
-      @char_1.force_encoding('UTF-8')
-      @felix_utf8.force_encoding('UTF-8')
-    end
-  end
-
-  def test_create_and_update
-    @request.session[:user_id] = 1
-    assert_difference 'Repository.count' do
-      post :create, :project_id => 'subproject1',
-                    :repository_scm => 'Git',
-                    :repository => {
-                       :url => '/test',
-                       :is_default => '0',
-                       :identifier => 'test-create',
-                       :extra_report_last_commit => '1',
-                     }
-    end
-    assert_response 302
-    repository = Repository.first(:order => 'id DESC')
-    assert_kind_of Repository::Git, repository
-    assert_equal '/test', repository.url
-    assert_equal true, repository.extra_report_last_commit
-
-    put :update, :id => repository.id,
-                 :repository => {
-                     :extra_report_last_commit => '0'
-                 }
-    assert_response 302
-    repo2 = Repository.find(repository.id)
-    assert_equal false, repo2.extra_report_last_commit
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    ## Ruby uses ANSI api to fork a process on Windows.
-    ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
-    ## and these are incompatible with ASCII.
-    ## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10
-    ## http://code.google.com/p/msysgit/issues/detail?id=80
-    ## So, Latin-1 path tests fail on Japanese Windows
-    WINDOWS_PASS = (Redmine::Platform.mswin? &&
-                         Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10]))
-    WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10"
-
-    def test_get_new
-      @request.session[:user_id] = 1
-      @project.repository.destroy
-      get :new, :project_id => 'subproject1', :repository_scm => 'Git'
-      assert_response :success
-      assert_template 'new'
-      assert_kind_of Repository::Git, assigns(:repository)
-      assert assigns(:repository).new_record?
-    end
-
-    def test_browse_root
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      get :show, :id => PRJ_ID
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal 9, assigns(:entries).size
-      assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'this_is_a_really_long_and_verbose_directory_name' && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
-      assert assigns(:entries).detect {|e| e.name == 'copied_README' && e.kind == 'file'}
-      assert assigns(:entries).detect {|e| e.name == 'new_file.txt' && e.kind == 'file'}
-      assert assigns(:entries).detect {|e| e.name == 'renamed_test.txt' && e.kind == 'file'}
-      assert assigns(:entries).detect {|e| e.name == 'filemane with spaces.txt' && e.kind == 'file'}
-      assert assigns(:entries).detect {|e| e.name == ' filename with a leading space.txt ' && e.kind == 'file'}
-      assert_not_nil assigns(:changesets)
-      assert assigns(:changesets).size > 0
-    end
-
-    def test_browse_branch
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :rev => 'test_branch'
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal 4, assigns(:entries).size
-      assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
-      assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
-      assert assigns(:entries).detect {|e| e.name == 'test.txt' && e.kind == 'file'}
-      assert_not_nil assigns(:changesets)
-      assert assigns(:changesets).size > 0
-    end
-
-    def test_browse_tag
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-       [
-        "tag00.lightweight",
-        "tag01.annotated",
-       ].each do |t1|
-        get :show, :id => PRJ_ID, :rev => t1
-        assert_response :success
-        assert_template 'show'
-        assert_not_nil assigns(:entries)
-        assert assigns(:entries).size > 0
-        assert_not_nil assigns(:changesets)
-        assert assigns(:changesets).size > 0
-      end
-    end
-
-    def test_browse_directory
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['edit.png'], assigns(:entries).collect(&:name)
-      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
-      assert_not_nil entry
-      assert_equal 'file', entry.kind
-      assert_equal 'images/edit.png', entry.path
-      assert_not_nil assigns(:changesets)
-      assert assigns(:changesets).size > 0
-    end
-
-    def test_browse_at_given_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
-          :rev => '7234cb2750b63f47bff735edc50a1c0a433c2518'
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['delete.png'], assigns(:entries).collect(&:name)
-      assert_not_nil assigns(:changesets)
-      assert assigns(:changesets).size > 0
-    end
-
-    def test_changes
-      get :changes, :id => PRJ_ID,
-          :path => repository_path_hash(['images', 'edit.png'])[:param]
-      assert_response :success
-      assert_template 'changes'
-      assert_tag :tag => 'h2', :content => 'edit.png'
-    end
-
-    def test_entry_show
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
-      assert_response :success
-      assert_template 'entry'
-      # Line 19
-      assert_tag :tag => 'th',
-                 :content => '11',
-                 :attributes => { :class => 'line-num' },
-                 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
-    end
-
-    def test_entry_show_latin_1
-      if @ruby19_non_utf8_pass
-        puts_ruby19_non_utf8_pass()
-      elsif WINDOWS_PASS
-        puts WINDOWS_SKIP_STR
-      elsif JRUBY_SKIP
-        puts JRUBY_SKIP_STR
-      else
-        with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-          ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
-            get :entry, :id => PRJ_ID,
-                :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
-                :rev => r1
-            assert_response :success
-            assert_template 'entry'
-            assert_tag :tag => 'th',
-                   :content => '1',
-                   :attributes => { :class => 'line-num' },
-                   :sibling => { :tag => 'td',
-                                 :content => /test-#{@char_1}.txt/ }
-          end
-        end
-      end
-    end
-
-    def test_entry_download
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
-          :format => 'raw'
-      assert_response :success
-      # File content
-      assert @response.body.include?('WITHOUT ANY WARRANTY')
-    end
-
-    def test_directory_entry
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entry)
-      assert_equal 'sources', assigns(:entry).name
-    end
-
-    def test_diff
-      assert_equal true, @repository.is_default
-      assert_nil @repository.identifier
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      # Full diff of changeset 2f9c0091
-      ['inline', 'sbs'].each do |dt|
-        get :diff,
-            :id   => PRJ_ID,
-            :rev  => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
-            :type => dt
-        assert_response :success
-        assert_template 'diff'
-        # Line 22 removed
-        assert_tag :tag => 'th',
-                   :content => /22/,
-                   :sibling => { :tag => 'td',
-                                 :attributes => { :class => /diff_out/ },
-                                 :content => /def remove/ }
-        assert_tag :tag => 'h2', :content => /2f9c0091/
-      end
-    end
-
-    def test_diff_with_rev_and_path
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      with_settings :diff_max_lines_displayed => 1000 do
-        # Full diff of changeset 2f9c0091
-        ['inline', 'sbs'].each do |dt|
-          get :diff,
-              :id   => PRJ_ID,
-              :rev  => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
-              :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
-              :type => dt
-          assert_response :success
-          assert_template 'diff'
-          # Line 22 removed
-          assert_tag :tag => 'th',
-                     :content => '22',
-                     :sibling => { :tag => 'td',
-                                   :attributes => { :class => /diff_out/ },
-                                   :content => /def remove/ }
-          assert_tag :tag => 'h2', :content => /2f9c0091/
-        end
-      end
-    end
-
-    def test_diff_truncated
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      with_settings :diff_max_lines_displayed => 5 do
-        # Truncated diff of changeset 2f9c0091
-        with_cache do
-          with_settings :default_language => 'en' do
-            get :diff, :id   => PRJ_ID, :type => 'inline',
-                :rev  => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
-            assert_response :success
-            assert @response.body.include?("... This diff was truncated")
-          end
-          with_settings :default_language => 'fr' do
-            get :diff, :id   => PRJ_ID, :type => 'inline',
-                :rev  => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
-            assert_response :success
-            assert ! @response.body.include?("... This diff was truncated")
-            assert @response.body.include?("... Ce diff")
-          end
-        end
-      end
-    end
-
-    def test_diff_two_revs
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['inline', 'sbs'].each do |dt|
-        get :diff,
-            :id     => PRJ_ID,
-            :rev    => '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
-            :rev_to => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
-            :type   => dt
-        assert_response :success
-        assert_template 'diff'
-        diff = assigns(:diff)
-        assert_not_nil diff
-        assert_tag :tag => 'h2', :content => /2f9c0091:61b685fb/
-        assert_tag :tag => "form",
-                   :attributes => {
-                     :action => "/projects/subproject1/repository/revisions/" +
-                                   "61b685fbe55ab05b5ac68402d5720c1a6ac973d1/diff"
-                   }
-        assert_tag :tag => 'input',
-                   :attributes => {
-                     :id => "rev_to",
-                     :name => "rev_to",
-                     :type => "hidden",
-                     :value => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
-                   }
-      end
-    end
-
-    def test_diff_path_in_subrepo
-      repo = Repository::Git.create(
-                      :project       => @project,
-                      :url           => REPOSITORY_PATH,
-                      :identifier => 'test-diff-path',
-                      :path_encoding => 'ISO-8859-1'
-                      );
-      assert repo
-      assert_equal false, repo.is_default
-      assert_equal 'test-diff-path', repo.identifier
-      get :diff,
-          :id     => PRJ_ID,
-          :repository_id => 'test-diff-path',
-          :rev    => '61b685fbe55ab05b',
-          :rev_to => '2f9c0091c754a91a',
-          :type   => 'inline'
-      assert_response :success
-      assert_template 'diff'
-      diff = assigns(:diff)
-      assert_not_nil diff
-      assert_tag :tag => "form",
-                 :attributes => {
-                   :action => "/projects/subproject1/repository/test-diff-path/" + 
-                                "revisions/61b685fbe55ab05b/diff"
-                 }
-      assert_tag :tag => 'input',
-                 :attributes => {
-                   :id => "rev_to",
-                   :name => "rev_to",
-                   :type => "hidden",
-                   :value => '2f9c0091c754a91a'
-                 }
-    end
-
-    def test_diff_latin_1
-      if @ruby19_non_utf8_pass
-        puts_ruby19_non_utf8_pass()
-      else
-        with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-          ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
-            ['inline', 'sbs'].each do |dt|
-              get :diff, :id => PRJ_ID, :rev => r1, :type => dt
-              assert_response :success
-              assert_template 'diff'
-              assert_tag :tag => 'thead',
-                         :descendant => {
-                           :tag => 'th',
-                           :attributes => { :class => 'filename' } ,
-                           :content => /latin-1-dir\/test-#{@char_1}.txt/ ,
-                          },
-                         :sibling => {
-                           :tag => 'tbody',
-                           :descendant => {
-                              :tag => 'td',
-                              :attributes => { :class => /diff_in/ },
-                              :content => /test-#{@char_1}.txt/
-                           }
-                         }
-            end
-          end
-        end
-      end
-    end
-
-    def test_diff_should_show_filenames
-      get :diff, :id => PRJ_ID, :rev => 'deff712f05a90d96edbd70facc47d944be5897e3', :type => 'inline'
-      assert_response :success
-      assert_template 'diff'
-      # modified file
-      assert_select 'th.filename', :text => 'sources/watchers_controller.rb'
-      # deleted file
-      assert_select 'th.filename', :text => 'test.txt'
-    end
-
-    def test_save_diff_type
-      user1 = User.find(1)
-      user1.pref[:diff_type] = nil
-      user1.preference.save
-      user = User.find(1)
-      assert_nil user.pref[:diff_type]
-
-      @request.session[:user_id] = 1 # admin
-      get :diff,
-          :id   => PRJ_ID,
-          :rev  => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
-      assert_response :success
-      assert_template 'diff'
-      user.reload
-      assert_equal "inline", user.pref[:diff_type]
-      get :diff,
-          :id   => PRJ_ID,
-          :rev  => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
-          :type => 'sbs'
-      assert_response :success
-      assert_template 'diff'
-      user.reload
-      assert_equal "sbs", user.pref[:diff_type]
-    end
-
-    def test_annotate
-      get :annotate, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
-      assert_response :success
-      assert_template 'annotate'
-
-      # Line 23, changeset 2f9c0091
-      assert_select 'tr' do
-        assert_select 'th.line-num', :text => '23'
-        assert_select 'td.revision', :text => /2f9c0091/
-        assert_select 'td.author', :text => 'jsmith'
-        assert_select 'td', :text => /remove_watcher/
-      end
-    end
-
-    def test_annotate_at_given_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :annotate, :id => PRJ_ID, :rev => 'deff7',
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
-      assert_response :success
-      assert_template 'annotate'
-      assert_tag :tag => 'h2', :content => /@ deff712f/
-    end
-
-    def test_annotate_binary_file
-      get :annotate, :id => PRJ_ID,
-          :path => repository_path_hash(['images', 'edit.png'])[:param]
-      assert_response 500
-      assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
-                              :content => /cannot be annotated/
-    end
-
-    def test_annotate_error_when_too_big
-      with_settings :file_max_size_displayed => 1 do
-        get :annotate, :id => PRJ_ID,
-            :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
-            :rev => 'deff712f'
-        assert_response 500
-        assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
-                                :content => /exceeds the maximum text file size/
-
-        get :annotate, :id => PRJ_ID,
-            :path => repository_path_hash(['README'])[:param],
-            :rev => '7234cb2'
-        assert_response :success
-        assert_template 'annotate'
-      end
-    end
-
-    def test_annotate_latin_1
-      if @ruby19_non_utf8_pass
-        puts_ruby19_non_utf8_pass()
-      elsif WINDOWS_PASS
-        puts WINDOWS_SKIP_STR
-      elsif JRUBY_SKIP
-        puts JRUBY_SKIP_STR
-      else
-        with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-          ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
-            get :annotate, :id => PRJ_ID,
-                :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
-                :rev => r1
-            assert_select "th.line-num", :text => '1' do
-              assert_select "+ td.revision" do
-                assert_select "a", :text => '57ca437c'
-                assert_select "+ td.author", :text => "jsmith" do
-                  assert_select "+ td",
-                                :text => "test-#{@char_1}.txt"
-                end
-              end
-            end
-          end
-        end
-      end
-    end
-
-    def test_annotate_latin_1_author
-      ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', '83ca5fd546063a'].each do |r1|
-        get :annotate, :id => PRJ_ID,
-            :path => repository_path_hash([" filename with a leading space.txt "])[:param],
-            :rev => r1
-        assert_select "th.line-num", :text => '1' do
-          assert_select "+ td.revision" do
-            assert_select "a", :text => '83ca5fd5'
-            assert_select "+ td.author", :text => @felix_utf8 do
-              assert_select "+ td",
-                            :text => "And this is a file with a leading and trailing space..."
-            end
-          end
-        end
-      end
-    end
-
-    def test_revisions
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :revisions, :id => PRJ_ID
-      assert_response :success
-      assert_template 'revisions'
-      assert_tag :tag => 'form',
-                 :attributes => {
-                   :method => 'get',
-                   :action => '/projects/subproject1/repository/revision'
-                 }
-    end
-
-    def test_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['61b685fbe55ab05b5ac68402d5720c1a6ac973d1', '61b685f'].each do |r|
-        get :revision, :id => PRJ_ID, :rev => r
-        assert_response :success
-        assert_template 'revision'
-      end
-    end
-
-    def test_empty_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['', ' ', nil].each do |r|
-        get :revision, :id => PRJ_ID, :rev => r
-        assert_response 404
-        assert_error_tag :content => /was not found/
-      end
-    end
-
-    def test_destroy_valid_repository
-      @request.session[:user_id] = 1 # admin
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-
-    def test_destroy_invalid_repository
-      @request.session[:user_id] = 1 # admin
-      @project.repository.destroy
-      @repository = Repository::Git.create!(
-                      :project       => @project,
-                      :url           => "/invalid",
-                      :path_encoding => 'ISO-8859-1'
-                      )
-      @repository.fetch_changesets
-      @repository.reload
-      assert_equal 0, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-
-    private
-
-    def puts_ruby19_non_utf8_pass
-      puts "TODO: This test fails in Ruby 1.9 " +
-           "and Encoding.default_external is not UTF-8. " +
-           "Current value is '#{Encoding.default_external.to_s}'"
-    end
-  else
-    puts "Git test repository NOT FOUND. Skipping functional tests !!!"
-    def test_fake; assert true end
-  end
-
-  private
-  def with_cache(&block)
-    before = ActionController::Base.perform_caching
-    ActionController::Base.perform_caching = true
-    block.call
-    ActionController::Base.perform_caching = before
-  end
-end
--- a/.svn/pristine/94/94850f049cba8fd1d7b631af60e061c441dc4401.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,385 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AttachmentsControllerTest < ActionController::TestCase
-  fixtures :users, :projects, :roles, :members, :member_roles,
-           :enabled_modules, :issues, :trackers, :attachments,
-           :versions, :wiki_pages, :wikis, :documents
-
-  def setup
-    User.current = nil
-    set_fixtures_attachments_directory
-  end
-
-  def teardown
-    set_tmp_attachments_directory
-  end
-
-  def test_show_diff
-    ['inline', 'sbs'].each do |dt|
-      # 060719210727_changeset_utf8.diff
-      get :show, :id => 14, :type => dt
-      assert_response :success
-      assert_template 'diff'
-      assert_equal 'text/html', @response.content_type
-      assert_tag 'th',
-        :attributes => {:class => /filename/},
-        :content => /issues_controller.rb\t\(révision 1484\)/
-      assert_tag 'td',
-        :attributes => {:class => /line-code/},
-        :content => /Demande créée avec succès/
-    end
-    set_tmp_attachments_directory
-  end
-
-  def test_show_diff_replace_cannot_convert_content
-    with_settings :repositories_encodings => 'UTF-8' do
-      ['inline', 'sbs'].each do |dt|
-        # 060719210727_changeset_iso8859-1.diff
-        get :show, :id => 5, :type => dt
-        assert_response :success
-        assert_template 'diff'
-        assert_equal 'text/html', @response.content_type
-        assert_tag 'th',
-          :attributes => {:class => "filename"},
-          :content => /issues_controller.rb\t\(r\?vision 1484\)/
-        assert_tag 'td',
-          :attributes => {:class => /line-code/},
-          :content => /Demande cr\?\?e avec succ\?s/
-      end
-    end
-    set_tmp_attachments_directory
-  end
-
-  def test_show_diff_latin_1
-    with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-      ['inline', 'sbs'].each do |dt|
-        # 060719210727_changeset_iso8859-1.diff
-        get :show, :id => 5, :type => dt
-        assert_response :success
-        assert_template 'diff'
-        assert_equal 'text/html', @response.content_type
-        assert_tag 'th',
-          :attributes => {:class => "filename"},
-          :content => /issues_controller.rb\t\(révision 1484\)/
-        assert_tag 'td',
-          :attributes => {:class => /line-code/},
-          :content => /Demande créée avec succès/
-      end
-    end
-    set_tmp_attachments_directory
-  end
-
-  def test_save_diff_type
-    user1 = User.find(1)
-    user1.pref[:diff_type] = nil
-    user1.preference.save
-    user = User.find(1)
-    assert_nil user.pref[:diff_type]
-
-    @request.session[:user_id] = 1 # admin
-    get :show, :id => 5
-    assert_response :success
-    assert_template 'diff'
-    user.reload
-    assert_equal "inline", user.pref[:diff_type]
-    get :show, :id => 5, :type => 'sbs'
-    assert_response :success
-    assert_template 'diff'
-    user.reload
-    assert_equal "sbs", user.pref[:diff_type]
-  end
-
-  def test_diff_show_filename_in_mercurial_export
-    set_tmp_attachments_directory
-    a = Attachment.new(:container => Issue.find(1),
-                       :file => uploaded_test_file("hg-export.diff", "text/plain"),
-                       :author => User.find(1))
-    assert a.save
-    assert_equal 'hg-export.diff', a.filename
-
-    get :show, :id => a.id, :type => 'inline'
-    assert_response :success
-    assert_template 'diff'
-    assert_equal 'text/html', @response.content_type
-    assert_select 'th.filename', :text => 'test1.txt'
-  end
-
-  def test_show_text_file
-    get :show, :id => 4
-    assert_response :success
-    assert_template 'file'
-    assert_equal 'text/html', @response.content_type
-    set_tmp_attachments_directory
-  end
-
-  def test_show_text_file_utf_8
-    set_tmp_attachments_directory
-    a = Attachment.new(:container => Issue.find(1),
-                       :file => uploaded_test_file("japanese-utf-8.txt", "text/plain"),
-                       :author => User.find(1))
-    assert a.save
-    assert_equal 'japanese-utf-8.txt', a.filename
-
-    str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
-    str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
-
-    get :show, :id => a.id
-    assert_response :success
-    assert_template 'file'
-    assert_equal 'text/html', @response.content_type
-    assert_tag :tag => 'th',
-               :content => '1',
-               :attributes => { :class => 'line-num' },
-               :sibling => { :tag => 'td', :content => /#{str_japanese}/ }
-  end
-
-  def test_show_text_file_replace_cannot_convert_content
-    set_tmp_attachments_directory
-    with_settings :repositories_encodings => 'UTF-8' do
-      a = Attachment.new(:container => Issue.find(1),
-                         :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
-                         :author => User.find(1))
-      assert a.save
-      assert_equal 'iso8859-1.txt', a.filename
-
-      get :show, :id => a.id
-      assert_response :success
-      assert_template 'file'
-      assert_equal 'text/html', @response.content_type
-      assert_tag :tag => 'th',
-                 :content => '7',
-                 :attributes => { :class => 'line-num' },
-                 :sibling => { :tag => 'td', :content => /Demande cr\?\?e avec succ\?s/ }
-    end
-  end
-
-  def test_show_text_file_latin_1
-    set_tmp_attachments_directory
-    with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-      a = Attachment.new(:container => Issue.find(1),
-                         :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
-                         :author => User.find(1))
-      assert a.save
-      assert_equal 'iso8859-1.txt', a.filename
-
-      get :show, :id => a.id
-      assert_response :success
-      assert_template 'file'
-      assert_equal 'text/html', @response.content_type
-      assert_tag :tag => 'th',
-                 :content => '7',
-                 :attributes => { :class => 'line-num' },
-                 :sibling => { :tag => 'td', :content => /Demande créée avec succès/ }
-      end
-  end
-
-  def test_show_text_file_should_send_if_too_big
-    Setting.file_max_size_displayed = 512
-    Attachment.find(4).update_attribute :filesize, 754.kilobyte
-
-    get :show, :id => 4
-    assert_response :success
-    assert_equal 'application/x-ruby', @response.content_type
-    set_tmp_attachments_directory
-  end
-
-  def test_show_other
-    get :show, :id => 6
-    assert_response :success
-    assert_equal 'application/octet-stream', @response.content_type
-    set_tmp_attachments_directory
-  end
-
-  def test_show_file_from_private_issue_without_permission
-    get :show, :id => 15
-    assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2F15'
-    set_tmp_attachments_directory
-  end
-
-  def test_show_file_from_private_issue_with_permission
-    @request.session[:user_id] = 2
-    get :show, :id => 15
-    assert_response :success
-    assert_tag 'h2', :content => /private.diff/
-    set_tmp_attachments_directory
-  end
-
-  def test_show_file_without_container_should_be_allowed_to_author
-    set_tmp_attachments_directory
-    attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
-
-    @request.session[:user_id] = 2
-    get :show, :id => attachment.id
-    assert_response 200
-  end
-
-  def test_show_file_without_container_should_be_denied_to_other_users
-    set_tmp_attachments_directory
-    attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
-
-    @request.session[:user_id] = 3
-    get :show, :id => attachment.id
-    assert_response 403
-  end
-
-  def test_show_invalid_should_respond_with_404
-    get :show, :id => 999
-    assert_response 404
-  end
-
-  def test_download_text_file
-    get :download, :id => 4
-    assert_response :success
-    assert_equal 'application/x-ruby', @response.content_type
-    set_tmp_attachments_directory
-  end
-
-  def test_download_version_file_with_issue_tracking_disabled
-    Project.find(1).disable_module! :issue_tracking
-    get :download, :id => 9
-    assert_response :success
-  end
-
-  def test_download_should_assign_content_type_if_blank
-    Attachment.find(4).update_attribute(:content_type, '')
-
-    get :download, :id => 4
-    assert_response :success
-    assert_equal 'text/x-ruby', @response.content_type
-    set_tmp_attachments_directory
-  end
-
-  def test_download_missing_file
-    get :download, :id => 2
-    assert_response 404
-    set_tmp_attachments_directory
-  end
-
-  def test_download_should_be_denied_without_permission
-    get :download, :id => 7
-    assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fdownload%2F7'
-    set_tmp_attachments_directory
-  end
-
-  if convert_installed?
-    def test_thumbnail
-      Attachment.clear_thumbnails
-      @request.session[:user_id] = 2
-
-      get :thumbnail, :id => 16
-      assert_response :success
-      assert_equal 'image/png', response.content_type
-    end
-
-    def test_thumbnail_should_not_exceed_maximum_size
-      Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 800}
-
-      @request.session[:user_id] = 2
-      get :thumbnail, :id => 16, :size => 2000
-    end
-
-    def test_thumbnail_should_round_size
-      Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 250}
-
-      @request.session[:user_id] = 2
-      get :thumbnail, :id => 16, :size => 260
-    end
-
-    def test_thumbnail_should_return_404_for_non_image_attachment
-      @request.session[:user_id] = 2
-
-      get :thumbnail, :id => 15
-      assert_response 404
-    end
-
-    def test_thumbnail_should_return_404_if_thumbnail_generation_failed
-      Attachment.any_instance.stubs(:thumbnail).returns(nil)
-      @request.session[:user_id] = 2
-
-      get :thumbnail, :id => 16
-      assert_response 404
-    end
-
-    def test_thumbnail_should_be_denied_without_permission
-      get :thumbnail, :id => 16
-      assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fthumbnail%2F16'
-    end
-  else
-    puts '(ImageMagick convert not available)'
-  end
-
-  def test_destroy_issue_attachment
-    set_tmp_attachments_directory
-    issue = Issue.find(3)
-    @request.session[:user_id] = 2
-
-    assert_difference 'issue.attachments.count', -1 do
-      assert_difference 'Journal.count' do
-        delete :destroy, :id => 1
-        assert_redirected_to '/projects/ecookbook'
-      end
-    end
-    assert_nil Attachment.find_by_id(1)
-    j = Journal.first(:order => 'id DESC')
-    assert_equal issue, j.journalized
-    assert_equal 'attachment', j.details.first.property
-    assert_equal '1', j.details.first.prop_key
-    assert_equal 'error281.txt', j.details.first.old_value
-    assert_equal User.find(2), j.user
-  end
-
-  def test_destroy_wiki_page_attachment
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-    assert_difference 'Attachment.count', -1 do
-      delete :destroy, :id => 3
-      assert_response 302
-    end
-  end
-
-  def test_destroy_project_attachment
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-    assert_difference 'Attachment.count', -1 do
-      delete :destroy, :id => 8
-      assert_response 302
-    end
-  end
-
-  def test_destroy_version_attachment
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-    assert_difference 'Attachment.count', -1 do
-      delete :destroy, :id => 9
-      assert_response 302
-    end
-  end
-
-  def test_destroy_without_permission
-    set_tmp_attachments_directory
-    assert_no_difference 'Attachment.count' do
-      delete :destroy, :id => 3
-    end
-    assert_response 302
-    assert Attachment.find_by_id(3)
-  end
-end
--- a/.svn/pristine/94/94b0a87688b1d61b6fb66241d11ae9e0ee65fa3e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-== Redmine upgrade
-
-Redmine - project management software
-Copyright (C) 2006-2013  Jean-Philippe Lang
-http://www.redmine.org/
-
-
-== Upgrading
-
-1. Uncompress the program archive in a new directory
-
-2. Copy your database settings (RAILS_ROOT/config/database.yml)
-   and your configuration file (RAILS_ROOT/config/configuration.yml)
-   into the new config directory
-   Note: before Redmine 1.2, SMTP configuration was stored in
-   config/email.yml. It should now be stored in config/configuration.yml. 
-
-3. Copy the RAILS_ROOT/files directory content into your new installation
-   This directory contains all the attached files.
-
-4. Copy the folders of the installed plugins and themes into new installation
-   Plugins must be stored in the [redmine_root]/plugins directory
-   Themes must be stored in the [redmine_root]/public/themes directory
-
-   WARNING: plugins from your previous Redmine version may not be compatible
-   with the Redmine version you're upgrading to.
-
-5. Install the required gems by running:
-     bundle install --without development test
-
-   If ImageMagick is not installed on your system, you should skip the installation
-   of the rmagick gem using:
-     bundle install --without development test rmagick
-
-   Only the gems that are needed by the adapters you've specified in your database
-   configuration file are actually installed (eg. if your config/database.yml
-   uses the 'mysql2' adapter, then only the mysql2 gem will be installed). Don't
-   forget to re-run `bundle install` when you change config/database.yml for using
-   other database adapters.
-
-   If you need to load some gems that are not required by Redmine core (eg. fcgi),
-   you can create a file named Gemfile.local at the root of your redmine directory.
-   It will be loaded automatically when running `bundle install`.
-
-6. Generate a session store secret
-   
-   Redmine stores session data in cookies by default, which requires
-   a secret to be generated. Under the new application directory run:
-     rake generate_secret_token
-   
-   DO NOT REPLACE OR EDIT ANY OTHER FILES.
-
-7. Migrate your database
-
-   If you are upgrading to Rails 2.3.14 as part of this migration, you
-   need to upgrade the plugin migrations before running the plugin migrations
-   using:
-     rake db:migrate:upgrade_plugin_migrations RAILS_ENV="production"
-   
-   Please make a backup before doing this! Under the new application
-   directory run:
-     rake db:migrate RAILS_ENV="production"
-   
-   If you have installed any plugins, you should also run their database
-   migrations using:
-     rake db:migrate_plugins RAILS_ENV="production"
-   
-8. Clear the cache and the existing sessions by running:
-     rake tmp:cache:clear
-     rake tmp:sessions:clear
-
-9. Restart the application server (e.g. mongrel, thin, passenger)
-
-10. Finally go to "Administration -> Roles & permissions" to check/set permissions
-    for new features, if any
-
-== References
-
-* http://www.redmine.org/wiki/redmine/RedmineUpgrade
--- a/.svn/pristine/95/954503d8b00c9c216119d7e8717102d3c9f6c727.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Acts
-    module Customizable
-      def self.included(base)
-        base.extend ClassMethods
-      end
-
-      module ClassMethods
-        def acts_as_customizable(options = {})
-          return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
-          cattr_accessor :customizable_options
-          self.customizable_options = options
-          has_many :custom_values, :as => :customized,
-                                   :include => :custom_field,
-                                   :order => "#{CustomField.table_name}.position",
-                                   :dependent => :delete_all,
-                                   :validate => false
-
-          send :include, Redmine::Acts::Customizable::InstanceMethods
-          validate :validate_custom_field_values
-          after_save :save_custom_field_values
-        end
-      end
-
-      module InstanceMethods
-        def self.included(base)
-          base.extend ClassMethods
-          base.send :alias_method_chain, :reload, :custom_fields
-        end
-
-        def available_custom_fields
-          CustomField.where("type = '#{self.class.name}CustomField'").sorted.all
-        end
-
-        # Sets the values of the object's custom fields
-        # values is an array like [{'id' => 1, 'value' => 'foo'}, {'id' => 2, 'value' => 'bar'}]
-        def custom_fields=(values)
-          values_to_hash = values.inject({}) do |hash, v|
-            v = v.stringify_keys
-            if v['id'] && v.has_key?('value')
-              hash[v['id']] = v['value']
-            end
-            hash
-          end
-          self.custom_field_values = values_to_hash
-        end
-
-        # Sets the values of the object's custom fields
-        # values is a hash like {'1' => 'foo', 2 => 'bar'}
-        def custom_field_values=(values)
-          values = values.stringify_keys
-
-          custom_field_values.each do |custom_field_value|
-            key = custom_field_value.custom_field_id.to_s
-            if values.has_key?(key)
-              value = values[key]
-              if value.is_a?(Array)
-                value = value.reject(&:blank?).uniq
-                if value.empty?
-                  value << ''
-                end
-              end
-              custom_field_value.value = value
-            end
-          end
-          @custom_field_values_changed = true
-        end
-
-        def custom_field_values
-          @custom_field_values ||= available_custom_fields.collect do |field|
-            x = CustomFieldValue.new
-            x.custom_field = field
-            x.customized = self
-            if field.multiple?
-              values = custom_values.select { |v| v.custom_field == field }
-              if values.empty?
-                values << custom_values.build(:customized => self, :custom_field => field, :value => nil)
-              end
-              x.value = values.map(&:value)
-            else
-              cv = custom_values.detect { |v| v.custom_field == field }
-              cv ||= custom_values.build(:customized => self, :custom_field => field, :value => nil)
-              x.value = cv.value
-            end
-            x
-          end
-        end
-
-        def visible_custom_field_values
-          custom_field_values.select(&:visible?)
-        end
-
-        def custom_field_values_changed?
-          @custom_field_values_changed == true
-        end
-
-        def custom_value_for(c)
-          field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
-          custom_values.detect {|v| v.custom_field_id == field_id }
-        end
-
-        def custom_field_value(c)
-          field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
-          custom_field_values.detect {|v| v.custom_field_id == field_id }.try(:value)
-        end
-
-        def validate_custom_field_values
-          if new_record? || custom_field_values_changed?
-            custom_field_values.each(&:validate_value)
-          end
-        end
-
-        def save_custom_field_values
-          target_custom_values = []
-          custom_field_values.each do |custom_field_value|
-            if custom_field_value.value.is_a?(Array)
-              custom_field_value.value.each do |v|
-                target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field && cv.value == v}
-                target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field, :value => v)
-                target_custom_values << target
-              end
-            else
-              target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field}
-              target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field)
-              target.value = custom_field_value.value
-              target_custom_values << target
-            end
-          end
-          self.custom_values = target_custom_values
-          custom_values.each(&:save)
-          @custom_field_values_changed = false
-          true
-        end
-
-        def reset_custom_values!
-          @custom_field_values = nil
-          @custom_field_values_changed = true
-        end
-
-        def reload_with_custom_fields(*args)
-          @custom_field_values = nil
-          @custom_field_values_changed = false
-          reload_without_custom_fields(*args)
-        end
-
-        module ClassMethods
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/95/9557b02b329df92601cf23c4bbe77124fa8eb394.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,494 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Mailer < ActionMailer::Base
-  layout 'mailer'
-  helper :application
-  helper :issues
-  helper :custom_fields
-
-  include Redmine::I18n
-
-  def self.default_url_options
-    { :host => Setting.host_name, :protocol => Setting.protocol }
-  end
-
-  # Builds a mail for notifying to_users and cc_users about a new issue
-  def issue_add(issue, to_users, cc_users)
-    redmine_headers 'Project' => issue.project.identifier,
-                    'Issue-Id' => issue.id,
-                    'Issue-Author' => issue.author.login
-    redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
-    message_id issue
-    references issue
-    @author = issue.author
-    @issue = issue
-    @users = to_users + cc_users
-    @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)
-    mail :to => to_users.map(&:mail),
-      :cc => cc_users.map(&:mail),
-      :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
-  end
-
-  # Notifies users about a new issue
-  def self.deliver_issue_add(issue)
-    to = issue.notified_users
-    cc = issue.notified_watchers - to
-    issue.each_notification(to + cc) do |users|
-      Mailer.issue_add(issue, to & users, cc & users).deliver
-    end
-  end
-
-  # Builds a mail for notifying to_users and cc_users about an issue update
-  def issue_edit(journal, to_users, cc_users)
-    issue = journal.journalized
-    redmine_headers 'Project' => issue.project.identifier,
-                    'Issue-Id' => issue.id,
-                    'Issue-Author' => issue.author.login
-    redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
-    message_id journal
-    references issue
-    @author = journal.user
-    s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
-    s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
-    s << issue.subject
-    @issue = issue
-    @users = to_users + cc_users
-    @journal = journal
-    @journal_details = journal.visible_details(@users.first)
-    @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
-    mail :to => to_users.map(&:mail),
-      :cc => cc_users.map(&:mail),
-      :subject => s
-  end
-
-  # Notifies users about an issue update
-  def self.deliver_issue_edit(journal)
-    issue = journal.journalized.reload
-    to = journal.notified_users
-    cc = journal.notified_watchers
-    journal.each_notification(to + cc) do |users|
-      issue.each_notification(users) do |users2|
-        Mailer.issue_edit(journal, to & users2, cc & users2).deliver
-      end
-    end
-  end
-
-  def reminder(user, issues, days)
-    set_language_if_valid user.language
-    @issues = issues
-    @days = days
-    @issues_url = url_for(:controller => 'issues', :action => 'index',
-                                :set_filter => 1, :assigned_to_id => user.id,
-                                :sort => 'due_date:asc')
-    mail :to => user.mail,
-      :subject => l(:mail_subject_reminder, :count => issues.size, :days => days)
-  end
-
-  # Builds a Mail::Message object used to email users belonging to the added document's project.
-  #
-  # Example:
-  #   document_added(document) => Mail::Message object
-  #   Mailer.document_added(document).deliver => sends an email to the document's project recipients
-  def document_added(document)
-    redmine_headers 'Project' => document.project.identifier
-    @author = User.current
-    @document = document
-    @document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
-    mail :to => document.recipients,
-      :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
-  end
-
-  # Builds a Mail::Message object used to email recipients of a project when an attachements are added.
-  #
-  # Example:
-  #   attachments_added(attachments) => Mail::Message object
-  #   Mailer.attachments_added(attachments).deliver => sends an email to the project's recipients
-  def attachments_added(attachments)
-    container = attachments.first.container
-    added_to = ''
-    added_to_url = ''
-    @author = attachments.first.author
-    case container.class.name
-    when 'Project'
-      added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
-      added_to = "#{l(:label_project)}: #{container}"
-      recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
-    when 'Version'
-      added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
-      added_to = "#{l(:label_version)}: #{container.name}"
-      recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
-    when 'Document'
-      added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
-      added_to = "#{l(:label_document)}: #{container.title}"
-      recipients = container.recipients
-    end
-    redmine_headers 'Project' => container.project.identifier
-    @attachments = attachments
-    @added_to = added_to
-    @added_to_url = added_to_url
-    mail :to => recipients,
-      :subject => "[#{container.project.name}] #{l(:label_attachment_new)}"
-  end
-
-  # Builds a Mail::Message object used to email recipients of a news' project when a news item is added.
-  #
-  # Example:
-  #   news_added(news) => Mail::Message object
-  #   Mailer.news_added(news).deliver => sends an email to the news' project recipients
-  def news_added(news)
-    redmine_headers 'Project' => news.project.identifier
-    @author = news.author
-    message_id news
-    references news
-    @news = news
-    @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
-    mail :to => news.recipients,
-      :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
-  end
-
-  # Builds a Mail::Message object used to email recipients of a news' project when a news comment is added.
-  #
-  # Example:
-  #   news_comment_added(comment) => Mail::Message object
-  #   Mailer.news_comment_added(comment) => sends an email to the news' project recipients
-  def news_comment_added(comment)
-    news = comment.commented
-    redmine_headers 'Project' => news.project.identifier
-    @author = comment.author
-    message_id comment
-    references news
-    @news = news
-    @comment = comment
-    @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
-    mail :to => news.recipients,
-     :cc => news.watcher_recipients,
-     :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
-  end
-
-  # Builds a Mail::Message object used to email the recipients of the specified message that was posted.
-  #
-  # Example:
-  #   message_posted(message) => Mail::Message object
-  #   Mailer.message_posted(message).deliver => sends an email to the recipients
-  def message_posted(message)
-    redmine_headers 'Project' => message.project.identifier,
-                    'Topic-Id' => (message.parent_id || message.id)
-    @author = message.author
-    message_id message
-    references message.root
-    recipients = message.recipients
-    cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients)
-    @message = message
-    @message_url = url_for(message.event_url)
-    mail :to => recipients,
-      :cc => cc,
-      :subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
-  end
-
-  # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was added.
-  #
-  # Example:
-  #   wiki_content_added(wiki_content) => Mail::Message object
-  #   Mailer.wiki_content_added(wiki_content).deliver => sends an email to the project's recipients
-  def wiki_content_added(wiki_content)
-    redmine_headers 'Project' => wiki_content.project.identifier,
-                    'Wiki-Page-Id' => wiki_content.page.id
-    @author = wiki_content.author
-    message_id wiki_content
-    recipients = wiki_content.recipients
-    cc = wiki_content.page.wiki.watcher_recipients - recipients
-    @wiki_content = wiki_content
-    @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
-                                      :project_id => wiki_content.project,
-                                      :id => wiki_content.page.title)
-    mail :to => recipients,
-      :cc => cc,
-      :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
-  end
-
-  # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was updated.
-  #
-  # Example:
-  #   wiki_content_updated(wiki_content) => Mail::Message object
-  #   Mailer.wiki_content_updated(wiki_content).deliver => sends an email to the project's recipients
-  def wiki_content_updated(wiki_content)
-    redmine_headers 'Project' => wiki_content.project.identifier,
-                    'Wiki-Page-Id' => wiki_content.page.id
-    @author = wiki_content.author
-    message_id wiki_content
-    recipients = wiki_content.recipients
-    cc = wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients
-    @wiki_content = wiki_content
-    @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
-                                      :project_id => wiki_content.project,
-                                      :id => wiki_content.page.title)
-    @wiki_diff_url = url_for(:controller => 'wiki', :action => 'diff',
-                                   :project_id => wiki_content.project, :id => wiki_content.page.title,
-                                   :version => wiki_content.version)
-    mail :to => recipients,
-      :cc => cc,
-      :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
-  end
-
-  # Builds a Mail::Message object used to email the specified user their account information.
-  #
-  # Example:
-  #   account_information(user, password) => Mail::Message object
-  #   Mailer.account_information(user, password).deliver => sends account information to the user
-  def account_information(user, password)
-    set_language_if_valid user.language
-    @user = user
-    @password = password
-    @login_url = url_for(:controller => 'account', :action => 'login')
-    mail :to => user.mail,
-      :subject => l(:mail_subject_register, Setting.app_title)
-  end
-
-  # Builds a Mail::Message object used to email all active administrators of an account activation request.
-  #
-  # Example:
-  #   account_activation_request(user) => Mail::Message object
-  #   Mailer.account_activation_request(user).deliver => sends an email to all active administrators
-  def account_activation_request(user)
-    # Send the email to all active administrators
-    recipients = User.active.where(:admin => true).all.collect { |u| u.mail }.compact
-    @user = user
-    @url = url_for(:controller => 'users', :action => 'index',
-                         :status => User::STATUS_REGISTERED,
-                         :sort_key => 'created_on', :sort_order => 'desc')
-    mail :to => recipients,
-      :subject => l(:mail_subject_account_activation_request, Setting.app_title)
-  end
-
-  # Builds a Mail::Message object used to email the specified user that their account was activated by an administrator.
-  #
-  # Example:
-  #   account_activated(user) => Mail::Message object
-  #   Mailer.account_activated(user).deliver => sends an email to the registered user
-  def account_activated(user)
-    set_language_if_valid user.language
-    @user = user
-    @login_url = url_for(:controller => 'account', :action => 'login')
-    mail :to => user.mail,
-      :subject => l(:mail_subject_register, Setting.app_title)
-  end
-
-  def lost_password(token)
-    set_language_if_valid(token.user.language)
-    @token = token
-    @url = url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
-    mail :to => token.user.mail,
-      :subject => l(:mail_subject_lost_password, Setting.app_title)
-  end
-
-  def register(token)
-    set_language_if_valid(token.user.language)
-    @token = token
-    @url = url_for(:controller => 'account', :action => 'activate', :token => token.value)
-    mail :to => token.user.mail,
-      :subject => l(:mail_subject_register, Setting.app_title)
-  end
-
-  def test_email(user)
-    set_language_if_valid(user.language)
-    @url = url_for(:controller => 'welcome')
-    mail :to => user.mail,
-      :subject => 'Redmine test'
-  end
-
-  # Sends reminders to issue assignees
-  # Available options:
-  # * :days     => how many days in the future to remind about (defaults to 7)
-  # * :tracker  => id of tracker for filtering issues (defaults to all trackers)
-  # * :project  => id or identifier of project to process (defaults to all projects)
-  # * :users    => array of user/group ids who should be reminded
-  def self.reminders(options={})
-    days = options[:days] || 7
-    project = options[:project] ? Project.find(options[:project]) : nil
-    tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
-    user_ids = options[:users]
-
-    scope = Issue.open.where("#{Issue.table_name}.assigned_to_id IS NOT NULL" +
-      " AND #{Project.table_name}.status = #{Project::STATUS_ACTIVE}" +
-      " AND #{Issue.table_name}.due_date <= ?", days.day.from_now.to_date
-    )
-    scope = scope.where(:assigned_to_id => user_ids) if user_ids.present?
-    scope = scope.where(:project_id => project.id) if project
-    scope = scope.where(:tracker_id => tracker.id) if tracker
-
-    issues_by_assignee = scope.includes(:status, :assigned_to, :project, :tracker).all.group_by(&:assigned_to)
-    issues_by_assignee.keys.each do |assignee|
-      if assignee.is_a?(Group)
-        assignee.users.each do |user|
-          issues_by_assignee[user] ||= []
-          issues_by_assignee[user] += issues_by_assignee[assignee]
-        end
-      end
-    end
-
-    issues_by_assignee.each do |assignee, issues|
-      reminder(assignee, issues, days).deliver if assignee.is_a?(User) && assignee.active?
-    end
-  end
-
-  # Activates/desactivates email deliveries during +block+
-  def self.with_deliveries(enabled = true, &block)
-    was_enabled = ActionMailer::Base.perform_deliveries
-    ActionMailer::Base.perform_deliveries = !!enabled
-    yield
-  ensure
-    ActionMailer::Base.perform_deliveries = was_enabled
-  end
-
-  # Sends emails synchronously in the given block
-  def self.with_synched_deliveries(&block)
-    saved_method = ActionMailer::Base.delivery_method
-    if m = saved_method.to_s.match(%r{^async_(.+)$})
-      synched_method = m[1]
-      ActionMailer::Base.delivery_method = synched_method.to_sym
-      ActionMailer::Base.send "#{synched_method}_settings=", ActionMailer::Base.send("async_#{synched_method}_settings")
-    end
-    yield
-  ensure
-    ActionMailer::Base.delivery_method = saved_method
-  end
-
-  def mail(headers={}, &block)
-    headers.merge! 'X-Mailer' => 'Redmine',
-            'X-Redmine-Host' => Setting.host_name,
-            'X-Redmine-Site' => Setting.app_title,
-            'X-Auto-Response-Suppress' => 'OOF',
-            'Auto-Submitted' => 'auto-generated',
-            'From' => Setting.mail_from,
-            'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>"
-
-    # Removes the author from the recipients and cc
-    # if the author does not want to receive notifications
-    # about what the author do
-    if @author && @author.logged? && @author.pref.no_self_notified
-      headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
-      headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
-    end
-
-    if @author && @author.logged?
-      redmine_headers 'Sender' => @author.login
-    end
-
-    # Blind carbon copy recipients
-    if Setting.bcc_recipients?
-      headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
-      headers[:to] = nil
-      headers[:cc] = nil
-    end
-
-    if @message_id_object
-      headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
-    end
-    if @references_objects
-      headers[:references] = @references_objects.collect {|o| "<#{self.class.references_for(o)}>"}.join(' ')
-    end
-
-    m = if block_given?
-      super headers, &block
-    else
-      super headers do |format|
-        format.text
-        format.html unless Setting.plain_text_mail?
-      end
-    end
-    set_language_if_valid @initial_language
-
-    m
-  end
-
-  def initialize(*args)
-    @initial_language = current_language
-    set_language_if_valid Setting.default_language
-    super
-  end
-
-  def self.deliver_mail(mail)
-    return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
-    begin
-      # Log errors when raise_delivery_errors is set to false, Rails does not
-      mail.raise_delivery_errors = true
-      super
-    rescue Exception => e
-      if ActionMailer::Base.raise_delivery_errors
-        raise e
-      else
-        Rails.logger.error "Email delivery error: #{e.message}"
-      end
-    end
-  end
-
-  def self.method_missing(method, *args, &block)
-    if m = method.to_s.match(%r{^deliver_(.+)$})
-      ActiveSupport::Deprecation.warn "Mailer.deliver_#{m[1]}(*args) is deprecated. Use Mailer.#{m[1]}(*args).deliver instead."
-      send(m[1], *args).deliver
-    else
-      super
-    end
-  end
-
-  private
-
-  # Appends a Redmine header field (name is prepended with 'X-Redmine-')
-  def redmine_headers(h)
-    h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
-  end
-
-  def self.token_for(object, rand=true)
-    timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
-    hash = [
-      "redmine",
-      "#{object.class.name.demodulize.underscore}-#{object.id}",
-      timestamp.strftime("%Y%m%d%H%M%S")
-    ]
-    if rand
-      hash << Redmine::Utils.random_hex(8)
-    end
-    host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
-    host = "#{::Socket.gethostname}.redmine" if host.empty?
-    "#{hash.join('.')}@#{host}"
-  end
-
-  # Returns a Message-Id for the given object
-  def self.message_id_for(object)
-    token_for(object, true)
-  end
-
-  # Returns a uniq token for a given object referenced by all notifications
-  # related to this object
-  def self.references_for(object)
-    token_for(object, false)
-  end
-
-  def message_id(object)
-    @message_id_object = object
-  end
-
-  def references(object)
-    @references_objects ||= []
-    @references_objects << object
-  end
-
-  def mylogger
-    Rails.logger
-  end
-end
--- a/.svn/pristine/96/96d2cda457836fbee33580894c1a138879e9a89e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Comment < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  belongs_to :commented, :polymorphic => true, :counter_cache => true
-  belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
-
-  validates_presence_of :commented, :author, :comments
-
-  after_create :send_notification
-
-  safe_attributes 'comments'
-
-  private
-
-  def send_notification
-    mailer_method = "#{commented.class.name.underscore}_comment_added"
-    if Setting.notified_events.include?(mailer_method)
-      Mailer.send(mailer_method, self).deliver
-    end
-  end
-end
--- a/.svn/pristine/97/978f900709ed8de466a8e142aefeff25cb8293df.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module SearchHelper
-  def highlight_tokens(text, tokens)
-    return text unless text && tokens && !tokens.empty?
-    re_tokens = tokens.collect {|t| Regexp.escape(t)}
-    regexp = Regexp.new "(#{re_tokens.join('|')})", Regexp::IGNORECASE
-    result = ''
-    text.split(regexp).each_with_index do |words, i|
-      if result.length > 1200
-        # maximum length of the preview reached
-        result << '...'
-        break
-      end
-      words = words.mb_chars
-      if i.even?
-        result << h(words.length > 100 ? "#{words.slice(0..44)} ... #{words.slice(-45..-1)}" : words)
-      else
-        t = (tokens.index(words.downcase) || 0) % 4
-        result << content_tag('span', h(words), :class => "highlight token-#{t}")
-      end
-    end
-    result.html_safe
-  end
-
-  def type_label(t)
-    l("label_#{t.singularize}_plural", :default => t.to_s.humanize)
-  end
-
-  def project_select_tag
-    options = [[l(:label_project_all), 'all']]
-    options << [l(:label_my_projects), 'my_projects'] unless User.current.memberships.empty?
-    options << [l(:label_and_its_subprojects, @project.name), 'subprojects'] unless @project.nil? || @project.descendants.active.empty?
-    options << [@project.name, ''] unless @project.nil?
-    label_tag("scope", l(:description_project_scope), :class => "hidden-for-sighted") +
-    select_tag('scope', options_for_select(options, params[:scope].to_s)) if options.size > 1
-  end
-
-  def render_results_by_type(results_by_type)
-    links = []
-    # Sorts types by results count
-    results_by_type.keys.sort {|a, b| results_by_type[b] <=> results_by_type[a]}.each do |t|
-      c = results_by_type[t]
-      next if c == 0
-      text = "#{type_label(t)} (#{c})"
-      links << link_to(h(text), :q => params[:q], :titles_only => params[:titles_only],
-                       :all_words => params[:all_words], :scope => params[:scope], t => 1)
-    end
-    ('<ul>'.html_safe +
-        links.map {|link| content_tag('li', link)}.join(' ').html_safe + 
-        '</ul>'.html_safe) unless links.empty?
-  end
-end
--- a/.svn/pristine/97/9797245a3a92458105708d0f347a48be95b75b9b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,475 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine #:nodoc:
-
-  class PluginNotFound < StandardError; end
-  class PluginRequirementError < StandardError; end
-
-  # Base class for Redmine plugins.
-  # Plugins are registered using the <tt>register</tt> class method that acts as the public constructor.
-  #
-  #   Redmine::Plugin.register :example do
-  #     name 'Example plugin'
-  #     author 'John Smith'
-  #     description 'This is an example plugin for Redmine'
-  #     version '0.0.1'
-  #     settings :default => {'foo'=>'bar'}, :partial => 'settings/settings'
-  #   end
-  #
-  # === Plugin attributes
-  #
-  # +settings+ is an optional attribute that let the plugin be configurable.
-  # It must be a hash with the following keys:
-  # * <tt>:default</tt>: default value for the plugin settings
-  # * <tt>:partial</tt>: path of the configuration partial view, relative to the plugin <tt>app/views</tt> directory
-  # Example:
-  #   settings :default => {'foo'=>'bar'}, :partial => 'settings/settings'
-  # In this example, the settings partial will be found here in the plugin directory: <tt>app/views/settings/_settings.rhtml</tt>.
-  #
-  # When rendered, the plugin settings value is available as the local variable +settings+
-  class Plugin
-    cattr_accessor :directory
-    self.directory = File.join(Rails.root, 'plugins')
-
-    cattr_accessor :public_directory
-    self.public_directory = File.join(Rails.root, 'public', 'plugin_assets')
-
-    @registered_plugins = {}
-    class << self
-      attr_reader :registered_plugins
-      private :new
-
-      def def_field(*names)
-        class_eval do
-          names.each do |name|
-            define_method(name) do |*args|
-              args.empty? ? instance_variable_get("@#{name}") : instance_variable_set("@#{name}", *args)
-            end
-          end
-        end
-      end
-    end
-    def_field :name, :description, :url, :author, :author_url, :version, :settings, :directory
-    attr_reader :id
-
-    # Plugin constructor
-    def self.register(id, &block)
-      p = new(id)
-      p.instance_eval(&block)
-
-      # Set a default name if it was not provided during registration
-      p.name(id.to_s.humanize) if p.name.nil?
-      # Set a default directory if it was not provided during registration
-      p.directory(File.join(self.directory, id.to_s)) if p.directory.nil?
-
-      # Adds plugin locales if any
-      # YAML translation files should be found under <plugin>/config/locales/
-      ::I18n.load_path += Dir.glob(File.join(p.directory, 'config', 'locales', '*.yml'))
-
-      # Prepends the app/views directory of the plugin to the view path
-      view_path = File.join(p.directory, 'app', 'views')
-      if File.directory?(view_path)
-        ActionController::Base.prepend_view_path(view_path)
-        ActionMailer::Base.prepend_view_path(view_path)
-      end
-
-      # Adds the app/{controllers,helpers,models} directories of the plugin to the autoload path
-      Dir.glob File.expand_path(File.join(p.directory, 'app', '{controllers,helpers,models}')) do |dir|
-        ActiveSupport::Dependencies.autoload_paths += [dir]
-      end
-
-      registered_plugins[id] = p
-    end
-
-    # Returns an array of all registered plugins
-    def self.all
-      registered_plugins.values.sort
-    end
-
-    # Finds a plugin by its id
-    # Returns a PluginNotFound exception if the plugin doesn't exist
-    def self.find(id)
-      registered_plugins[id.to_sym] || raise(PluginNotFound)
-    end
-
-    # Clears the registered plugins hash
-    # It doesn't unload installed plugins
-    def self.clear
-      @registered_plugins = {}
-    end
-
-    # Checks if a plugin is installed
-    #
-    # @param [String] id name of the plugin
-    def self.installed?(id)
-      registered_plugins[id.to_sym].present?
-    end
-
-    def self.load
-      Dir.glob(File.join(self.directory, '*')).sort.each do |directory|
-        if File.directory?(directory)
-          lib = File.join(directory, "lib")
-          if File.directory?(lib)
-            $:.unshift lib
-            ActiveSupport::Dependencies.autoload_paths += [lib]
-          end
-          initializer = File.join(directory, "init.rb")
-          if File.file?(initializer)
-            require initializer
-          end
-        end
-      end
-    end
-
-    def initialize(id)
-      @id = id.to_sym
-    end
-
-    def public_directory
-      File.join(self.class.public_directory, id.to_s)
-    end
-
-    def to_param
-      id
-    end
-
-    def assets_directory
-      File.join(directory, 'assets')
-    end
-
-    def <=>(plugin)
-      self.id.to_s <=> plugin.id.to_s
-    end
-
-    # Sets a requirement on Redmine version
-    # Raises a PluginRequirementError exception if the requirement is not met
-    #
-    # Examples
-    #   # Requires Redmine 0.7.3 or higher
-    #   requires_redmine :version_or_higher => '0.7.3'
-    #   requires_redmine '0.7.3'
-    #
-    #   # Requires Redmine 0.7.x or higher
-    #   requires_redmine '0.7'
-    #
-    #   # Requires a specific Redmine version
-    #   requires_redmine :version => '0.7.3'              # 0.7.3 only
-    #   requires_redmine :version => '0.7'                # 0.7.x
-    #   requires_redmine :version => ['0.7.3', '0.8.0']   # 0.7.3 or 0.8.0
-    #
-    #   # Requires a Redmine version within a range
-    #   requires_redmine :version => '0.7.3'..'0.9.1'     # >= 0.7.3 and <= 0.9.1
-    #   requires_redmine :version => '0.7'..'0.9'         # >= 0.7.x and <= 0.9.x
-    def requires_redmine(arg)
-      arg = { :version_or_higher => arg } unless arg.is_a?(Hash)
-      arg.assert_valid_keys(:version, :version_or_higher)
-
-      current = Redmine::VERSION.to_a
-      arg.each do |k, req|
-        case k
-        when :version_or_higher
-          raise ArgumentError.new(":version_or_higher accepts a version string only") unless req.is_a?(String)
-          unless compare_versions(req, current) <= 0
-            raise PluginRequirementError.new("#{id} plugin requires Redmine #{req} or higher but current is #{current.join('.')}")
-          end
-        when :version
-          req = [req] if req.is_a?(String)
-          if req.is_a?(Array)
-            unless req.detect {|ver| compare_versions(ver, current) == 0}
-              raise PluginRequirementError.new("#{id} plugin requires one the following Redmine versions: #{req.join(', ')} but current is #{current.join('.')}")
-            end
-          elsif req.is_a?(Range)
-            unless compare_versions(req.first, current) <= 0 && compare_versions(req.last, current) >= 0
-              raise PluginRequirementError.new("#{id} plugin requires a Redmine version between #{req.first} and #{req.last} but current is #{current.join('.')}")
-            end
-          else
-            raise ArgumentError.new(":version option accepts a version string, an array or a range of versions")
-          end
-        end
-      end
-      true
-    end
-
-    def compare_versions(requirement, current)
-      requirement = requirement.split('.').collect(&:to_i)
-      requirement <=> current.slice(0, requirement.size)
-    end
-    private :compare_versions
-
-    # Sets a requirement on a Redmine plugin version
-    # Raises a PluginRequirementError exception if the requirement is not met
-    #
-    # Examples
-    #   # Requires a plugin named :foo version 0.7.3 or higher
-    #   requires_redmine_plugin :foo, :version_or_higher => '0.7.3'
-    #   requires_redmine_plugin :foo, '0.7.3'
-    #
-    #   # Requires a specific version of a Redmine plugin
-    #   requires_redmine_plugin :foo, :version => '0.7.3'              # 0.7.3 only
-    #   requires_redmine_plugin :foo, :version => ['0.7.3', '0.8.0']   # 0.7.3 or 0.8.0
-    def requires_redmine_plugin(plugin_name, arg)
-      arg = { :version_or_higher => arg } unless arg.is_a?(Hash)
-      arg.assert_valid_keys(:version, :version_or_higher)
-
-      plugin = Plugin.find(plugin_name)
-      current = plugin.version.split('.').collect(&:to_i)
-
-      arg.each do |k, v|
-        v = [] << v unless v.is_a?(Array)
-        versions = v.collect {|s| s.split('.').collect(&:to_i)}
-        case k
-        when :version_or_higher
-          raise ArgumentError.new("wrong number of versions (#{versions.size} for 1)") unless versions.size == 1
-          unless (current <=> versions.first) >= 0
-            raise PluginRequirementError.new("#{id} plugin requires the #{plugin_name} plugin #{v} or higher but current is #{current.join('.')}")
-          end
-        when :version
-          unless versions.include?(current.slice(0,3))
-            raise PluginRequirementError.new("#{id} plugin requires one the following versions of #{plugin_name}: #{v.join(', ')} but current is #{current.join('.')}")
-          end
-        end
-      end
-      true
-    end
-
-    # Adds an item to the given +menu+.
-    # The +id+ parameter (equals to the project id) is automatically added to the url.
-    #   menu :project_menu, :plugin_example, { :controller => 'example', :action => 'say_hello' }, :caption => 'Sample'
-    #
-    # +name+ parameter can be: :top_menu, :account_menu, :application_menu or :project_menu
-    #
-    def menu(menu, item, url, options={})
-      Redmine::MenuManager.map(menu).push(item, url, options)
-    end
-    alias :add_menu_item :menu
-
-    # Removes +item+ from the given +menu+.
-    def delete_menu_item(menu, item)
-      Redmine::MenuManager.map(menu).delete(item)
-    end
-
-    # Defines a permission called +name+ for the given +actions+.
-    #
-    # The +actions+ argument is a hash with controllers as keys and actions as values (a single value or an array):
-    #   permission :destroy_contacts, { :contacts => :destroy }
-    #   permission :view_contacts, { :contacts => [:index, :show] }
-    #
-    # The +options+ argument is a hash that accept the following keys:
-    # * :public => the permission is public if set to true (implicitly given to any user)
-    # * :require => can be set to one of the following values to restrict users the permission can be given to: :loggedin, :member
-    # * :read => set it to true so that the permission is still granted on closed projects
-    #
-    # Examples
-    #   # A permission that is implicitly given to any user
-    #   # This permission won't appear on the Roles & Permissions setup screen
-    #   permission :say_hello, { :example => :say_hello }, :public => true, :read => true
-    #
-    #   # A permission that can be given to any user
-    #   permission :say_hello, { :example => :say_hello }
-    #
-    #   # A permission that can be given to registered users only
-    #   permission :say_hello, { :example => :say_hello }, :require => :loggedin
-    #
-    #   # A permission that can be given to project members only
-    #   permission :say_hello, { :example => :say_hello }, :require => :member
-    def permission(name, actions, options = {})
-      if @project_module
-        Redmine::AccessControl.map {|map| map.project_module(@project_module) {|map|map.permission(name, actions, options)}}
-      else
-        Redmine::AccessControl.map {|map| map.permission(name, actions, options)}
-      end
-    end
-
-    # Defines a project module, that can be enabled/disabled for each project.
-    # Permissions defined inside +block+ will be bind to the module.
-    #
-    #   project_module :things do
-    #     permission :view_contacts, { :contacts => [:list, :show] }, :public => true
-    #     permission :destroy_contacts, { :contacts => :destroy }
-    #   end
-    def project_module(name, &block)
-      @project_module = name
-      self.instance_eval(&block)
-      @project_module = nil
-    end
-
-    # Registers an activity provider.
-    #
-    # Options:
-    # * <tt>:class_name</tt> - one or more model(s) that provide these events (inferred from event_type by default)
-    # * <tt>:default</tt> - setting this option to false will make the events not displayed by default
-    #
-    # A model can provide several activity event types.
-    #
-    # Examples:
-    #   register :news
-    #   register :scrums, :class_name => 'Meeting'
-    #   register :issues, :class_name => ['Issue', 'Journal']
-    #
-    # Retrieving events:
-    # Associated model(s) must implement the find_events class method.
-    # ActiveRecord models can use acts_as_activity_provider as a way to implement this class method.
-    #
-    # The following call should return all the scrum events visible by current user that occured in the 5 last days:
-    #   Meeting.find_events('scrums', User.current, 5.days.ago, Date.today)
-    #   Meeting.find_events('scrums', User.current, 5.days.ago, Date.today, :project => foo) # events for project foo only
-    #
-    # Note that :view_scrums permission is required to view these events in the activity view.
-    def activity_provider(*args)
-      Redmine::Activity.register(*args)
-    end
-
-    # Registers a wiki formatter.
-    #
-    # Parameters:
-    # * +name+ - human-readable name
-    # * +formatter+ - formatter class, which should have an instance method +to_html+
-    # * +helper+ - helper module, which will be included by wiki pages
-    def wiki_format_provider(name, formatter, helper)
-      Redmine::WikiFormatting.register(name, formatter, helper)
-    end
-
-    # Returns +true+ if the plugin can be configured.
-    def configurable?
-      settings && settings.is_a?(Hash) && !settings[:partial].blank?
-    end
-
-    def mirror_assets
-      source = assets_directory
-      destination = public_directory
-      return unless File.directory?(source)
-
-      source_files = Dir[source + "/**/*"]
-      source_dirs = source_files.select { |d| File.directory?(d) }
-      source_files -= source_dirs
-
-      unless source_files.empty?
-        base_target_dir = File.join(destination, File.dirname(source_files.first).gsub(source, ''))
-        begin
-          FileUtils.mkdir_p(base_target_dir)
-        rescue Exception => e
-          raise "Could not create directory #{base_target_dir}: " + e.message
-        end
-      end
-
-      source_dirs.each do |dir|
-        # strip down these paths so we have simple, relative paths we can
-        # add to the destination
-        target_dir = File.join(destination, dir.gsub(source, ''))
-        begin
-          FileUtils.mkdir_p(target_dir)
-        rescue Exception => e
-          raise "Could not create directory #{target_dir}: " + e.message
-        end
-      end
-
-      source_files.each do |file|
-        begin
-          target = File.join(destination, file.gsub(source, ''))
-          unless File.exist?(target) && FileUtils.identical?(file, target)
-            FileUtils.cp(file, target)
-          end
-        rescue Exception => e
-          raise "Could not copy #{file} to #{target}: " + e.message
-        end
-      end
-    end
-
-    # Mirrors assets from one or all plugins to public/plugin_assets
-    def self.mirror_assets(name=nil)
-      if name.present?
-        find(name).mirror_assets
-      else
-        all.each do |plugin|
-          plugin.mirror_assets
-        end
-      end
-    end
-
-    # The directory containing this plugin's migrations (<tt>plugin/db/migrate</tt>)
-    def migration_directory
-      File.join(Rails.root, 'plugins', id.to_s, 'db', 'migrate')
-    end
-
-    # Returns the version number of the latest migration for this plugin. Returns
-    # nil if this plugin has no migrations.
-    def latest_migration
-      migrations.last
-    end
-
-    # Returns the version numbers of all migrations for this plugin.
-    def migrations
-      migrations = Dir[migration_directory+"/*.rb"]
-      migrations.map { |p| File.basename(p).match(/0*(\d+)\_/)[1].to_i }.sort
-    end
-
-    # Migrate this plugin to the given version
-    def migrate(version = nil)
-      puts "Migrating #{id} (#{name})..."
-      Redmine::Plugin::Migrator.migrate_plugin(self, version)
-    end
-
-    # Migrates all plugins or a single plugin to a given version
-    # Exemples:
-    #   Plugin.migrate
-    #   Plugin.migrate('sample_plugin')
-    #   Plugin.migrate('sample_plugin', 1)
-    #
-    def self.migrate(name=nil, version=nil)
-      if name.present?
-        find(name).migrate(version)
-      else
-        all.each do |plugin|
-          plugin.migrate
-        end
-      end
-    end
-
-    class Migrator < ActiveRecord::Migrator
-      # We need to be able to set the 'current' plugin being migrated.
-      cattr_accessor :current_plugin
-
-      class << self
-        # Runs the migrations from a plugin, up (or down) to the version given
-        def migrate_plugin(plugin, version)
-          self.current_plugin = plugin
-          return if current_version(plugin) == version
-          migrate(plugin.migration_directory, version)
-        end
-
-        def current_version(plugin=current_plugin)
-          # Delete migrations that don't match .. to_i will work because the number comes first
-          ::ActiveRecord::Base.connection.select_values(
-            "SELECT version FROM #{schema_migrations_table_name}"
-          ).delete_if{ |v| v.match(/-#{plugin.id}/) == nil }.map(&:to_i).max || 0
-        end
-      end
-
-      def migrated
-        sm_table = self.class.schema_migrations_table_name
-        ::ActiveRecord::Base.connection.select_values(
-          "SELECT version FROM #{sm_table}"
-        ).delete_if{ |v| v.match(/-#{current_plugin.id}/) == nil }.map(&:to_i).sort
-      end
-
-      def record_version_state_after_migrating(version)
-        super(version.to_s + "-" + current_plugin.id.to_s)
-      end
-    end
-  end
-end
--- a/.svn/pristine/97/97bd979cf7f818b35efc479635225a7f42cd4140.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-<%= labelled_fields_for :issue, @issue do |f| %>
-<%= call_hook(:view_issues_form_details_top, { :issue => @issue, :form => f }) %>
-
-<% if @issue.safe_attribute? 'is_private' %>
-<p style="float:right; margin-right:1em;">
-  <%= f.check_box :is_private, :no_label => true %><label class="inline" for="issue_is_private" id="issue_is_private_label"><%= l(:field_is_private) %></label>
-</p>
-<% end %>
-
-<% if @issue.safe_attribute? 'project_id' %>
-<p><%= f.select :project_id, project_tree_options_for_select(@issue.allowed_target_projects, :selected => @issue.project), {:required => true},
-                :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %></p>
-<% end %>
-
-<% if @issue.safe_attribute? 'tracker_id' %>
-<p><%= f.select :tracker_id, @issue.project.trackers.collect {|t| [t.name, t.id]}, {:required => true},
-                :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %></p>
-<% end %>
-
-<% if @issue.safe_attribute? 'subject' %>
-<p><%= f.text_field :subject, :size => 80, :maxlength => 255, :required => true %></p>
-<% end %>
-
-<% if @issue.safe_attribute? 'description' %>
-<p>
-  <%= f.label_for_field :description, :required => @issue.required_attribute?('description') %>
-  <%= link_to_function image_tag('edit.png'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @issue.new_record? %>
-  <%= content_tag 'span', :id => "issue_description_and_toolbar", :style => (@issue.new_record? ? nil : 'display:none') do %>
-    <%= f.text_area :description,
-                   :cols => 60,
-                   :rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
-                   :accesskey => accesskey(:edit),
-                   :class => 'wiki-edit',
-                   :no_label => true %>
-  <% end %>
-</p>
-<%= wikitoolbar_for 'issue_description' %>
-<% end %>
-
-<div id="attributes" class="attributes">
-  <%= render :partial => 'issues/attributes' %>
-</div>
-
-<%= call_hook(:view_issues_form_details_bottom, { :issue => @issue, :form => f }) %>
-<% end %>
--- a/.svn/pristine/97/97cf218fc7442945a6c4ade29d3288030034a7d6.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class CustomFieldsController < ApplicationController
-  layout 'admin'
-
-  before_filter :require_admin
-  before_filter :build_new_custom_field, :only => [:new, :create]
-  before_filter :find_custom_field, :only => [:edit, :update, :destroy]
-  accept_api_auth :index
-
-  def index
-    respond_to do |format|
-      format.html {
-        @custom_fields_by_type = CustomField.all.group_by {|f| f.class.name }
-        @tab = params[:tab] || 'IssueCustomField'
-      }
-      format.api {
-        @custom_fields = CustomField.all
-      }
-    end
-  end
-
-  def new
-  end
-
-  def create
-    if @custom_field.save
-      flash[:notice] = l(:notice_successful_create)
-      call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
-      redirect_to custom_fields_path(:tab => @custom_field.class.name)
-    else
-      render :action => 'new'
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    if @custom_field.update_attributes(params[:custom_field])
-      flash[:notice] = l(:notice_successful_update)
-      call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
-      redirect_to custom_fields_path(:tab => @custom_field.class.name)
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def destroy
-    begin
-      @custom_field.destroy
-    rescue
-      flash[:error] = l(:error_can_not_delete_custom_field)
-    end
-    redirect_to custom_fields_path(:tab => @custom_field.class.name)
-  end
-
-  private
-
-  def build_new_custom_field
-    @custom_field = CustomField.new_subclass_instance(params[:type], params[:custom_field])
-    if @custom_field.nil?
-      render_404
-    else
-      @custom_field.default_value = nil
-    end
-  end
-
-  def find_custom_field
-    @custom_field = CustomField.find(params[:id])
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/97/97df7b6827e22c2665eace13dd5952db27af0ff3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueStatusesControllerTest < ActionController::TestCase
-  fixtures :issue_statuses, :issues, :users
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 1 # admin
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-  end
-  
-  def test_index_by_anonymous_should_redirect_to_login_form
-    @request.session[:user_id] = nil
-    get :index
-    assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fissue_statuses'
-  end
-  
-  def test_index_by_user_should_respond_with_406
-    @request.session[:user_id] = 2
-    get :index
-    assert_response 406
-  end
-
-  def test_new
-    get :new
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_create
-    assert_difference 'IssueStatus.count' do
-      post :create, :issue_status => {:name => 'New status'}
-    end
-    assert_redirected_to :action => 'index'
-    status = IssueStatus.order('id DESC').first
-    assert_equal 'New status', status.name
-  end
-
-  def test_create_with_failure
-    post :create, :issue_status => {:name => ''}
-    assert_response :success
-    assert_template 'new'
-    assert_error_tag :content => /name can&#x27;t be blank/i
-  end
-
-  def test_edit
-    get :edit, :id => '3'
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_update
-    put :update, :id => '3', :issue_status => {:name => 'Renamed status'}
-    assert_redirected_to :action => 'index'
-    status = IssueStatus.find(3)
-    assert_equal 'Renamed status', status.name
-  end
-
-  def test_update_with_failure
-    put :update, :id => '3', :issue_status => {:name => ''}
-    assert_response :success
-    assert_template 'edit'
-    assert_error_tag :content => /name can&#x27;t be blank/i
-  end
-
-  def test_destroy
-    Issue.delete_all("status_id = 1")
-
-    assert_difference 'IssueStatus.count', -1 do
-      delete :destroy, :id => '1'
-    end
-    assert_redirected_to :action => 'index'
-    assert_nil IssueStatus.find_by_id(1)
-  end
-
-  def test_destroy_should_block_if_status_in_use
-    assert_not_nil Issue.find_by_status_id(1)
-
-    assert_no_difference 'IssueStatus.count' do
-      delete :destroy, :id => '1'
-    end
-    assert_redirected_to :action => 'index'
-    assert_not_nil IssueStatus.find_by_id(1)
-  end
-
-  def test_update_issue_done_ratio_with_issue_done_ratio_set_to_issue_field
-    with_settings :issue_done_ratio => 'issue_field' do
-      post :update_issue_done_ratio
-      assert_match /not updated/, flash[:error].to_s
-      assert_redirected_to '/issue_statuses'
-    end
-  end
-
-  def test_update_issue_done_ratio_with_issue_done_ratio_set_to_issue_status
-    with_settings :issue_done_ratio => 'issue_status' do
-      post :update_issue_done_ratio
-      assert_match /Issue done ratios updated/, flash[:notice].to_s
-      assert_redirected_to '/issue_statuses'
-    end
-  end
-end
--- a/.svn/pristine/98/9804b3e3abfd00a58dec9be4b531677efbf34d66.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class MenuManagerTest < ActionController::IntegrationTest
-  include Redmine::I18n
-
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def test_project_menu_with_specific_locale
-    get 'projects/ecookbook/issues', { }, 'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
-
-    assert_tag :div, :attributes => { :id => 'main-menu' },
-                     :descendant => { :tag => 'li', :child => { :tag => 'a', :content => ll('fr', :label_activity),
-                                                                             :attributes => { :href => '/projects/ecookbook/activity',
-                                                                                              :class => 'activity' } } }
-    assert_tag :div, :attributes => { :id => 'main-menu' },
-                     :descendant => { :tag => 'li', :child => { :tag => 'a', :content => ll('fr', :label_issue_plural),
-                                                                             :attributes => { :href => '/projects/ecookbook/issues',
-                                                                                              :class => 'issues selected' } } }
-  end
-
-  def test_project_menu_with_additional_menu_items
-    Setting.default_language = 'en'
-    assert_no_difference 'Redmine::MenuManager.items(:project_menu).size' do
-      Redmine::MenuManager.map :project_menu do |menu|
-        menu.push :foo, { :controller => 'projects', :action => 'show' }, :caption => 'Foo'
-        menu.push :bar, { :controller => 'projects', :action => 'show' }, :before => :activity
-        menu.push :hello, { :controller => 'projects', :action => 'show' }, :caption => Proc.new {|p| p.name.upcase }, :after => :bar
-      end
-
-      get 'projects/ecookbook'
-      assert_tag :div, :attributes => { :id => 'main-menu' },
-                       :descendant => { :tag => 'li', :child => { :tag => 'a', :content => 'Foo',
-                                                                               :attributes => { :class => 'foo' } } }
-
-      assert_tag :div, :attributes => { :id => 'main-menu' },
-                       :descendant => { :tag => 'li', :child => { :tag => 'a', :content => 'Bar',
-                                                                               :attributes => { :class => 'bar' } },
-                                                      :before => { :tag => 'li', :child => { :tag => 'a', :content => 'ECOOKBOOK' } } }
-
-      assert_tag :div, :attributes => { :id => 'main-menu' },
-                       :descendant => { :tag => 'li', :child => { :tag => 'a', :content => 'ECOOKBOOK',
-                                                                               :attributes => { :class => 'hello' } },
-                                                      :before => { :tag => 'li', :child => { :tag => 'a', :content => 'Activity' } } }
-
-      # Remove the menu items
-      Redmine::MenuManager.map :project_menu do |menu|
-        menu.delete :foo
-        menu.delete :bar
-        menu.delete :hello
-      end
-    end
-  end
-end
--- a/.svn/pristine/99/994c6e124b87f66f87d072585f0635b097da8f7b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class SysControllerTest < ActionController::TestCase
-  fixtures :projects, :repositories, :enabled_modules
-
-  def setup
-    Setting.sys_api_enabled = '1'
-    Setting.enabled_scm = %w(Subversion Git)
-  end
-
-  def teardown
-    Setting.clear_cache
-  end
-
-  def test_projects_with_repository_enabled
-    get :projects
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    with_options :tag => 'projects' do |test|
-      test.assert_tag :children => { :count  => Project.active.has_module(:repository).count }
-      test.assert_tag 'project', :child => {:tag => 'identifier', :sibling => {:tag => 'is-public'}}
-    end
-    assert_no_tag 'extra-info'
-    assert_no_tag 'extra_info'
-  end
-
-  def test_create_project_repository
-    assert_nil Project.find(4).repository
-
-    post :create_project_repository, :id => 4,
-                                     :vendor => 'Subversion',
-                                     :repository => { :url => 'file:///create/project/repository/subproject2'}
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-
-    r = Project.find(4).repository
-    assert r.is_a?(Repository::Subversion)
-    assert_equal 'file:///create/project/repository/subproject2', r.url
-    
-    assert_tag 'repository-subversion',
-      :child => {
-        :tag => 'id', :content => r.id.to_s,
-        :sibling => {:tag => 'url', :content => r.url}
-      }
-    assert_no_tag 'extra-info'
-    assert_no_tag 'extra_info'
-  end
-
-  def test_create_already_existing
-    post :create_project_repository, :id => 1,
-      :vendor => 'Subversion',
-      :repository => { :url => 'file:///create/project/repository/subproject2'}
-
-    assert_response :conflict
-  end
-
-  def test_create_with_failure
-    post :create_project_repository, :id => 4,
-      :vendor => 'Subversion',
-      :repository => { :url => 'invalid url'}
-
-    assert_response :unprocessable_entity
-  end
-
-  def test_fetch_changesets
-    Repository::Subversion.any_instance.expects(:fetch_changesets).twice.returns(true)
-    get :fetch_changesets
-    assert_response :success
-  end
-
-  def test_fetch_changesets_one_project_by_identifier
-    Repository::Subversion.any_instance.expects(:fetch_changesets).once.returns(true)
-    get :fetch_changesets, :id => 'ecookbook'
-    assert_response :success
-  end
-
-  def test_fetch_changesets_one_project_by_id
-    Repository::Subversion.any_instance.expects(:fetch_changesets).once.returns(true)
-    get :fetch_changesets, :id => '1'
-    assert_response :success
-  end
-
-  def test_fetch_changesets_unknown_project
-    get :fetch_changesets, :id => 'unknown'
-    assert_response 404
-  end
-
-  def test_disabled_ws_should_respond_with_403_error
-    with_settings :sys_api_enabled => '0' do
-      get :projects
-      assert_response 403
-    end
-  end
-
-  def test_api_key
-    with_settings :sys_api_key => 'my_secret_key' do
-      get :projects, :key => 'my_secret_key'
-      assert_response :success
-    end
-  end
-
-  def test_wrong_key_should_respond_with_403_error
-    with_settings :sys_api_enabled => 'my_secret_key' do
-      get :projects, :key => 'wrong_key'
-      assert_response 403
-    end
-  end
-end
--- a/.svn/pristine/99/997678775f2af1af27b63a8490e45d609905f797.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class BoardsController < ApplicationController
-  default_search_scope :messages
-  before_filter :find_project_by_project_id, :find_board_if_available, :authorize
-  accept_rss_auth :index, :show
-
-  helper :sort
-  include SortHelper
-  helper :watchers
-
-  def index
-    @boards = @project.boards.includes(:project, :last_message => :author).all
-    # show the board if there is only one
-    if @boards.size == 1
-      @board = @boards.first
-      show
-    end
-  end
-
-  def show
-    respond_to do |format|
-      format.html {
-        sort_init 'updated_on', 'desc'
-        sort_update 'created_on' => "#{Message.table_name}.created_on",
-                    'replies' => "#{Message.table_name}.replies_count",
-                    'updated_on' => "COALESCE(last_replies_messages.created_on, #{Message.table_name}.created_on)"
-
-        @topic_count = @board.topics.count
-        @topic_pages = Paginator.new @topic_count, per_page_option, params['page']
-        @topics =  @board.topics.
-          reorder("#{Message.table_name}.sticky DESC").
-          includes(:last_reply).
-          limit(@topic_pages.per_page).
-          offset(@topic_pages.offset).
-          order(sort_clause).
-          preload(:author, {:last_reply => :author}).
-          all
-        @message = Message.new(:board => @board)
-        render :action => 'show', :layout => !request.xhr?
-      }
-      format.atom {
-        @messages = @board.messages.
-          reorder('created_on DESC').
-          includes(:author, :board).
-          limit(Setting.feeds_limit.to_i).
-          all
-        render_feed(@messages, :title => "#{@project}: #{@board}")
-      }
-    end
-  end
-
-  def new
-    @board = @project.boards.build
-    @board.safe_attributes = params[:board]
-  end
-
-  def create
-    @board = @project.boards.build
-    @board.safe_attributes = params[:board]
-    if @board.save
-      flash[:notice] = l(:notice_successful_create)
-      redirect_to_settings_in_projects
-    else
-      render :action => 'new'
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    @board.safe_attributes = params[:board]
-    if @board.save
-      redirect_to_settings_in_projects
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def destroy
-    @board.destroy
-    redirect_to_settings_in_projects
-  end
-
-private
-  def redirect_to_settings_in_projects
-    redirect_to settings_project_path(@project, :tab => 'boards')
-  end
-
-  def find_board_if_available
-    @board = @project.boards.find(params[:id]) if params[:id]
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/9a/9a40b8d61a3b252d9bf2afe70d0ed928e7cbe617.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Views
-    class ApiTemplateHandler
-      def self.call(template)
-        "Redmine::Views::Builders.for(params[:format], request, response) do |api|; #{template.source}; self.output_buffer = api.output; end"
-      end
-    end
-  end
-end
--- a/.svn/pristine/9a/9acee3f273053af6824f9d963f851333a4619eb2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class DocumentCategoryTest < ActiveSupport::TestCase
-  fixtures :enumerations, :documents, :issues
-
-  def test_should_be_an_enumeration
-    assert DocumentCategory.ancestors.include?(Enumeration)
-  end
-
-  def test_objects_count
-    assert_equal 2, DocumentCategory.find_by_name("Uncategorized").objects_count
-    assert_equal 0, DocumentCategory.find_by_name("User documentation").objects_count
-  end
-
-  def test_option_name
-    assert_equal :enumeration_doc_categories, DocumentCategory.new.option_name
-  end
-
-  def test_default
-    assert_nil DocumentCategory.where(:is_default => true).first
-    e = Enumeration.find_by_name('Technical documentation')
-    e.update_attributes(:is_default => true)
-    assert_equal 3, DocumentCategory.default.id
-  end
-
-  def test_force_default
-    assert_nil DocumentCategory.where(:is_default => true).first
-    assert_equal 1, DocumentCategory.default.id
-  end
-end
--- a/.svn/pristine/9b/9b3e5b07fcd5813f8a0dc3f62a18ba58010c1bee.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::IssueCategoriesTest < Redmine::ApiTest::Base
-  fixtures :projects, :users, :issue_categories, :issues,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /projects/:project_id/issue_categories.xml should return the issue categories" do
-    get '/projects/1/issue_categories.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'issue_categories',
-      :child => {:tag => 'issue_category', :child => {:tag => 'id', :content => '2'}}
-  end
-
-  test "GET /issue_categories/:id.xml should return the issue category" do
-    get '/issue_categories/2.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'issue_category',
-      :child => {:tag => 'id', :content => '2'}
-  end
-
-  test "POST /projects/:project_id/issue_categories.xml should return create issue category" do
-    assert_difference 'IssueCategory.count' do
-      post '/projects/1/issue_categories.xml', {:issue_category => {:name => 'API'}}, credentials('jsmith')
-    end
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-
-    category = IssueCategory.first(:order => 'id DESC')
-    assert_equal 'API', category.name
-    assert_equal 1, category.project_id
-  end
-
-  test "POST /projects/:project_id/issue_categories.xml with invalid parameters should return errors" do
-    assert_no_difference 'IssueCategory.count' do
-      post '/projects/1/issue_categories.xml', {:issue_category => {:name => ''}}, credentials('jsmith')
-    end
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', @response.content_type
-
-    assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
-  end
-
-  test "PUT /issue_categories/:id.xml with valid parameters should update the issue category" do
-    assert_no_difference 'IssueCategory.count' do
-      put '/issue_categories/2.xml', {:issue_category => {:name => 'API Update'}}, credentials('jsmith')
-    end
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_equal 'API Update', IssueCategory.find(2).name
-  end
-
-  test "PUT /issue_categories/:id.xml with invalid parameters should return errors" do
-    assert_no_difference 'IssueCategory.count' do
-      put '/issue_categories/2.xml', {:issue_category => {:name => ''}}, credentials('jsmith')
-    end
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', @response.content_type
-
-    assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
-  end
-
-  test "DELETE /issue_categories/:id.xml should destroy the issue category" do
-    assert_difference 'IssueCategory.count', -1 do
-      delete '/issue_categories/1.xml', {}, credentials('jsmith')
-    end
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_nil IssueCategory.find_by_id(1)
-  end
-    
-  test "DELETE /issue_categories/:id.xml should reassign issues with :reassign_to_id param" do
-    issue_count = Issue.where(:category_id => 1).count
-    assert issue_count > 0
-
-    assert_difference 'IssueCategory.count', -1 do
-      assert_difference 'Issue.where(:category_id => 2).count', 3 do
-        delete '/issue_categories/1.xml', {:reassign_to_id => 2}, credentials('jsmith')
-      end
-    end
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_nil IssueCategory.find_by_id(1)
-  end
-end
--- a/.svn/pristine/9c/9ccedbf66a9f47b4ce6ada31cc7d30c26f464002.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingActivitiesTest < ActionController::IntegrationTest
-  def test_activities
-    assert_routing(
-           { :method => 'get', :path => "/activity" },
-           { :controller => 'activities', :action => 'index' }
-        )
-    assert_routing(
-           { :method => 'get', :path => "/activity.atom" },
-           { :controller => 'activities', :action => 'index', :format => 'atom' }
-        )
-    assert_routing(
-        { :method => 'get', :path => "/projects/33/activity" },
-        { :controller => 'activities', :action => 'index', :id => '33' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/33/activity.atom" },
-        { :controller => 'activities', :action => 'index', :id => '33',
-          :format => 'atom' }
-      )
-  end
-end
--- a/.svn/pristine/9f/9f118459c4368ff4d85087a360e2fc5dc451c4fe.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,262 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class ProjectsController < ApplicationController
-  menu_item :overview
-  menu_item :roadmap, :only => :roadmap
-  menu_item :settings, :only => :settings
-
-  before_filter :find_project, :except => [ :index, :list, :new, :create, :copy ]
-  before_filter :authorize, :except => [ :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy]
-  before_filter :authorize_global, :only => [:new, :create]
-  before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ]
-  accept_rss_auth :index
-  accept_api_auth :index, :show, :create, :update, :destroy
-
-  after_filter :only => [:create, :edit, :update, :archive, :unarchive, :destroy] do |controller|
-    if controller.request.post?
-      controller.send :expire_action, :controller => 'welcome', :action => 'robots'
-    end
-  end
-
-  helper :sort
-  include SortHelper
-  helper :custom_fields
-  include CustomFieldsHelper
-  helper :issues
-  helper :queries
-  include QueriesHelper
-  helper :repositories
-  include RepositoriesHelper
-  include ProjectsHelper
-  helper :members
-
-  # Lists visible projects
-  def index
-    respond_to do |format|
-      format.html {
-        scope = Project
-        unless params[:closed]
-          scope = scope.active
-        end
-        @projects = scope.visible.order('lft').all
-      }
-      format.api  {
-        @offset, @limit = api_offset_and_limit
-        @project_count = Project.visible.count
-        @projects = Project.visible.offset(@offset).limit(@limit).order('lft').all
-      }
-      format.atom {
-        projects = Project.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).all
-        render_feed(projects, :title => "#{Setting.app_title}: #{l(:label_project_latest)}")
-      }
-    end
-  end
-
-  def new
-    @issue_custom_fields = IssueCustomField.sorted.all
-    @trackers = Tracker.sorted.all
-    @project = Project.new
-    @project.safe_attributes = params[:project]
-  end
-
-  def create
-    @issue_custom_fields = IssueCustomField.sorted.all
-    @trackers = Tracker.sorted.all
-    @project = Project.new
-    @project.safe_attributes = params[:project]
-
-    if validate_parent_id && @project.save
-      @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
-      # Add current user as a project member if current user is not admin
-      unless User.current.admin?
-        r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
-        m = Member.new(:user => User.current, :roles => [r])
-        @project.members << m
-      end
-      respond_to do |format|
-        format.html {
-          flash[:notice] = l(:notice_successful_create)
-          if params[:continue]
-            attrs = {:parent_id => @project.parent_id}.reject {|k,v| v.nil?}
-            redirect_to new_project_path(attrs)
-          else
-            redirect_to settings_project_path(@project)
-          end
-        }
-        format.api  { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
-      end
-    else
-      respond_to do |format|
-        format.html { render :action => 'new' }
-        format.api  { render_validation_errors(@project) }
-      end
-    end
-  end
-
-  def copy
-    @issue_custom_fields = IssueCustomField.sorted.all
-    @trackers = Tracker.sorted.all
-    @source_project = Project.find(params[:id])
-    if request.get?
-      @project = Project.copy_from(@source_project)
-      @project.identifier = Project.next_identifier if Setting.sequential_project_identifiers?
-    else
-      Mailer.with_deliveries(params[:notifications] == '1') do
-        @project = Project.new
-        @project.safe_attributes = params[:project]
-        if validate_parent_id && @project.copy(@source_project, :only => params[:only])
-          @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
-          flash[:notice] = l(:notice_successful_create)
-          redirect_to settings_project_path(@project)
-        elsif !@project.new_record?
-          # Project was created
-          # But some objects were not copied due to validation failures
-          # (eg. issues from disabled trackers)
-          # TODO: inform about that
-          redirect_to settings_project_path(@project)
-        end
-      end
-    end
-  rescue ActiveRecord::RecordNotFound
-    # source_project not found
-    render_404
-  end
-
-  # Show @project
-  def show
-    # try to redirect to the requested menu item
-    if params[:jump] && redirect_to_project_menu_item(@project, params[:jump])
-      return
-    end
-
-    @users_by_role = @project.users_by_role
-    @subprojects = @project.children.visible.all
-    @news = @project.news.limit(5).includes(:author, :project).reorder("#{News.table_name}.created_on DESC").all
-    @trackers = @project.rolled_up_trackers
-
-    cond = @project.project_condition(Setting.display_subprojects_issues?)
-
-    @open_issues_by_tracker = Issue.visible.open.where(cond).count(:group => :tracker)
-    @total_issues_by_tracker = Issue.visible.where(cond).count(:group => :tracker)
-
-    if User.current.allowed_to?(:view_time_entries, @project)
-      @total_hours = TimeEntry.visible.where(cond).sum(:hours).to_f
-    end
-
-    @key = User.current.rss_key
-
-    respond_to do |format|
-      format.html
-      format.api
-    end
-  end
-
-  def settings
-    @issue_custom_fields = IssueCustomField.sorted.all
-    @issue_category ||= IssueCategory.new
-    @member ||= @project.members.new
-    @trackers = Tracker.sorted.all
-    @wiki ||= @project.wiki
-  end
-
-  def edit
-  end
-
-  def update
-    @project.safe_attributes = params[:project]
-    if validate_parent_id && @project.save
-      @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
-      respond_to do |format|
-        format.html {
-          flash[:notice] = l(:notice_successful_update)
-          redirect_to settings_project_path(@project)
-        }
-        format.api  { render_api_ok }
-      end
-    else
-      respond_to do |format|
-        format.html {
-          settings
-          render :action => 'settings'
-        }
-        format.api  { render_validation_errors(@project) }
-      end
-    end
-  end
-
-  def modules
-    @project.enabled_module_names = params[:enabled_module_names]
-    flash[:notice] = l(:notice_successful_update)
-    redirect_to settings_project_path(@project, :tab => 'modules')
-  end
-
-  def archive
-    if request.post?
-      unless @project.archive
-        flash[:error] = l(:error_can_not_archive_project)
-      end
-    end
-    redirect_to admin_projects_path(:status => params[:status])
-  end
-
-  def unarchive
-    @project.unarchive if request.post? && !@project.active?
-    redirect_to admin_projects_path(:status => params[:status])
-  end
-
-  def close
-    @project.close
-    redirect_to project_path(@project)
-  end
-
-  def reopen
-    @project.reopen
-    redirect_to project_path(@project)
-  end
-
-  # Delete @project
-  def destroy
-    @project_to_destroy = @project
-    if api_request? || params[:confirm]
-      @project_to_destroy.destroy
-      respond_to do |format|
-        format.html { redirect_to admin_projects_path }
-        format.api  { render_api_ok }
-      end
-    end
-    # hide project in layout
-    @project = nil
-  end
-
-  private
-
-  # Validates parent_id param according to user's permissions
-  # TODO: move it to Project model in a validation that depends on User.current
-  def validate_parent_id
-    return true if User.current.admin?
-    parent_id = params[:project] && params[:project][:parent_id]
-    if parent_id || @project.new_record?
-      parent = parent_id.blank? ? nil : Project.find_by_id(parent_id.to_i)
-      unless @project.allowed_parents.include?(parent)
-        @project.errors.add :parent_id, :invalid
-        return false
-      end
-    end
-    true
-  end
-end
--- a/.svn/pristine/9f/9f1ac231e02337e90b8fc44a90ad7c28bf25d85b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WikiContentTest < ActiveSupport::TestCase
-  fixtures :projects, :enabled_modules,
-           :users, :members, :member_roles, :roles,
-           :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
-
-  def setup
-    @wiki = Wiki.find(1)
-    @page = @wiki.pages.first
-  end
-
-  def test_create
-    page = WikiPage.new(:wiki => @wiki, :title => "Page")
-    page.content = WikiContent.new(:text => "Content text", :author => User.find(1), :comments => "My comment")
-    assert page.save
-    page.reload
-
-    content = page.content
-    assert_kind_of WikiContent, content
-    assert_equal 1, content.version
-    assert_equal 1, content.versions.length
-    assert_equal "Content text", content.text
-    assert_equal "My comment", content.comments
-    assert_equal User.find(1), content.author
-    assert_equal content.text, content.versions.last.text
-  end
-
-  def test_create_should_send_email_notification
-    ActionMailer::Base.deliveries.clear
-    page = WikiPage.new(:wiki => @wiki, :title => "A new page")
-    page.content = WikiContent.new(:text => "Content text", :author => User.find(1), :comments => "My comment")
-
-    with_settings :default_language => 'en', :notified_events => %w(wiki_content_added) do
-      assert page.save
-    end
-
-    assert_equal 1, ActionMailer::Base.deliveries.size
-    assert_include 'wiki page has been added', mail_body(ActionMailer::Base.deliveries.last)
-  end
-
-  def test_update_should_be_versioned
-    content = @page.content
-    version_count = content.version
-    content.text = "My new content"
-    assert_difference 'WikiContent::Version.count' do
-      assert content.save
-    end
-    content.reload
-    assert_equal version_count+1, content.version
-    assert_equal version_count+1, content.versions.length
-
-    version = WikiContent::Version.first(:order => 'id DESC')
-    assert_equal @page.id, version.page_id
-    assert_equal '', version.compression
-    assert_equal "My new content", version.data
-    assert_equal "My new content", version.text
-  end
-
-  def test_update_with_gzipped_history
-    with_settings :wiki_compression => 'gzip' do
-      content = @page.content
-      content.text = "My new content"
-      assert_difference 'WikiContent::Version.count' do
-        assert content.save
-      end
-    end
-
-    version = WikiContent::Version.first(:order => 'id DESC')
-    assert_equal @page.id, version.page_id
-    assert_equal 'gzip', version.compression
-    assert_not_equal "My new content", version.data
-    assert_equal "My new content", version.text
-  end
-
-  def test_update_should_send_email_notification
-    ActionMailer::Base.deliveries.clear
-    content = @page.content
-    content.text = "My new content"
-
-    with_settings :notified_events => %w(wiki_content_updated) do
-      assert content.save
-    end
-
-    assert_equal 1, ActionMailer::Base.deliveries.size
-    assert_include 'wiki page has been updated', mail_body(ActionMailer::Base.deliveries.last)
-  end
-
-  def test_fetch_history
-    assert !@page.content.versions.empty?
-    @page.content.versions.each do |version|
-      assert_kind_of String, version.text
-    end
-  end
-
-  def test_large_text_should_not_be_truncated_to_64k
-    page = WikiPage.new(:wiki => @wiki, :title => "Big page")
-    page.content = WikiContent.new(:text => "a" * 500.kilobyte, :author => User.find(1))
-    assert page.save
-    page.reload
-    assert_equal 500.kilobyte, page.content.text.size
-  end
-
-  def test_current_version
-    content = WikiContent.find(11)
-    assert_equal true, content.current_version?
-    assert_equal true, content.versions.first(:order => 'version DESC').current_version?
-    assert_equal false, content.versions.first(:order => 'version ASC').current_version?
-  end
-
-  def test_previous_for_first_version_should_return_nil
-    content = WikiContent::Version.find_by_page_id_and_version(1, 1)
-    assert_nil content.previous
-  end
-
-  def test_previous_for_version_should_return_previous_version
-    content = WikiContent::Version.find_by_page_id_and_version(1, 3)
-    assert_not_nil content.previous
-    assert_equal 2, content.previous.version
-  end
-
-  def test_previous_for_version_with_gap_should_return_previous_available_version
-    WikiContent::Version.find_by_page_id_and_version(1, 2).destroy
-
-    content = WikiContent::Version.find_by_page_id_and_version(1, 3)
-    assert_not_nil content.previous
-    assert_equal 1, content.previous.version
-  end
-
-  def test_next_for_last_version_should_return_nil
-    content = WikiContent::Version.find_by_page_id_and_version(1, 3)
-    assert_nil content.next
-  end
-
-  def test_next_for_version_should_return_next_version
-    content = WikiContent::Version.find_by_page_id_and_version(1, 1)
-    assert_not_nil content.next
-    assert_equal 2, content.next.version
-  end
-
-  def test_next_for_version_with_gap_should_return_next_available_version
-    WikiContent::Version.find_by_page_id_and_version(1, 2).destroy
-
-    content = WikiContent::Version.find_by_page_id_and_version(1, 1)
-    assert_not_nil content.next
-    assert_equal 3, content.next.version
-  end
-end
--- a/.svn/pristine/9f/9fd9de5370e8b7489081f79cbc0f65cb941662d5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,425 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesSubversionControllerTest < ActionController::TestCase
-  tests RepositoriesController
-
-  fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
-           :repositories, :issues, :issue_statuses, :changesets, :changes,
-           :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers
-
-  PRJ_ID = 3
-  NUM_REV = 11
-
-  def setup
-    Setting.default_language = 'en'
-    User.current = nil
-
-    @project = Project.find(PRJ_ID)
-    @repository = Repository::Subversion.create(:project => @project,
-               :url => self.class.subversion_repository_url)
-    assert @repository
-  end
-
-  if repository_configured?('subversion')
-    def test_new
-      @request.session[:user_id] = 1
-      @project.repository.destroy
-      get :new, :project_id => 'subproject1', :repository_scm => 'Subversion'
-      assert_response :success
-      assert_template 'new'
-      assert_kind_of Repository::Subversion, assigns(:repository)
-      assert assigns(:repository).new_record?
-    end
-
-    def test_show
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_not_nil assigns(:changesets)
-
-      entry = assigns(:entries).detect {|e| e.name == 'subversion_test'}
-      assert_not_nil entry
-      assert_equal 'dir', entry.kind
-      assert_select 'tr.dir a[href=/projects/subproject1/repository/show/subversion_test]'
-
-      assert_tag 'input', :attributes => {:name => 'rev'}
-      assert_tag 'a', :content => 'Statistics'
-      assert_tag 'a', :content => 'Atom'
-      assert_tag :tag => 'a',
-                 :attributes => {:href => '/projects/subproject1/repository'},
-                 :content => 'root'
-    end
-
-    def test_show_non_default
-      Repository::Subversion.create(:project => @project,
-        :url => self.class.subversion_repository_url,
-        :is_default => false, :identifier => 'svn')
-
-      get :show, :id => PRJ_ID, :repository_id => 'svn'
-      assert_response :success
-      assert_template 'show'
-      assert_select 'tr.dir a[href=/projects/subproject1/repository/svn/show/subversion_test]'
-      # Repository menu should link to the main repo
-      assert_select '#main-menu a[href=/projects/subproject1/repository]'
-    end
-
-    def test_browse_directory
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['subversion_test'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal [
-           '[folder_with_brackets]', 'folder', '.project',
-           'helloworld.c', 'textfile.txt'
-         ],
-        assigns(:entries).collect(&:name)
-      entry = assigns(:entries).detect {|e| e.name == 'helloworld.c'}
-      assert_equal 'file', entry.kind
-      assert_equal 'subversion_test/helloworld.c', entry.path
-      assert_tag :a, :content => 'helloworld.c', :attributes => { :class => /text\-x\-c/ }
-    end
-
-    def test_browse_at_given_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['subversion_test'])[:param],
-          :rev => 4
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['folder', '.project', 'helloworld.c', 'helloworld.rb', 'textfile.txt'],
-                   assigns(:entries).collect(&:name)
-    end
-
-    def test_file_changes
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :changes, :id => PRJ_ID,
-          :path => repository_path_hash(['subversion_test', 'folder', 'helloworld.rb'])[:param]
-      assert_response :success
-      assert_template 'changes'
-
-      changesets = assigns(:changesets)
-      assert_not_nil changesets
-      assert_equal %w(6 3 2), changesets.collect(&:revision)
-
-      # svn properties displayed with svn >= 1.5 only
-      if Redmine::Scm::Adapters::SubversionAdapter.client_version_above?([1, 5, 0])
-        assert_not_nil assigns(:properties)
-        assert_equal 'native', assigns(:properties)['svn:eol-style']
-        assert_tag :ul,
-                   :child => { :tag => 'li',
-                               :child => { :tag => 'b', :content => 'svn:eol-style' },
-                               :child => { :tag => 'span', :content => 'native' } }
-      end
-    end
-
-    def test_directory_changes
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :changes, :id => PRJ_ID,
-          :path => repository_path_hash(['subversion_test', 'folder'])[:param]
-      assert_response :success
-      assert_template 'changes'
-
-      changesets = assigns(:changesets)
-      assert_not_nil changesets
-      assert_equal %w(10 9 7 6 5 2), changesets.collect(&:revision)
-    end
-
-    def test_entry
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
-      assert_response :success
-      assert_template 'entry'
-    end
-
-    def test_entry_should_send_if_too_big
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      # no files in the test repo is larger than 1KB...
-      with_settings :file_max_size_displayed => 0 do
-        get :entry, :id => PRJ_ID,
-            :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
-        assert_response :success
-        assert_equal 'attachment; filename="helloworld.c"',
-                     @response.headers['Content-Disposition']
-      end
-    end
-
-    def test_entry_should_send_images_inline
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['subversion_test', 'folder', 'subfolder', 'rubylogo.gif'])[:param]
-      assert_response :success
-      assert_equal 'inline; filename="rubylogo.gif"', response.headers['Content-Disposition']
-    end
-
-    def test_entry_at_given_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['subversion_test', 'helloworld.rb'])[:param],
-          :rev => 2
-      assert_response :success
-      assert_template 'entry'
-      # this line was removed in r3 and file was moved in r6
-      assert_tag :tag => 'td', :attributes => { :class => /line-code/},
-                               :content => /Here's the code/
-    end
-
-    def test_entry_not_found
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['subversion_test', 'zzz.c'])[:param]
-      assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
-                 :content => /The entry or revision was not found in the repository/
-    end
-
-    def test_entry_download
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :raw, :id => PRJ_ID,
-          :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
-      assert_response :success
-      assert_equal 'attachment; filename="helloworld.c"', @response.headers['Content-Disposition']
-    end
-
-    def test_directory_entry
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['subversion_test', 'folder'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entry)
-      assert_equal 'folder', assigns(:entry).name
-    end
-
-    # TODO: this test needs fixtures.
-    def test_revision
-      get :revision, :id => 1, :rev => 2
-      assert_response :success
-      assert_template 'revision'
-
-      assert_select 'ul' do
-        assert_select 'li' do
-          # link to the entry at rev 2
-          assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/2/entry/test/some/path/in/the/repo', :text => 'repo'
-          # link to partial diff
-          assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/2/diff/test/some/path/in/the/repo'
-        end
-      end
-    end
-
-    def test_invalid_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :revision, :id => PRJ_ID, :rev => 'something_weird'
-      assert_response 404
-      assert_error_tag :content => /was not found/
-    end
-
-    def test_invalid_revision_diff
-      get :diff, :id => PRJ_ID, :rev => '1', :rev_to => 'something_weird'
-      assert_response 404
-      assert_error_tag :content => /was not found/
-    end
-
-    def test_empty_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['', ' ', nil].each do |r|
-        get :revision, :id => PRJ_ID, :rev => r
-        assert_response 404
-        assert_error_tag :content => /was not found/
-      end
-    end
-
-    # TODO: this test needs fixtures.
-    def test_revision_with_repository_pointing_to_a_subdirectory
-      r = Project.find(1).repository
-      # Changes repository url to a subdirectory
-      r.update_attribute :url, (r.url + '/test/some')
-
-      get :revision, :id => 1, :rev => 2
-      assert_response :success
-      assert_template 'revision'
-
-      assert_select 'ul' do
-        assert_select 'li' do
-          # link to the entry at rev 2
-          assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/2/entry/path/in/the/repo', :text => 'repo'
-          # link to partial diff
-          assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/2/diff/path/in/the/repo'
-        end
-      end
-    end
-
-    def test_revision_diff
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['inline', 'sbs'].each do |dt|
-        get :diff, :id => PRJ_ID, :rev => 3, :type => dt
-        assert_response :success
-        assert_template 'diff'
-        assert_select 'h2', :text => /Revision 3/
-        assert_select 'th.filename', :text => 'subversion_test/textfile.txt'
-      end
-    end
-
-    def test_revision_diff_raw_format
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      get :diff, :id => PRJ_ID, :rev => 5, :format => 'diff'
-      assert_response :success
-      assert_equal 'text/x-patch', @response.content_type
-      assert_equal 'Index: subversion_test/folder/greeter.rb', @response.body.split(/\r?\n/).first
-    end
-
-    def test_directory_diff
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['inline', 'sbs'].each do |dt|
-        get :diff, :id => PRJ_ID, :rev => 6, :rev_to => 2,
-            :path => repository_path_hash(['subversion_test', 'folder'])[:param],
-            :type => dt
-        assert_response :success
-        assert_template 'diff'
-
-        diff = assigns(:diff)
-        assert_not_nil diff
-        # 2 files modified
-        assert_equal 2, Redmine::UnifiedDiff.new(diff).size
-        assert_tag :tag => 'h2', :content => /2:6/
-      end
-    end
-
-    def test_annotate
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :annotate, :id => PRJ_ID,
-          :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
-      assert_response :success
-      assert_template 'annotate'
-
-      assert_select 'tr' do
-        assert_select 'th.line-num', :text => '1'
-        assert_select 'td.revision', :text => '4'
-        assert_select 'td.author', :text => 'jp'
-        assert_select 'td', :text => /stdio.h/
-      end
-      # Same revision
-      assert_select 'tr' do
-        assert_select 'th.line-num', :text => '2'
-        assert_select 'td.revision', :text => ''
-        assert_select 'td.author', :text => ''
-      end
-    end
-
-    def test_annotate_at_given_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :annotate, :id => PRJ_ID, :rev => 8,
-          :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
-      assert_response :success
-      assert_template 'annotate'
-      assert_tag :tag => 'h2', :content => /@ 8/
-    end
-
-    def test_destroy_valid_repository
-      @request.session[:user_id] = 1 # admin
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      assert_equal NUM_REV, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-
-    def test_destroy_invalid_repository
-      @request.session[:user_id] = 1 # admin
-      @project.repository.destroy
-      @repository = Repository::Subversion.create!(
-                       :project => @project,
-                       :url     => "file:///invalid")
-      @repository.fetch_changesets
-      assert_equal 0, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-  else
-    puts "Subversion test repository NOT FOUND. Skipping functional tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/a0/a004869c868a2f96a8bb7c88e2f423fbf74007bc.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,434 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
-
-  class MercurialAdapterTest < ActiveSupport::TestCase
-    HELPERS_DIR        = Redmine::Scm::Adapters::MercurialAdapter::HELPERS_DIR
-    TEMPLATE_NAME      = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_NAME
-    TEMPLATE_EXTENSION = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_EXTENSION
-
-    REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
-    CHAR_1_HEX = "\xc3\x9c"
-
-    if File.directory?(REPOSITORY_PATH)
-      def setup
-        adapter_class = Redmine::Scm::Adapters::MercurialAdapter
-        assert adapter_class
-        assert adapter_class.client_command
-        assert_equal true, adapter_class.client_available
-        assert_equal true, adapter_class.client_version_above?([0, 9, 5])
-
-        @adapter = Redmine::Scm::Adapters::MercurialAdapter.new(
-                              REPOSITORY_PATH,
-                              nil,
-                              nil,
-                              nil,
-                             'ISO-8859-1')
-        @diff_c_support = true
-        @char_1        = CHAR_1_HEX.dup
-        @tag_char_1    = "tag-#{CHAR_1_HEX}-00"
-        @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
-        @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
-        if @tag_char_1.respond_to?(:force_encoding)
-          @char_1.force_encoding('UTF-8')
-          @tag_char_1.force_encoding('UTF-8')
-          @branch_char_0.force_encoding('UTF-8')
-          @branch_char_1.force_encoding('UTF-8')
-        end
-      end
-
-      def test_hgversion
-        to_test = { "Mercurial Distributed SCM (version 0.9.5)\n"  => [0,9,5],
-                    "Mercurial Distributed SCM (1.0)\n"            => [1,0],
-                    "Mercurial Distributed SCM (1e4ddc9ac9f7+20080325)\n" => nil,
-                    "Mercurial Distributed SCM (1.0.1+20080525)\n" => [1,0,1],
-                    "Mercurial Distributed SCM (1916e629a29d)\n"   => nil,
-                    "Mercurial SCM Distribuito (versione 0.9.5)\n" => [0,9,5],
-                    "(1.6)\n(1.7)\n(1.8)"                          => [1,6],
-                    "(1.7.1)\r\n(1.8.1)\r\n(1.9.1)"                => [1,7,1]}
-
-        to_test.each do |s, v|
-          test_hgversion_for(s, v)
-        end
-      end
-
-      def test_template_path
-        to_test = {
-                    [1,2]    => "1.0",
-                    []       => "1.0",
-                    [1,2,1]  => "1.0",
-                    [1,7]    => "1.0",
-                    [1,7,1]  => "1.0",
-                    [2,0]    => "1.0",
-                   }
-        to_test.each do |v, template|
-          test_template_path_for(v, template)
-        end
-      end
-
-      def test_info
-        [REPOSITORY_PATH, REPOSITORY_PATH + "/",
-             REPOSITORY_PATH + "//"].each do |repo|
-          adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo)
-          repo_path =  adp.info.root_url.gsub(/\\/, "/")
-          assert_equal REPOSITORY_PATH, repo_path
-          assert_equal '31', adp.info.lastrev.revision
-          assert_equal '31eeee7395c8',adp.info.lastrev.scmid
-        end
-      end
-
-      def test_revisions
-        revisions = @adapter.revisions(nil, 2, 4)
-        assert_equal 3, revisions.size
-        assert_equal '2', revisions[0].revision
-        assert_equal '400bb8672109', revisions[0].scmid
-        assert_equal '4', revisions[2].revision
-        assert_equal 'def6d2f1254a', revisions[2].scmid
-
-        revisions = @adapter.revisions(nil, 2, 4, {:limit => 2})
-        assert_equal 2, revisions.size
-        assert_equal '2', revisions[0].revision
-        assert_equal '400bb8672109', revisions[0].scmid
-      end
-
-      def test_parents
-        revs1 = @adapter.revisions(nil, 0, 0)
-        assert_equal 1, revs1.size
-        assert_equal [], revs1[0].parents
-        revs2 = @adapter.revisions(nil, 1, 1)
-        assert_equal 1, revs2.size
-        assert_equal 1, revs2[0].parents.size
-        assert_equal "0885933ad4f6", revs2[0].parents[0]
-        revs3 = @adapter.revisions(nil, 30, 30)
-        assert_equal 1, revs3.size
-        assert_equal 2, revs3[0].parents.size
-        assert_equal "a94b0528f24f", revs3[0].parents[0]
-        assert_equal "3a330eb32958", revs3[0].parents[1]
-      end
-
-      def test_diff
-        if @adapter.class.client_version_above?([1, 2])
-          assert_nil @adapter.diff(nil, '100000')
-        end
-        assert_nil @adapter.diff(nil, '100000', '200000')
-        [2, '400bb8672109', '400', 400].each do |r1|
-          diff1 = @adapter.diff(nil, r1)
-          if @diff_c_support
-            assert_equal 28, diff1.size
-            buf = diff1[24].gsub(/\r\n|\r|\n/, "")
-            assert_equal "+    return true unless klass.respond_to?('watched_by')", buf
-          else
-            assert_equal 0, diff1.size
-          end
-          [4, 'def6d2f1254a'].each do |r2|
-            diff2 = @adapter.diff(nil, r1, r2)
-            assert_equal 49, diff2.size
-            buf =  diff2[41].gsub(/\r\n|\r|\n/, "")
-            assert_equal "+class WelcomeController < ApplicationController", buf
-            diff3 = @adapter.diff('sources/watchers_controller.rb', r1, r2)
-            assert_equal 20, diff3.size
-            buf =  diff3[12].gsub(/\r\n|\r|\n/, "")
-            assert_equal "+    @watched.remove_watcher(user)", buf
-
-            diff4 = @adapter.diff(nil, r2, r1)
-            assert_equal 49, diff4.size
-            buf =  diff4[41].gsub(/\r\n|\r|\n/, "")
-            assert_equal "-class WelcomeController < ApplicationController", buf
-            diff5 = @adapter.diff('sources/watchers_controller.rb', r2, r1)
-            assert_equal 20, diff5.size
-            buf =  diff5[9].gsub(/\r\n|\r|\n/, "")
-            assert_equal "-    @watched.remove_watcher(user)", buf
-          end
-        end
-      end
-
-      def test_diff_made_by_revision
-        if @diff_c_support
-          [24, '24', '4cddb4e45f52'].each do |r1|
-            diff1 = @adapter.diff(nil, r1)
-            assert_equal 5, diff1.size
-            buf = diff1[4].gsub(/\r\n|\r|\n/, "")
-            assert_equal '+0885933ad4f68d77c2649cd11f8311276e7ef7ce tag-init-revision', buf
-          end
-        end
-      end
-
-      def test_cat
-        [2, '400bb8672109', '400', 400].each do |r|
-          buf = @adapter.cat('sources/welcome_controller.rb', r)
-          assert buf
-          lines = buf.split("\r\n")
-          assert_equal 25, lines.length
-          assert_equal 'class WelcomeController < ApplicationController', lines[17]
-        end
-        assert_nil @adapter.cat('sources/welcome_controller.rb')
-      end
-
-      def test_annotate
-        assert_equal [], @adapter.annotate("sources/welcome_controller.rb").lines
-        [2, '400bb8672109', '400', 400].each do |r|
-          ann = @adapter.annotate('sources/welcome_controller.rb', r)
-          assert ann
-          assert_equal '1', ann.revisions[17].revision
-          assert_equal '9d5b5b004199', ann.revisions[17].identifier
-          assert_equal 'jsmith', ann.revisions[0].author
-          assert_equal 25, ann.lines.length
-          assert_equal 'class WelcomeController < ApplicationController', ann.lines[17]
-        end
-      end
-
-      def test_entries
-        assert_nil @adapter.entries(nil, '100000')
-
-        assert_equal 1, @adapter.entries("sources", 3).size
-        assert_equal 1, @adapter.entries("sources", 'b3a615152df8').size
-
-        [2, '400bb8672109', '400', 400].each do |r|
-          entries1 = @adapter.entries(nil, r)
-          assert entries1
-          assert_equal 3, entries1.size
-          assert_equal 'sources', entries1[1].name
-          assert_equal 'sources', entries1[1].path
-          assert_equal 'dir', entries1[1].kind
-          readme = entries1[2]
-          assert_equal 'README', readme.name
-          assert_equal 'README', readme.path
-          assert_equal 'file', readme.kind
-          assert_equal 27, readme.size
-          assert_equal '1', readme.lastrev.revision
-          assert_equal '9d5b5b004199', readme.lastrev.identifier
-          # 2007-12-14 10:24:01 +0100
-          assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
-
-          entries2 = @adapter.entries('sources', r)
-          assert entries2
-          assert_equal 2, entries2.size
-          assert_equal 'watchers_controller.rb', entries2[0].name
-          assert_equal 'sources/watchers_controller.rb', entries2[0].path
-          assert_equal 'file', entries2[0].kind
-          assert_equal 'welcome_controller.rb', entries2[1].name
-          assert_equal 'sources/welcome_controller.rb', entries2[1].path
-          assert_equal 'file', entries2[1].kind
-        end
-      end
-
-      def test_entries_tag
-        entries1 = @adapter.entries(nil, 'tag_test.00')
-        assert entries1
-        assert_equal 3, entries1.size
-        assert_equal 'sources', entries1[1].name
-        assert_equal 'sources', entries1[1].path
-        assert_equal 'dir', entries1[1].kind
-        readme = entries1[2]
-        assert_equal 'README', readme.name
-        assert_equal 'README', readme.path
-        assert_equal 'file', readme.kind
-        assert_equal 21, readme.size
-        assert_equal '0', readme.lastrev.revision
-        assert_equal '0885933ad4f6', readme.lastrev.identifier
-        # 2007-12-14 10:22:52 +0100
-        assert_equal Time.gm(2007, 12, 14, 9, 22, 52), readme.lastrev.time
-      end
-
-      def test_entries_branch
-        entries1 = @adapter.entries(nil, 'test-branch-00')
-        assert entries1
-        assert_equal 5, entries1.size
-        assert_equal 'sql_escape', entries1[2].name
-        assert_equal 'sql_escape', entries1[2].path
-        assert_equal 'dir', entries1[2].kind
-        readme = entries1[4]
-        assert_equal 'README', readme.name
-        assert_equal 'README', readme.path
-        assert_equal 'file', readme.kind
-        assert_equal 365, readme.size
-        assert_equal '8', readme.lastrev.revision
-        assert_equal 'c51f5bb613cd', readme.lastrev.identifier
-        # 2001-02-01 00:00:00 -0900
-        assert_equal Time.gm(2001, 2, 1, 9, 0, 0), readme.lastrev.time
-      end
-
-      def test_locate_on_outdated_repository
-        assert_equal 1, @adapter.entries("images", 0).size
-        assert_equal 2, @adapter.entries("images").size
-        assert_equal 2, @adapter.entries("images", 2).size
-      end
-
-      def test_access_by_nodeid
-        path = 'sources/welcome_controller.rb'
-        assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400bb8672109')
-      end
-
-      def test_access_by_fuzzy_nodeid
-        path = 'sources/welcome_controller.rb'
-        # falls back to nodeid
-        assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400')
-      end
-
-      def test_tags
-        assert_equal [@tag_char_1, 'tag_test.00', 'tag-init-revision'], @adapter.tags
-      end
-
-      def test_tagmap
-        tm = {
-          @tag_char_1         => 'adf805632193',
-          'tag_test.00'       => '6987191f453a',
-          'tag-init-revision' => '0885933ad4f6',
-          }
-        assert_equal tm, @adapter.tagmap
-      end
-
-      def test_branches
-        brs = []
-        @adapter.branches.each do |b|
-          brs << b
-        end
-        assert_equal 7, brs.length
-        assert_equal 'default', brs[0].to_s
-        assert_equal '31', brs[0].revision
-        assert_equal '31eeee7395c8', brs[0].scmid
-        assert_equal 'test-branch-01', brs[1].to_s
-        assert_equal '30', brs[1].revision
-        assert_equal 'ad4dc4f80284', brs[1].scmid
-        assert_equal @branch_char_1, brs[2].to_s
-        assert_equal '27', brs[2].revision
-        assert_equal '7bbf4c738e71', brs[2].scmid
-        assert_equal 'branch (1)[2]&,%.-3_4', brs[3].to_s
-        assert_equal '25', brs[3].revision
-        assert_equal 'afc61e85bde7', brs[3].scmid
-        assert_equal @branch_char_0, brs[4].to_s
-        assert_equal '23', brs[4].revision
-        assert_equal 'c8d3e4887474', brs[4].scmid
-        assert_equal 'test_branch.latin-1', brs[5].to_s
-        assert_equal '22', brs[5].revision
-        assert_equal 'c2ffe7da686a', brs[5].scmid
-        assert_equal 'test-branch-00', brs[6].to_s
-        assert_equal '13', brs[6].revision
-        assert_equal '3a330eb32958', brs[6].scmid
-      end
-
-      def test_branchmap
-        bm = {
-           'default'               => '31eeee7395c8',
-           'test_branch.latin-1'   => 'c2ffe7da686a',
-           'branch (1)[2]&,%.-3_4' => 'afc61e85bde7',
-           'test-branch-00'        => '3a330eb32958',
-           "test-branch-01"        => 'ad4dc4f80284',
-           @branch_char_0          => 'c8d3e4887474',
-           @branch_char_1          => '7bbf4c738e71',
-         }
-        assert_equal bm, @adapter.branchmap
-      end
-
-      def test_path_space
-        p = 'README (1)[2]&,%.-3_4'
-        [15, '933ca60293d7'].each do |r1|
-          assert @adapter.diff(p, r1)
-          assert @adapter.cat(p, r1)
-          assert_equal 1, @adapter.annotate(p, r1).lines.length
-          [25, 'afc61e85bde7'].each do |r2|
-            assert @adapter.diff(p, r1, r2)
-          end
-        end
-      end
-
-      def test_tag_non_ascii
-        p = "latin-1-dir/test-#{@char_1}-1.txt"
-        assert @adapter.cat(p, @tag_char_1)
-        assert_equal 1, @adapter.annotate(p, @tag_char_1).lines.length
-      end
-
-      def test_branch_non_ascii
-        p = "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-1.txt"
-        assert @adapter.cat(p, @branch_char_1)
-        assert_equal 1, @adapter.annotate(p, @branch_char_1).lines.length
-      end
-
-      def test_nodes_in_branch
-         [
-            'default',
-            @branch_char_1,
-            'branch (1)[2]&,%.-3_4',
-            @branch_char_0,
-            'test_branch.latin-1',
-            'test-branch-00',
-               ].each do |bra|
-          nib0 = @adapter.nodes_in_branch(bra)
-          assert nib0
-          nib1 = @adapter.nodes_in_branch(bra, :limit => 1)
-          assert_equal 1, nib1.size
-          case bra
-            when 'branch (1)[2]&,%.-3_4'
-              if @adapter.class.client_version_above?([1, 6])
-                assert_equal 3, nib0.size
-                assert_equal nib0[0], 'afc61e85bde7'
-                nib2 = @adapter.nodes_in_branch(bra, :limit => 2)
-                assert_equal 2, nib2.size
-                assert_equal nib2[1], '933ca60293d7'
-              end
-            when @branch_char_1
-              if @adapter.class.client_version_above?([1, 6])
-                assert_equal 2, nib0.size
-                assert_equal nib0[1], '08ff3227303e'
-                nib2 = @adapter.nodes_in_branch(bra, :limit => 1)
-                assert_equal 1, nib2.size
-                assert_equal nib2[0], '7bbf4c738e71'
-              end
-          end
-        end
-      end
-
-      def test_path_encoding_default_utf8
-        adpt1 = Redmine::Scm::Adapters::MercurialAdapter.new(
-                                  REPOSITORY_PATH
-                                )
-        assert_equal "UTF-8", adpt1.path_encoding
-        adpt2 = Redmine::Scm::Adapters::MercurialAdapter.new(
-                                  REPOSITORY_PATH,
-                                  nil,
-                                  nil,
-                                  nil,
-                                  ""
-                                )
-        assert_equal "UTF-8", adpt2.path_encoding
-      end
-
-      private
-
-      def test_hgversion_for(hgversion, version)
-        @adapter.class.expects(:hgversion_from_command_line).returns(hgversion)
-        assert_equal version, @adapter.class.hgversion
-      end
-
-      def test_template_path_for(version, template)
-        assert_equal "#{HELPERS_DIR}/#{TEMPLATE_NAME}-#{template}.#{TEMPLATE_EXTENSION}",
-                     @adapter.class.template_path_for(version)
-        assert File.exist?(@adapter.class.template_path_for(version))
-      end
-    else
-      puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
-    end
-  end
-rescue LoadError
-  class MercurialMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
-  end
-end
--- a/.svn/pristine/a0/a031ba3671a49b989b6b3f05b2432855669191cf.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class PrincipalTest < ActiveSupport::TestCase
-  fixtures :users, :projects, :members, :member_roles
-
-  def test_active_scope_should_return_groups_and_active_users
-    result = Principal.active.all
-    assert_include Group.first, result
-    assert_not_nil result.detect {|p| p.is_a?(User)}
-    assert_nil result.detect {|p| p.is_a?(User) && !p.active?}
-    assert_nil result.detect {|p| p.is_a?(AnonymousUser)}
-  end
-
-  def test_member_of_scope_should_return_the_union_of_all_members
-    projects = Project.find_all_by_id(1, 2)
-    assert_equal projects.map(&:principals).flatten.sort, Principal.member_of(projects).sort
-  end
-
-  def test_member_of_scope_should_be_empty_for_no_projects
-    assert_equal [], Principal.member_of([]).sort
-  end
-
-  def test_not_member_of_scope_should_return_users_that_have_no_memberships
-    projects = Project.find_all_by_id(1, 2)
-    expected = (Principal.all - projects.map(&:memberships).flatten.map(&:principal)).sort
-    assert_equal expected, Principal.not_member_of(projects).sort
-  end
-
-  def test_not_member_of_scope_should_be_empty_for_no_projects
-    assert_equal [], Principal.not_member_of([]).sort
-  end
-
-  def test_sorted_scope_should_sort_users_before_groups
-    scope = Principal.where("type <> ?", 'AnonymousUser')
-    expected_order = scope.all.sort do |a, b|
-      if a.is_a?(User) && b.is_a?(Group)
-        -1
-      elsif a.is_a?(Group) && b.is_a?(User)
-        1
-      else
-        a.name.downcase <=> b.name.downcase
-      end
-    end
-    assert_equal expected_order.map(&:name).map(&:downcase), scope.sorted.all.map(&:name).map(&:downcase)
-  end
-
-  test "like scope should search login" do
-    results = Principal.like('jsmi')
-
-    assert results.any?
-    assert results.all? {|u| u.login.match(/jsmi/i) }
-  end
-
-  test "like scope should search firstname" do
-    results = Principal.like('john')
-
-    assert results.any?
-    assert results.all? {|u| u.firstname.match(/john/i) }
-  end
-
-  test "like scope should search lastname" do
-    results = Principal.like('smi')
-
-    assert results.any?
-    assert results.all? {|u| u.lastname.match(/smi/i) }
-  end
-
-  test "like scope should search mail" do
-    results = Principal.like('somenet')
-
-    assert results.any?
-    assert results.all? {|u| u.mail.match(/somenet/i) }
-  end
-
-  test "like scope should search firstname and lastname" do
-    results = Principal.like('john smi')
-
-    assert_equal 1, results.count
-    assert_equal User.find(2), results.first
-  end
-
-  test "like scope should search lastname and firstname" do
-    results = Principal.like('smith joh')
-
-    assert_equal 1, results.count
-    assert_equal User.find(2), results.first
-  end
-
-  def test_like_scope_with_cyrillic_name
-    user = User.generate!(:firstname => 'Соболев', :lastname => 'Денис')
-    results = Principal.like('Собо')
-    assert_equal 1, results.count
-    assert_equal user, results.first
-  end
-end
--- a/.svn/pristine/a1/a15efc0a7b7f938a7d937205168f8739fcc6338f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WikiContentVersionTest < ActiveSupport::TestCase
-  fixtures :projects, :users, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
-
-  def setup
-  end
-
-  def test_destroy
-    v = WikiContent::Version.find(2)
-
-    assert_difference 'WikiContent::Version.count', -1 do
-      v.destroy
-    end
-  end
-
-  def test_destroy_last_version_should_revert_content
-    v = WikiContent::Version.find(3)
-
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_difference 'WikiContent::Version.count', -1 do
-          assert v.destroy
-        end
-      end
-    end
-    c = WikiContent.find(1)
-    v = c.versions.last
-    assert_equal 2, c.version
-    assert_equal v.version, c.version
-    assert_equal v.comments, c.comments
-    assert_equal v.text, c.text
-    assert_equal v.author, c.author
-    assert_equal v.updated_on, c.updated_on
-  end
-
-  def test_destroy_all_versions_should_delete_page
-    WikiContent::Version.find(1).destroy
-    WikiContent::Version.find(2).destroy
-    v = WikiContent::Version.find(3)
-
-    assert_difference 'WikiPage.count', -1 do
-      assert_difference 'WikiContent.count', -1 do
-        assert_difference 'WikiContent::Version.count', -1 do
-          assert v.destroy
-        end
-      end
-    end
-    assert_nil WikiPage.find_by_id(1)
-  end
-end
--- a/.svn/pristine/a1/a17e85541ced0de37f4c279c99198e91fbe8ecd9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-require 'pp'
-class RepositoryCvsTest < ActiveSupport::TestCase
-  fixtures :projects
-
-  include Redmine::I18n
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s
-  REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
-  # CVS module
-  MODULE_NAME    = 'test'
-  CHANGESETS_NUM = 7
-
-  def setup
-    @project = Project.find(3)
-    @repository = Repository::Cvs.create(:project  => @project,
-                                         :root_url => REPOSITORY_PATH,
-                                         :url      => MODULE_NAME,
-                                         :log_encoding => 'UTF-8')
-    assert @repository
-  end
-
-  def test_blank_module_error_message
-    set_language_if_valid 'en'
-    repo = Repository::Cvs.new(
-                          :project      => @project,
-                          :identifier   => 'test',
-                          :log_encoding => 'UTF-8',
-                          :root_url     => REPOSITORY_PATH
-                        )
-    assert !repo.save
-    assert_include "Module can't be blank",
-                   repo.errors.full_messages
-  end
-
-  def test_blank_module_error_message_fr
-    set_language_if_valid 'fr'
-    str = "Module doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    repo = Repository::Cvs.new(
-                          :project       => @project,
-                          :identifier    => 'test',
-                          :log_encoding  => 'UTF-8',
-                          :path_encoding => '',
-                          :url           => '',
-                          :root_url      => REPOSITORY_PATH
-                        )
-    assert !repo.save
-    assert_include str, repo.errors.full_messages
-  end
-
-  def test_blank_cvsroot_error_message
-    set_language_if_valid 'en'
-    repo = Repository::Cvs.new(
-                          :project      => @project,
-                          :identifier   => 'test',
-                          :log_encoding => 'UTF-8',
-                          :url          => MODULE_NAME
-                        )
-    assert !repo.save
-    assert_include "CVSROOT can't be blank",
-                   repo.errors.full_messages
-  end
-
-  def test_blank_cvsroot_error_message_fr
-    set_language_if_valid 'fr'
-    str = "CVSROOT doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    repo = Repository::Cvs.new(
-                          :project       => @project,
-                          :identifier    => 'test',
-                          :log_encoding  => 'UTF-8',
-                          :path_encoding => '',
-                          :url           => MODULE_NAME,
-                          :root_url      => ''
-                        )
-    assert !repo.save
-    assert_include str, repo.errors.full_messages
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    def test_fetch_changesets_from_scratch
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-
-      assert_equal CHANGESETS_NUM, @repository.changesets.count
-      assert_equal 16, @repository.filechanges.count
-      assert_not_nil @repository.changesets.find_by_comments('Two files changed')
-
-      r2 = @repository.changesets.find_by_revision('2')
-      assert_equal 'v1-20071213-162510', r2.scmid
-    end
-
-    def test_fetch_changesets_incremental
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal CHANGESETS_NUM, @repository.changesets.count
-
-      # Remove changesets with revision > 3
-      @repository.changesets.all.each {|c| c.destroy if c.revision.to_i > 3}
-      @project.reload
-      assert_equal 3, @repository.changesets.count
-      assert_equal %w|3 2 1|, @repository.changesets.all.collect(&:revision)
-
-      rev3_commit = @repository.changesets.reorder('committed_on DESC').first
-      assert_equal '3', rev3_commit.revision
-       # 2007-12-14 01:27:22 +0900
-      rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22)
-      assert_equal 'HEAD-20071213-162722', rev3_commit.scmid
-      assert_equal rev3_committed_on, rev3_commit.committed_on
-      latest_rev = @repository.latest_changeset
-      assert_equal rev3_committed_on, latest_rev.committed_on
-
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal CHANGESETS_NUM, @repository.changesets.count
-      assert_equal %w|7 6 5 4 3 2 1|, @repository.changesets.all.collect(&:revision)
-      rev5_commit = @repository.changesets.find_by_revision('5')
-      assert_equal 'HEAD-20071213-163001', rev5_commit.scmid
-       # 2007-12-14 01:30:01 +0900
-      rev5_committed_on = Time.gm(2007, 12, 13, 16, 30, 1)
-      assert_equal rev5_committed_on, rev5_commit.committed_on
-    end
-
-    def test_deleted_files_should_not_be_listed
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal CHANGESETS_NUM, @repository.changesets.count
-
-      entries = @repository.entries('sources')
-      assert entries.detect {|e| e.name == 'watchers_controller.rb'}
-      assert_nil entries.detect {|e| e.name == 'welcome_controller.rb'}
-    end
-
-    def test_entries_rev3
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal CHANGESETS_NUM, @repository.changesets.count
-      entries = @repository.entries('', '3')
-      assert_kind_of Redmine::Scm::Adapters::Entries, entries
-      assert_equal 3, entries.size
-      assert_equal entries[2].name, "README"
-      assert_equal entries[2].lastrev.time, Time.gm(2007, 12, 13, 16, 27, 22)
-      assert_equal entries[2].lastrev.identifier, '3'
-      assert_equal entries[2].lastrev.revision, '3'
-      assert_equal entries[2].lastrev.author, 'LANG'
-    end
-
-    def test_entries_invalid_path
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal CHANGESETS_NUM, @repository.changesets.count
-      assert_nil @repository.entries('missing')
-      assert_nil @repository.entries('missing', '3')
-    end
-
-    def test_entries_invalid_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal CHANGESETS_NUM, @repository.changesets.count
-      assert_nil @repository.entries('', '123')
-    end
-
-    def test_cat
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal CHANGESETS_NUM, @repository.changesets.count
-      buf = @repository.cat('README')
-      assert buf
-      lines = buf.split("\n")
-      assert_equal 3, lines.length
-      buf = lines[1].gsub(/\r$/, "")
-      assert_equal 'with one change', buf
-      buf = @repository.cat('README', '1')
-      assert buf
-      lines = buf.split("\n")
-      assert_equal 1, lines.length
-      buf = lines[0].gsub(/\r$/, "")
-      assert_equal 'CVS test repository', buf
-      assert_nil @repository.cat('missing.rb')
-
-      # sources/welcome_controller.rb is removed at revision 5.
-      assert @repository.cat('sources/welcome_controller.rb', '4')
-      assert @repository.cat('sources/welcome_controller.rb', '5').blank?
-
-      # invalid revision
-      assert @repository.cat('README', '123').blank?
-    end
-
-    def test_annotate
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal CHANGESETS_NUM, @repository.changesets.count
-      ann = @repository.annotate('README')
-      assert ann
-      assert_equal 3, ann.revisions.length
-      assert_equal '1.2', ann.revisions[1].revision
-      assert_equal 'LANG', ann.revisions[1].author
-      assert_equal 'with one change', ann.lines[1]
-
-      ann = @repository.annotate('README', '1')
-      assert ann
-      assert_equal 1, ann.revisions.length
-      assert_equal '1.1', ann.revisions[0].revision
-      assert_equal 'LANG', ann.revisions[0].author
-      assert_equal 'CVS test repository', ann.lines[0]
-
-     # invalid revision
-     assert_nil @repository.annotate('README', '123')
-   end
-
-  else
-    puts "CVS test repository NOT FOUND. Skipping unit tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/a2/a228c3d0b7910e4eb07f95e583bb22e9efe2f4c4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-# redminehelper: Redmine helper extension for Mercurial
-#
-# Copyright 2010 Alessio Franceschelli (alefranz.net)
-# Copyright 2010-2011 Yuya Nishihara <yuya@tcha.org>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2 or any later version.
-"""helper commands for Redmine to reduce the number of hg calls
-
-To test this extension, please try::
-
-    $ hg --config extensions.redminehelper=redminehelper.py rhsummary
-
-I/O encoding:
-
-:file path: urlencoded, raw string
-:tag name: utf-8
-:branch name: utf-8
-:node: 12-digits (short) hex string
-
-Output example of rhsummary::
-
-    <?xml version="1.0"?>
-    <rhsummary>
-      <repository root="/foo/bar">
-        <tip revision="1234" node="abcdef0123..."/>
-        <tag revision="123" node="34567abc..." name="1.1.1"/>
-        <branch .../>
-        ...
-      </repository>
-    </rhsummary>
-
-Output example of rhmanifest::
-
-    <?xml version="1.0"?>
-    <rhmanifest>
-      <repository root="/foo/bar">
-        <manifest revision="1234" path="lib">
-          <file name="diff.rb" revision="123" node="34567abc..." time="12345"
-                 size="100"/>
-          ...
-          <dir name="redmine"/>
-          ...
-        </manifest>
-      </repository>
-    </rhmanifest>
-"""
-import re, time, cgi, urllib
-from mercurial import cmdutil, commands, node, error, hg
-
-_x = cgi.escape
-_u = lambda s: cgi.escape(urllib.quote(s))
-
-def _tip(ui, repo):
-    # see mercurial/commands.py:tip
-    def tiprev():
-        try:
-            return len(repo) - 1
-        except TypeError:  # Mercurial < 1.1
-            return repo.changelog.count() - 1
-    tipctx = repo.changectx(tiprev())
-    ui.write('<tip revision="%d" node="%s"/>\n'
-             % (tipctx.rev(), _x(node.short(tipctx.node()))))
-
-_SPECIAL_TAGS = ('tip',)
-
-def _tags(ui, repo):
-    # see mercurial/commands.py:tags
-    for t, n in reversed(repo.tagslist()):
-        if t in _SPECIAL_TAGS:
-            continue
-        try:
-            r = repo.changelog.rev(n)
-        except error.LookupError:
-            continue
-        ui.write('<tag revision="%d" node="%s" name="%s"/>\n'
-                 % (r, _x(node.short(n)), _x(t)))
-
-def _branches(ui, repo):
-    # see mercurial/commands.py:branches
-    def iterbranches():
-        for t, n in repo.branchtags().iteritems():
-            yield t, n, repo.changelog.rev(n)
-    def branchheads(branch):
-        try:
-            return repo.branchheads(branch, closed=False)
-        except TypeError:  # Mercurial < 1.2
-            return repo.branchheads(branch)
-    for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True):
-        if repo.lookup(r) in branchheads(t):
-            ui.write('<branch revision="%d" node="%s" name="%s"/>\n'
-                     % (r, _x(node.short(n)), _x(t)))
-
-def _manifest(ui, repo, path, rev):
-    ctx = repo.changectx(rev)
-    ui.write('<manifest revision="%d" path="%s">\n'
-             % (ctx.rev(), _u(path)))
-
-    known = set()
-    pathprefix = (path.rstrip('/') + '/').lstrip('/')
-    for f, n in sorted(ctx.manifest().iteritems(), key=lambda e: e[0]):
-        if not f.startswith(pathprefix):
-            continue
-        name = re.sub(r'/.*', '/', f[len(pathprefix):])
-        if name in known:
-            continue
-        known.add(name)
-
-        if name.endswith('/'):
-            ui.write('<dir name="%s"/>\n'
-                     % _x(urllib.quote(name[:-1])))
-        else:
-            fctx = repo.filectx(f, fileid=n)
-            tm, tzoffset = fctx.date()
-            ui.write('<file name="%s" revision="%d" node="%s" '
-                     'time="%d" size="%d"/>\n'
-                     % (_u(name), fctx.rev(), _x(node.short(fctx.node())),
-                        tm, fctx.size(), ))
-
-    ui.write('</manifest>\n')
-
-def rhannotate(ui, repo, *pats, **opts):
-    rev = urllib.unquote_plus(opts.pop('rev', None))
-    opts['rev'] = rev
-    return commands.annotate(ui, repo, *map(urllib.unquote_plus, pats), **opts)
-
-def rhcat(ui, repo, file1, *pats, **opts):
-    rev = urllib.unquote_plus(opts.pop('rev', None))
-    opts['rev'] = rev
-    return commands.cat(ui, repo, urllib.unquote_plus(file1), *map(urllib.unquote_plus, pats), **opts)
-
-def rhdiff(ui, repo, *pats, **opts):
-    """diff repository (or selected files)"""
-    change = opts.pop('change', None)
-    if change:  # add -c option for Mercurial<1.1
-        base = repo.changectx(change).parents()[0].rev()
-        opts['rev'] = [str(base), change]
-    opts['nodates'] = True
-    return commands.diff(ui, repo, *map(urllib.unquote_plus, pats), **opts)
-
-def rhlog(ui, repo, *pats, **opts):
-    rev      = opts.pop('rev')
-    bra0     = opts.pop('branch')
-    from_rev = urllib.unquote_plus(opts.pop('from', None))
-    to_rev   = urllib.unquote_plus(opts.pop('to'  , None))
-    bra      = urllib.unquote_plus(opts.pop('rhbranch', None))
-    from_rev = from_rev.replace('"', '\\"')
-    to_rev   = to_rev.replace('"', '\\"')
-    if hg.util.version() >= '1.6':
-      opts['rev'] = ['"%s":"%s"' % (from_rev, to_rev)]
-    else:
-      opts['rev'] = ['%s:%s' % (from_rev, to_rev)]
-    opts['branch'] = [bra]
-    return commands.log(ui, repo, *map(urllib.unquote_plus, pats), **opts)
-
-def rhmanifest(ui, repo, path='', **opts):
-    """output the sub-manifest of the specified directory"""
-    ui.write('<?xml version="1.0"?>\n')
-    ui.write('<rhmanifest>\n')
-    ui.write('<repository root="%s">\n' % _u(repo.root))
-    try:
-        _manifest(ui, repo, urllib.unquote_plus(path), urllib.unquote_plus(opts.get('rev')))
-    finally:
-        ui.write('</repository>\n')
-        ui.write('</rhmanifest>\n')
-
-def rhsummary(ui, repo, **opts):
-    """output the summary of the repository"""
-    ui.write('<?xml version="1.0"?>\n')
-    ui.write('<rhsummary>\n')
-    ui.write('<repository root="%s">\n' % _u(repo.root))
-    try:
-        _tip(ui, repo)
-        _tags(ui, repo)
-        _branches(ui, repo)
-        # TODO: bookmarks in core (Mercurial>=1.8)
-    finally:
-        ui.write('</repository>\n')
-        ui.write('</rhsummary>\n')
-
-cmdtable = {
-    'rhannotate': (rhannotate,
-         [('r', 'rev', '', 'revision'),
-          ('u', 'user', None, 'list the author (long with -v)'),
-          ('n', 'number', None, 'list the revision number (default)'),
-          ('c', 'changeset', None, 'list the changeset'),
-         ],
-         'hg rhannotate [-r REV] [-u] [-n] [-c] FILE...'),
-    'rhcat': (rhcat,
-               [('r', 'rev', '', 'revision')],
-               'hg rhcat ([-r REV] ...) FILE...'),
-    'rhdiff': (rhdiff,
-               [('r', 'rev', [], 'revision'),
-                ('c', 'change', '', 'change made by revision')],
-               'hg rhdiff ([-c REV] | [-r REV] ...) [FILE]...'),
-    'rhlog': (rhlog,
-                   [
-                    ('r', 'rev', [], 'show the specified revision'),
-                    ('b', 'branch', [],
-                       'show changesets within the given named branch'),
-                    ('l', 'limit', '',
-                         'limit number of changes displayed'),
-                    ('d', 'date', '',
-                         'show revisions matching date spec'),
-                    ('u', 'user', [],
-                      'revisions committed by user'),
-                    ('', 'from', '',
-                      ''),
-                    ('', 'to', '',
-                      ''),
-                    ('', 'rhbranch', '',
-                      ''),
-                    ('', 'template', '',
-                       'display with template')],
-                   'hg rhlog [OPTION]... [FILE]'),
-    'rhmanifest': (rhmanifest,
-                   [('r', 'rev', '', 'show the specified revision')],
-                   'hg rhmanifest [-r REV] [PATH]'),
-    'rhsummary': (rhsummary, [], 'hg rhsummary'),
-}
--- a/.svn/pristine/a2/a22e306fd6141198284b162f707867ef8c8e9b27.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,412 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/abstract_adapter'
-
-module Redmine
-  module Scm
-    module Adapters
-      class GitAdapter < AbstractAdapter
-
-        # Git executable name
-        GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
-
-        class GitBranch < Branch 
-          attr_accessor :is_default
-        end
-
-        class << self
-          def client_command
-            @@bin    ||= GIT_BIN
-          end
-
-          def sq_bin
-            @@sq_bin ||= shell_quote_command
-          end
-
-          def client_version
-            @@client_version ||= (scm_command_version || [])
-          end
-
-          def client_available
-            !client_version.empty?
-          end
-
-          def scm_command_version
-            scm_version = scm_version_from_command_line.dup
-            if scm_version.respond_to?(:force_encoding)
-              scm_version.force_encoding('ASCII-8BIT')
-            end
-            if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
-              m[2].scan(%r{\d+}).collect(&:to_i)
-            end
-          end
-
-          def scm_version_from_command_line
-            shellout("#{sq_bin} --version --no-color") { |io| io.read }.to_s
-          end
-        end
-
-        def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
-          super
-          @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
-        end
-
-        def path_encoding
-          @path_encoding
-        end
-
-        def info
-          begin
-            Info.new(:root_url => url, :lastrev => lastrev('',nil))
-          rescue
-            nil
-          end
-        end
-
-        def branches
-          return @branches if @branches
-          @branches = []
-          cmd_args = %w|branch --no-color --verbose --no-abbrev|
-          git_cmd(cmd_args) do |io|
-            io.each_line do |line|
-              branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$')
-              bran = GitBranch.new(branch_rev[2])
-              bran.revision =  branch_rev[3]
-              bran.scmid    =  branch_rev[3]
-              bran.is_default = ( branch_rev[1] == '*' )
-              @branches << bran
-            end
-          end
-          @branches.sort!
-        rescue ScmCommandAborted
-          nil
-        end
-
-        def tags
-          return @tags if @tags
-          cmd_args = %w|tag|
-          git_cmd(cmd_args) do |io|
-            @tags = io.readlines.sort!.map{|t| t.strip}
-          end
-        rescue ScmCommandAborted
-          nil
-        end
-
-        def default_branch
-          bras = self.branches
-          return nil if bras.nil?
-          default_bras = bras.select{|x| x.is_default == true}
-          return default_bras.first.to_s if ! default_bras.empty?
-          master_bras = bras.select{|x| x.to_s == 'master'}
-          master_bras.empty? ? bras.first.to_s : 'master' 
-        end
-
-        def entry(path=nil, identifier=nil)
-          parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
-          search_path = parts[0..-2].join('/')
-          search_name = parts[-1]
-          if search_path.blank? && search_name.blank?
-            # Root entry
-            Entry.new(:path => '', :kind => 'dir')
-          else
-            # Search for the entry in the parent directory
-            es = entries(search_path, identifier,
-                         options = {:report_last_commit => false})
-            es ? es.detect {|e| e.name == search_name} : nil
-          end
-        end
-
-        def entries(path=nil, identifier=nil, options={})
-          path ||= ''
-          p = scm_iconv(@path_encoding, 'UTF-8', path)
-          entries = Entries.new
-          cmd_args = %w|ls-tree -l|
-          cmd_args << "HEAD:#{p}"          if identifier.nil?
-          cmd_args << "#{identifier}:#{p}" if identifier
-          git_cmd(cmd_args) do |io|
-            io.each_line do |line|
-              e = line.chomp.to_s
-              if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\t(.+)$/
-                type = $1
-                sha  = $2
-                size = $3
-                name = $4
-                if name.respond_to?(:force_encoding)
-                  name.force_encoding(@path_encoding)
-                end
-                full_path = p.empty? ? name : "#{p}/#{name}"
-                n      = scm_iconv('UTF-8', @path_encoding, name)
-                full_p = scm_iconv('UTF-8', @path_encoding, full_path)
-                entries << Entry.new({:name => n,
-                 :path => full_p,
-                 :kind => (type == "tree") ? 'dir' : 'file',
-                 :size => (type == "tree") ? nil : size,
-                 :lastrev => options[:report_last_commit] ?
-                                 lastrev(full_path, identifier) : Revision.new
-                }) unless entries.detect{|entry| entry.name == name}
-              end
-            end
-          end
-          entries.sort_by_name
-        rescue ScmCommandAborted
-          nil
-        end
-
-        def lastrev(path, rev)
-          return nil if path.nil?
-          cmd_args = %w|log --no-color --encoding=UTF-8 --date=iso --pretty=fuller --no-merges -n 1|
-          cmd_args << rev if rev
-          cmd_args << "--" << path unless path.empty?
-          lines = []
-          git_cmd(cmd_args) { |io| lines = io.readlines }
-          begin
-              id = lines[0].split[1]
-              author = lines[1].match('Author:\s+(.*)$')[1]
-              time = Time.parse(lines[4].match('CommitDate:\s+(.*)$')[1])
-
-              Revision.new({
-                :identifier => id,
-                :scmid      => id,
-                :author     => author,
-                :time       => time,
-                :message    => nil,
-                :paths      => nil
-                })
-          rescue NoMethodError => e
-              logger.error("The revision '#{path}' has a wrong format")
-              return nil
-          end
-        rescue ScmCommandAborted
-          nil
-        end
-
-        def revisions(path, identifier_from, identifier_to, options={})
-          revs = Revisions.new
-          cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents --stdin|
-          cmd_args << "--reverse" if options[:reverse]
-          cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit]
-          cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty?
-          revisions = []
-          if identifier_from || identifier_to
-            revisions << ""
-            revisions[0] << "#{identifier_from}.." if identifier_from
-            revisions[0] << "#{identifier_to}" if identifier_to
-          else
-            unless options[:includes].blank?
-              revisions += options[:includes]
-            end
-            unless options[:excludes].blank?
-              revisions += options[:excludes].map{|r| "^#{r}"}
-            end
-          end
-
-          git_cmd(cmd_args, {:write_stdin => true}) do |io|
-            io.binmode
-            io.puts(revisions.join("\n"))
-            io.close_write
-            files=[]
-            changeset = {}
-            parsing_descr = 0  #0: not parsing desc or files, 1: parsing desc, 2: parsing files
-
-            io.each_line do |line|
-              if line =~ /^commit ([0-9a-f]{40})(( [0-9a-f]{40})*)$/
-                key = "commit"
-                value = $1
-                parents_str = $2
-                if (parsing_descr == 1 || parsing_descr == 2)
-                  parsing_descr = 0
-                  revision = Revision.new({
-                    :identifier => changeset[:commit],
-                    :scmid      => changeset[:commit],
-                    :author     => changeset[:author],
-                    :time       => Time.parse(changeset[:date]),
-                    :message    => changeset[:description],
-                    :paths      => files,
-                    :parents    => changeset[:parents]
-                  })
-                  if block_given?
-                    yield revision
-                  else
-                    revs << revision
-                  end
-                  changeset = {}
-                  files = []
-                end
-                changeset[:commit] = $1
-                unless parents_str.nil? or parents_str == ""
-                  changeset[:parents] = parents_str.strip.split(' ')
-                end
-              elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
-                key = $1
-                value = $2
-                if key == "Author"
-                  changeset[:author] = value
-                elsif key == "CommitDate"
-                  changeset[:date] = value
-                end
-              elsif (parsing_descr == 0) && line.chomp.to_s == ""
-                parsing_descr = 1
-                changeset[:description] = ""
-              elsif (parsing_descr == 1 || parsing_descr == 2) \
-                  && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\t(.+)$/
-                parsing_descr = 2
-                fileaction    = $1
-                filepath      = $2
-                p = scm_iconv('UTF-8', @path_encoding, filepath)
-                files << {:action => fileaction, :path => p}
-              elsif (parsing_descr == 1 || parsing_descr == 2) \
-                  && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\t(.+)$/
-                parsing_descr = 2
-                fileaction    = $1
-                filepath      = $3
-                p = scm_iconv('UTF-8', @path_encoding, filepath)
-                files << {:action => fileaction, :path => p}
-              elsif (parsing_descr == 1) && line.chomp.to_s == ""
-                parsing_descr = 2
-              elsif (parsing_descr == 1)
-                changeset[:description] << line[4..-1]
-              end
-            end
-
-            if changeset[:commit]
-              revision = Revision.new({
-                :identifier => changeset[:commit],
-                :scmid      => changeset[:commit],
-                :author     => changeset[:author],
-                :time       => Time.parse(changeset[:date]),
-                :message    => changeset[:description],
-                :paths      => files,
-                :parents    => changeset[:parents]
-                 })
-              if block_given?
-                yield revision
-              else
-                revs << revision
-              end
-            end
-          end
-          revs
-        rescue ScmCommandAborted => e
-          err_msg = "git log error: #{e.message}"
-          logger.error(err_msg)
-          if block_given?
-            raise CommandFailed, err_msg
-          else
-            revs
-          end
-        end
-
-        def diff(path, identifier_from, identifier_to=nil)
-          path ||= ''
-          cmd_args = []
-          if identifier_to
-            cmd_args << "diff" << "--no-color" <<  identifier_to << identifier_from
-          else
-            cmd_args << "show" << "--no-color" << identifier_from
-          end
-          cmd_args << "--" <<  scm_iconv(@path_encoding, 'UTF-8', path) unless path.empty?
-          diff = []
-          git_cmd(cmd_args) do |io|
-            io.each_line do |line|
-              diff << line
-            end
-          end
-          diff
-        rescue ScmCommandAborted
-          nil
-        end
-
-        def annotate(path, identifier=nil)
-          identifier = 'HEAD' if identifier.blank?
-          cmd_args = %w|blame --encoding=UTF-8|
-          cmd_args << "-p" << identifier << "--" <<  scm_iconv(@path_encoding, 'UTF-8', path)
-          blame = Annotate.new
-          content = nil
-          git_cmd(cmd_args) { |io| io.binmode; content = io.read }
-          # git annotates binary files
-          return nil if content.is_binary_data?
-          identifier = ''
-          # git shows commit author on the first occurrence only
-          authors_by_commit = {}
-          content.split("\n").each do |line|
-            if line =~ /^([0-9a-f]{39,40})\s.*/
-              identifier = $1
-            elsif line =~ /^author (.+)/
-              authors_by_commit[identifier] = $1.strip
-            elsif line =~ /^\t(.*)/
-              blame.add_line($1, Revision.new(
-                                    :identifier => identifier,
-                                    :revision   => identifier,
-                                    :scmid      => identifier,
-                                    :author     => authors_by_commit[identifier]
-                                    ))
-              identifier = ''
-              author = ''
-            end
-          end
-          blame
-        rescue ScmCommandAborted
-          nil
-        end
-
-        def cat(path, identifier=nil)
-          if identifier.nil?
-            identifier = 'HEAD'
-          end
-          cmd_args = %w|show --no-color|
-          cmd_args << "#{identifier}:#{scm_iconv(@path_encoding, 'UTF-8', path)}"
-          cat = nil
-          git_cmd(cmd_args) do |io|
-            io.binmode
-            cat = io.read
-          end
-          cat
-        rescue ScmCommandAborted
-          nil
-        end
-
-        class Revision < Redmine::Scm::Adapters::Revision
-          # Returns the readable identifier
-          def format_identifier
-            identifier[0,8]
-          end
-        end
-
-        def git_cmd(args, options = {}, &block)
-          repo_path = root_url || url
-          full_args = ['--git-dir', repo_path]
-          if self.class.client_version_above?([1, 7, 2])
-            full_args << '-c' << 'core.quotepath=false'
-            full_args << '-c' << 'log.decorate=no'
-          end
-          full_args += args
-          ret = shellout(
-                   self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
-                   options,
-                   &block
-                   )
-          if $? && $?.exitstatus != 0
-            raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}"
-          end
-          ret
-        end
-        private :git_cmd
-      end
-    end
-  end
-end
--- a/.svn/pristine/a2/a287706354ad35bfd9b7a22dc5edd1bfb0f897d3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class MailHandlerControllerTest < ActionController::TestCase
-  fixtures :users, :projects, :enabled_modules, :roles, :members, :member_roles, :issues, :issue_statuses,
-           :trackers, :projects_trackers, :enumerations
-
-  FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
-
-  def setup
-    User.current = nil
-  end
-
-  def test_should_create_issue
-    # Enable API and set a key
-    Setting.mail_handler_api_enabled = 1
-    Setting.mail_handler_api_key = 'secret'
-
-    assert_difference 'Issue.count' do
-      post :index, :key => 'secret', :email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
-    end
-    assert_response 201
-  end
-
-  def test_should_respond_with_422_if_not_created
-    Project.find('onlinestore').destroy
-
-    Setting.mail_handler_api_enabled = 1
-    Setting.mail_handler_api_key = 'secret'
-
-    assert_no_difference 'Issue.count' do
-      post :index, :key => 'secret', :email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
-    end
-    assert_response 422
-  end
-
-  def test_should_not_allow_with_api_disabled
-    # Disable API
-    Setting.mail_handler_api_enabled = 0
-    Setting.mail_handler_api_key = 'secret'
-
-    assert_no_difference 'Issue.count' do
-      post :index, :key => 'secret', :email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
-    end
-    assert_response 403
-  end
-
-  def test_should_not_allow_with_wrong_key
-    # Disable API
-    Setting.mail_handler_api_enabled = 1
-    Setting.mail_handler_api_key = 'secret'
-
-    assert_no_difference 'Issue.count' do
-      post :index, :key => 'wrong', :email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
-    end
-    assert_response 403
-  end
-end
--- a/.svn/pristine/a3/a355ad47972838f60c489f8cf36f7b28781aa191.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,809 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'tcpdf'
-require 'fpdf/chinese'
-require 'fpdf/japanese'
-require 'fpdf/korean'
-
-if RUBY_VERSION < '1.9'
-  require 'iconv'
-end
-
-module Redmine
-  module Export
-    module PDF
-      include ActionView::Helpers::TextHelper
-      include ActionView::Helpers::NumberHelper
-      include IssuesHelper
-
-      class ITCPDF < TCPDF
-        include Redmine::I18n
-        attr_accessor :footer_date
-
-        def initialize(lang, orientation='P')
-          @@k_path_cache = Rails.root.join('tmp', 'pdf')
-          FileUtils.mkdir_p @@k_path_cache unless File::exist?(@@k_path_cache)
-          set_language_if_valid lang
-          pdf_encoding = l(:general_pdf_encoding).upcase
-          super(orientation, 'mm', 'A4', (pdf_encoding == 'UTF-8'), pdf_encoding)
-          case current_language.to_s.downcase
-          when 'vi'
-            @font_for_content = 'DejaVuSans'
-            @font_for_footer  = 'DejaVuSans'
-          else
-            case pdf_encoding
-            when 'UTF-8'
-              @font_for_content = 'FreeSans'
-              @font_for_footer  = 'FreeSans'
-            when 'CP949'
-              extend(PDF_Korean)
-              AddUHCFont()
-              @font_for_content = 'UHC'
-              @font_for_footer  = 'UHC'
-            when 'CP932', 'SJIS', 'SHIFT_JIS'
-              extend(PDF_Japanese)
-              AddSJISFont()
-              @font_for_content = 'SJIS'
-              @font_for_footer  = 'SJIS'
-            when 'GB18030'
-              extend(PDF_Chinese)
-              AddGBFont()
-              @font_for_content = 'GB'
-              @font_for_footer  = 'GB'
-            when 'BIG5'
-              extend(PDF_Chinese)
-              AddBig5Font()
-              @font_for_content = 'Big5'
-              @font_for_footer  = 'Big5'
-            else
-              @font_for_content = 'Arial'
-              @font_for_footer  = 'Helvetica'
-            end
-          end
-          SetCreator(Redmine::Info.app_name)
-          SetFont(@font_for_content)
-          @outlines = []
-          @outlineRoot = nil
-        end
-
-        def SetFontStyle(style, size)
-          SetFont(@font_for_content, style, size)
-        end
-
-        def SetTitle(txt)
-          txt = begin
-            utf16txt = to_utf16(txt)
-            hextxt = "<FEFF"  # FEFF is BOM
-            hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
-            hextxt << ">"
-          rescue
-            txt
-          end || ''
-          super(txt)
-        end
-
-        def textstring(s)
-          # Format a text string
-          if s =~ /^</  # This means the string is hex-dumped.
-            return s
-          else
-            return '('+escape(s)+')'
-          end
-        end
-
-        def fix_text_encoding(txt)
-          RDMPdfEncoding::rdm_from_utf8(txt, l(:general_pdf_encoding))
-        end
-
-        def formatted_text(text)
-          html = Redmine::WikiFormatting.to_html(Setting.text_formatting, text)
-          # Strip {{toc}} tags
-          html.gsub!(/<p>\{\{([<>]?)toc\}\}<\/p>/i, '')
-          html
-        end
-
-        # Encodes an UTF-8 string to UTF-16BE
-        def to_utf16(str)
-          if str.respond_to?(:encode)
-            str.encode('UTF-16BE')
-          else
-            Iconv.conv('UTF-16BE', 'UTF-8', str)
-          end
-        end
-
-        def RDMCell(w ,h=0, txt='', border=0, ln=0, align='', fill=0, link='')
-          Cell(w, h, fix_text_encoding(txt), border, ln, align, fill, link)
-        end
-
-        def RDMMultiCell(w, h=0, txt='', border=0, align='', fill=0, ln=1)
-          MultiCell(w, h, fix_text_encoding(txt), border, align, fill, ln)
-        end
-
-        def RDMwriteHTMLCell(w, h, x, y, txt='', attachments=[], border=0, ln=1, fill=0)
-          @attachments = attachments
-          writeHTMLCell(w, h, x, y,
-            fix_text_encoding(formatted_text(txt)),
-            border, ln, fill)
-        end
-
-        def getImageFilename(attrname)
-          # attrname: general_pdf_encoding string file/uri name
-          atta = RDMPdfEncoding.attach(@attachments, attrname, l(:general_pdf_encoding))
-          if atta
-            return atta.diskfile
-          else
-            return nil
-          end
-        end
-
-        def Footer
-          SetFont(@font_for_footer, 'I', 8)
-          SetY(-15)
-          SetX(15)
-          RDMCell(0, 5, @footer_date, 0, 0, 'L')
-          SetY(-15)
-          SetX(-30)
-          RDMCell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
-        end
-
-        def Bookmark(txt, level=0, y=0)
-          if (y == -1)
-            y = GetY()
-          end
-          @outlines << {:t => txt, :l => level, :p => PageNo(), :y => (@h - y)*@k}
-        end
-
-        def bookmark_title(txt)
-          txt = begin
-            utf16txt = to_utf16(txt)
-            hextxt = "<FEFF"  # FEFF is BOM
-            hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
-            hextxt << ">"
-          rescue
-            txt
-          end || ''
-        end
-
-        def putbookmarks
-          nb=@outlines.size
-          return if (nb==0)
-          lru=[]
-          level=0
-          @outlines.each_with_index do |o, i|
-            if(o[:l]>0)
-              parent=lru[o[:l]-1]
-              #Set parent and last pointers
-              @outlines[i][:parent]=parent
-              @outlines[parent][:last]=i
-              if (o[:l]>level)
-                #Level increasing: set first pointer
-                @outlines[parent][:first]=i
-              end
-            else
-              @outlines[i][:parent]=nb
-            end
-            if (o[:l]<=level && i>0)
-              #Set prev and next pointers
-              prev=lru[o[:l]]
-              @outlines[prev][:next]=i
-              @outlines[i][:prev]=prev
-            end
-            lru[o[:l]]=i
-            level=o[:l]
-          end
-          #Outline items
-          n=self.n+1
-          @outlines.each_with_index do |o, i|
-            newobj()
-            out('<</Title '+bookmark_title(o[:t]))
-            out("/Parent #{n+o[:parent]} 0 R")
-            if (o[:prev])
-              out("/Prev #{n+o[:prev]} 0 R")
-            end
-            if (o[:next])
-              out("/Next #{n+o[:next]} 0 R")
-            end
-            if (o[:first])
-              out("/First #{n+o[:first]} 0 R")
-            end
-            if (o[:last])
-              out("/Last #{n+o[:last]} 0 R")
-            end
-            out("/Dest [%d 0 R /XYZ 0 %.2f null]" % [1+2*o[:p], o[:y]])
-            out('/Count 0>>')
-            out('endobj')
-          end
-          #Outline root
-          newobj()
-          @outlineRoot=self.n
-          out("<</Type /Outlines /First #{n} 0 R");
-          out("/Last #{n+lru[0]} 0 R>>");
-          out('endobj');
-        end
-
-        def putresources()
-          super
-          putbookmarks()
-        end
-
-        def putcatalog()
-          super
-          if(@outlines.size > 0)
-            out("/Outlines #{@outlineRoot} 0 R");
-            out('/PageMode /UseOutlines');
-          end
-        end
-      end
-
-      # fetch row values
-      def fetch_row_values(issue, query, level)
-        query.inline_columns.collect do |column|
-          s = if column.is_a?(QueryCustomFieldColumn)
-            cv = issue.visible_custom_field_values.detect {|v| v.custom_field_id == column.custom_field.id}
-            show_value(cv)
-          else
-            value = issue.send(column.name)
-            if column.name == :subject
-              value = "  " * level + value
-            end
-            if value.is_a?(Date)
-              format_date(value)
-            elsif value.is_a?(Time)
-              format_time(value)
-            else
-              value
-            end
-          end
-          s.to_s
-        end
-      end
-
-      # calculate columns width
-      def calc_col_width(issues, query, table_width, pdf)
-        # calculate statistics
-        #  by captions
-        pdf.SetFontStyle('B',8)
-        col_padding = pdf.GetStringWidth('OO')
-        col_width_min = query.inline_columns.map {|v| pdf.GetStringWidth(v.caption) + col_padding}
-        col_width_max = Array.new(col_width_min)
-        col_width_avg = Array.new(col_width_min)
-        word_width_max = query.inline_columns.map {|c|
-          n = 10
-          c.caption.split.each {|w|
-            x = pdf.GetStringWidth(w) + col_padding
-            n = x if n < x
-          }
-          n
-        }
-
-        #  by properties of issues
-        pdf.SetFontStyle('',8)
-        col_padding = pdf.GetStringWidth('OO')
-        k = 1
-        issue_list(issues) {|issue, level|
-          k += 1
-          values = fetch_row_values(issue, query, level)
-          values.each_with_index {|v,i|
-            n = pdf.GetStringWidth(v) + col_padding
-            col_width_max[i] = n if col_width_max[i] < n
-            col_width_min[i] = n if col_width_min[i] > n
-            col_width_avg[i] += n
-            v.split.each {|w|
-              x = pdf.GetStringWidth(w) + col_padding
-              word_width_max[i] = x if word_width_max[i] < x
-            }
-          }
-        }
-        col_width_avg.map! {|x| x / k}
-
-        # calculate columns width
-        ratio = table_width / col_width_avg.inject(0, :+)
-        col_width = col_width_avg.map {|w| w * ratio}
-
-        # correct max word width if too many columns
-        ratio = table_width / word_width_max.inject(0, :+)
-        word_width_max.map! {|v| v * ratio} if ratio < 1
-
-        # correct and lock width of some columns
-        done = 1
-        col_fix = []
-        col_width.each_with_index do |w,i|
-          if w > col_width_max[i]
-            col_width[i] = col_width_max[i]
-            col_fix[i] = 1
-            done = 0
-          elsif w < word_width_max[i]
-            col_width[i] = word_width_max[i]
-            col_fix[i] = 1
-            done = 0
-          else
-            col_fix[i] = 0
-          end
-        end
-
-        # iterate while need to correct and lock coluns width
-        while done == 0
-          # calculate free & locked columns width
-          done = 1
-          fix_col_width = 0
-          free_col_width = 0
-          col_width.each_with_index do |w,i|
-            if col_fix[i] == 1
-              fix_col_width += w
-            else
-              free_col_width += w
-            end
-          end
-
-          # calculate column normalizing ratio
-          if free_col_width == 0
-            ratio = table_width / col_width.inject(0, :+)
-          else
-            ratio = (table_width - fix_col_width) / free_col_width
-          end
-
-          # correct columns width
-          col_width.each_with_index do |w,i|
-            if col_fix[i] == 0
-              col_width[i] = w * ratio
-
-              # check if column width less then max word width
-              if col_width[i] < word_width_max[i]
-                col_width[i] = word_width_max[i]
-                col_fix[i] = 1
-                done = 0
-              elsif col_width[i] > col_width_max[i]
-                col_width[i] = col_width_max[i]
-                col_fix[i] = 1
-                done = 0
-              end
-            end
-          end
-        end
-        col_width
-      end
-
-      def render_table_header(pdf, query, col_width, row_height, table_width)
-        # headers
-        pdf.SetFontStyle('B',8)
-        pdf.SetFillColor(230, 230, 230)
-
-        # render it background to find the max height used
-        base_x = pdf.GetX
-        base_y = pdf.GetY
-        max_height = issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true)
-        pdf.Rect(base_x, base_y, table_width, max_height, 'FD');
-        pdf.SetXY(base_x, base_y);
-
-        # write the cells on page
-        issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true)
-        issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, 0, col_width)
-        pdf.SetY(base_y + max_height);
-
-        # rows
-        pdf.SetFontStyle('',8)
-        pdf.SetFillColor(255, 255, 255)
-      end
-
-      # Returns a PDF string of a list of issues
-      def issues_to_pdf(issues, project, query)
-        pdf = ITCPDF.new(current_language, "L")
-        title = query.new_record? ? l(:label_issue_plural) : query.name
-        title = "#{project} - #{title}" if project
-        pdf.SetTitle(title)
-        pdf.alias_nb_pages
-        pdf.footer_date = format_date(Date.today)
-        pdf.SetAutoPageBreak(false)
-        pdf.AddPage("L")
-
-        # Landscape A4 = 210 x 297 mm
-        page_height   = 210
-        page_width    = 297
-        left_margin   = 10
-        right_margin  = 10
-        bottom_margin = 20
-        row_height    = 4
-
-        # column widths
-        table_width = page_width - right_margin - left_margin
-        col_width = []
-        unless query.inline_columns.empty?
-          col_width = calc_col_width(issues, query, table_width, pdf)
-          table_width = col_width.inject(0, :+)
-        end
-
-        # use full width if the description is displayed
-        if table_width > 0 && query.has_column?(:description)
-          col_width = col_width.map {|w| w * (page_width - right_margin - left_margin) / table_width}
-          table_width = col_width.inject(0, :+)
-        end
-
-        # title
-        pdf.SetFontStyle('B',11)
-        pdf.RDMCell(190,10, title)
-        pdf.Ln
-        render_table_header(pdf, query, col_width, row_height, table_width)
-        previous_group = false
-        issue_list(issues) do |issue, level|
-          if query.grouped? &&
-               (group = query.group_by_column.value(issue)) != previous_group
-            pdf.SetFontStyle('B',10)
-            group_label = group.blank? ? 'None' : group.to_s.dup
-            group_label << " (#{query.issue_count_by_group[group]})"
-            pdf.Bookmark group_label, 0, -1
-            pdf.RDMCell(table_width, row_height * 2, group_label, 1, 1, 'L')
-            pdf.SetFontStyle('',8)
-            previous_group = group
-          end
-
-          # fetch row values
-          col_values = fetch_row_values(issue, query, level)
-
-          # render it off-page to find the max height used
-          base_x = pdf.GetX
-          base_y = pdf.GetY
-          pdf.SetY(2 * page_height)
-          max_height = issues_to_pdf_write_cells(pdf, col_values, col_width, row_height)
-          pdf.SetXY(base_x, base_y)
-
-          # make new page if it doesn't fit on the current one
-          space_left = page_height - base_y - bottom_margin
-          if max_height > space_left
-            pdf.AddPage("L")
-            render_table_header(pdf, query, col_width, row_height, table_width)
-            base_x = pdf.GetX
-            base_y = pdf.GetY
-          end
-
-          # write the cells on page
-          issues_to_pdf_write_cells(pdf, col_values, col_width, row_height)
-          issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, 0, col_width)
-          pdf.SetY(base_y + max_height);
-
-          if query.has_column?(:description) && issue.description?
-            pdf.SetX(10)
-            pdf.SetAutoPageBreak(true, 20)
-            pdf.RDMwriteHTMLCell(0, 5, 10, 0, issue.description.to_s, issue.attachments, "LRBT")
-            pdf.SetAutoPageBreak(false)
-          end
-        end
-
-        if issues.size == Setting.issues_export_limit.to_i
-          pdf.SetFontStyle('B',10)
-          pdf.RDMCell(0, row_height, '...')
-        end
-        pdf.Output
-      end
-
-      # Renders MultiCells and returns the maximum height used
-      def issues_to_pdf_write_cells(pdf, col_values, col_widths, row_height, head=false)
-        base_y = pdf.GetY
-        max_height = row_height
-        col_values.each_with_index do |column, i|
-          col_x = pdf.GetX
-          if head == true
-            pdf.RDMMultiCell(col_widths[i], row_height, column.caption, "T", 'L', 1)
-          else
-            pdf.RDMMultiCell(col_widths[i], row_height, column, "T", 'L', 1)
-          end
-          max_height = (pdf.GetY - base_y) if (pdf.GetY - base_y) > max_height
-          pdf.SetXY(col_x + col_widths[i], base_y);
-        end
-        return max_height
-      end
-
-      # Draw lines to close the row (MultiCell border drawing in not uniform)
-      #
-      #  parameter "col_id_width" is not used. it is kept for compatibility.
-      def issues_to_pdf_draw_borders(pdf, top_x, top_y, lower_y,
-                                     col_id_width, col_widths)
-        col_x = top_x
-        pdf.Line(col_x, top_y, col_x, lower_y)    # id right border
-        col_widths.each do |width|
-          col_x += width
-          pdf.Line(col_x, top_y, col_x, lower_y)  # columns right border
-        end
-        pdf.Line(top_x, top_y, top_x, lower_y)    # left border
-        pdf.Line(top_x, lower_y, col_x, lower_y)  # bottom border
-      end
-
-      # Returns a PDF string of a single issue
-      def issue_to_pdf(issue, assoc={})
-        pdf = ITCPDF.new(current_language)
-        pdf.SetTitle("#{issue.project} - #{issue.tracker} ##{issue.id}")
-        pdf.alias_nb_pages
-        pdf.footer_date = format_date(Date.today)
-        pdf.AddPage
-        pdf.SetFontStyle('B',11)
-        buf = "#{issue.project} - #{issue.tracker} ##{issue.id}"
-        pdf.RDMMultiCell(190, 5, buf)
-        pdf.SetFontStyle('',8)
-        base_x = pdf.GetX
-        i = 1
-        issue.ancestors.visible.each do |ancestor|
-          pdf.SetX(base_x + i)
-          buf = "#{ancestor.tracker} # #{ancestor.id} (#{ancestor.status.to_s}): #{ancestor.subject}"
-          pdf.RDMMultiCell(190 - i, 5, buf)
-          i += 1 if i < 35
-        end
-        pdf.SetFontStyle('B',11)
-        pdf.RDMMultiCell(190 - i, 5, issue.subject.to_s)
-        pdf.SetFontStyle('',8)
-        pdf.RDMMultiCell(190, 5, "#{format_time(issue.created_on)} - #{issue.author}")
-        pdf.Ln
-
-        left = []
-        left << [l(:field_status), issue.status]
-        left << [l(:field_priority), issue.priority]
-        left << [l(:field_assigned_to), issue.assigned_to] unless issue.disabled_core_fields.include?('assigned_to_id')
-        left << [l(:field_category), issue.category] unless issue.disabled_core_fields.include?('category_id')
-        left << [l(:field_fixed_version), issue.fixed_version] unless issue.disabled_core_fields.include?('fixed_version_id')
-
-        right = []
-        right << [l(:field_start_date), format_date(issue.start_date)] unless issue.disabled_core_fields.include?('start_date')
-        right << [l(:field_due_date), format_date(issue.due_date)] unless issue.disabled_core_fields.include?('due_date')
-        right << [l(:field_done_ratio), "#{issue.done_ratio}%"] unless issue.disabled_core_fields.include?('done_ratio')
-        right << [l(:field_estimated_hours), l_hours(issue.estimated_hours)] unless issue.disabled_core_fields.include?('estimated_hours')
-        right << [l(:label_spent_time), l_hours(issue.total_spent_hours)] if User.current.allowed_to?(:view_time_entries, issue.project)
-
-        rows = left.size > right.size ? left.size : right.size
-        while left.size < rows
-          left << nil
-        end
-        while right.size < rows
-          right << nil
-        end
-
-        half = (issue.visible_custom_field_values.size / 2.0).ceil
-        issue.visible_custom_field_values.each_with_index do |custom_value, i|
-          (i < half ? left : right) << [custom_value.custom_field.name, show_value(custom_value)]
-        end
-
-        rows = left.size > right.size ? left.size : right.size
-        rows.times do |i|
-          item = left[i]
-          pdf.SetFontStyle('B',9)
-          pdf.RDMCell(35,5, item ? "#{item.first}:" : "", i == 0 ? "LT" : "L")
-          pdf.SetFontStyle('',9)
-          pdf.RDMCell(60,5, item ? item.last.to_s : "", i == 0 ? "RT" : "R")
-
-          item = right[i]
-          pdf.SetFontStyle('B',9)
-          pdf.RDMCell(35,5, item ? "#{item.first}:" : "", i == 0 ? "LT" : "L")
-          pdf.SetFontStyle('',9)
-          pdf.RDMCell(60,5, item ? item.last.to_s : "", i == 0 ? "RT" : "R")
-          pdf.Ln
-        end
-
-        pdf.SetFontStyle('B',9)
-        pdf.RDMCell(35+155, 5, l(:field_description), "LRT", 1)
-        pdf.SetFontStyle('',9)
-
-        # Set resize image scale
-        pdf.SetImageScale(1.6)
-        pdf.RDMwriteHTMLCell(35+155, 5, 0, 0,
-              issue.description.to_s, issue.attachments, "LRB")
-
-        unless issue.leaf?
-          # for CJK
-          truncate_length = ( l(:general_pdf_encoding).upcase == "UTF-8" ? 90 : 65 )
-
-          pdf.SetFontStyle('B',9)
-          pdf.RDMCell(35+155,5, l(:label_subtask_plural) + ":", "LTR")
-          pdf.Ln
-          issue_list(issue.descendants.visible.sort_by(&:lft)) do |child, level|
-            buf = truncate("#{child.tracker} # #{child.id}: #{child.subject}",
-                           :length => truncate_length)
-            level = 10 if level >= 10
-            pdf.SetFontStyle('',8)
-            pdf.RDMCell(35+135,5, (level >=1 ? "  " * level : "") + buf, "L")
-            pdf.SetFontStyle('B',8)
-            pdf.RDMCell(20,5, child.status.to_s, "R")
-            pdf.Ln
-          end
-        end
-
-        relations = issue.relations.select { |r| r.other_issue(issue).visible? }
-        unless relations.empty?
-          # for CJK
-          truncate_length = ( l(:general_pdf_encoding).upcase == "UTF-8" ? 80 : 60 )
-
-          pdf.SetFontStyle('B',9)
-          pdf.RDMCell(35+155,5, l(:label_related_issues) + ":", "LTR")
-          pdf.Ln
-          relations.each do |relation|
-            buf = ""
-            buf += "#{l(relation.label_for(issue))} "
-            if relation.delay && relation.delay != 0
-              buf += "(#{l('datetime.distance_in_words.x_days', :count => relation.delay)}) "
-            end
-            if Setting.cross_project_issue_relations?
-              buf += "#{relation.other_issue(issue).project} - "
-            end
-            buf += "#{relation.other_issue(issue).tracker}" +
-                   " # #{relation.other_issue(issue).id}: #{relation.other_issue(issue).subject}"
-            buf = truncate(buf, :length => truncate_length)
-            pdf.SetFontStyle('', 8)
-            pdf.RDMCell(35+155-60, 5, buf, "L")
-            pdf.SetFontStyle('B',8)
-            pdf.RDMCell(20,5, relation.other_issue(issue).status.to_s, "")
-            pdf.RDMCell(20,5, format_date(relation.other_issue(issue).start_date), "")
-            pdf.RDMCell(20,5, format_date(relation.other_issue(issue).due_date), "R")
-            pdf.Ln
-          end
-        end
-        pdf.RDMCell(190,5, "", "T")
-        pdf.Ln
-
-        if issue.changesets.any? &&
-             User.current.allowed_to?(:view_changesets, issue.project)
-          pdf.SetFontStyle('B',9)
-          pdf.RDMCell(190,5, l(:label_associated_revisions), "B")
-          pdf.Ln
-          for changeset in issue.changesets
-            pdf.SetFontStyle('B',8)
-            csstr  = "#{l(:label_revision)} #{changeset.format_identifier} - "
-            csstr += format_time(changeset.committed_on) + " - " + changeset.author.to_s
-            pdf.RDMCell(190, 5, csstr)
-            pdf.Ln
-            unless changeset.comments.blank?
-              pdf.SetFontStyle('',8)
-              pdf.RDMwriteHTMLCell(190,5,0,0,
-                    changeset.comments.to_s, issue.attachments, "")
-            end
-            pdf.Ln
-          end
-        end
-
-        if assoc[:journals].present?
-          pdf.SetFontStyle('B',9)
-          pdf.RDMCell(190,5, l(:label_history), "B")
-          pdf.Ln
-          assoc[:journals].each do |journal|
-            pdf.SetFontStyle('B',8)
-            title = "##{journal.indice} - #{format_time(journal.created_on)} - #{journal.user}"
-            title << " (#{l(:field_private_notes)})" if journal.private_notes?
-            pdf.RDMCell(190,5, title)
-            pdf.Ln
-            pdf.SetFontStyle('I',8)
-            details_to_strings(journal.visible_details, true).each do |string|
-              pdf.RDMMultiCell(190,5, "- " + string)
-            end
-            if journal.notes?
-              pdf.Ln unless journal.details.empty?
-              pdf.SetFontStyle('',8)
-              pdf.RDMwriteHTMLCell(190,5,0,0,
-                    journal.notes.to_s, issue.attachments, "")
-            end
-            pdf.Ln
-          end
-        end
-
-        if issue.attachments.any?
-          pdf.SetFontStyle('B',9)
-          pdf.RDMCell(190,5, l(:label_attachment_plural), "B")
-          pdf.Ln
-          for attachment in issue.attachments
-            pdf.SetFontStyle('',8)
-            pdf.RDMCell(80,5, attachment.filename)
-            pdf.RDMCell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
-            pdf.RDMCell(25,5, format_date(attachment.created_on),0,0,"R")
-            pdf.RDMCell(65,5, attachment.author.name,0,0,"R")
-            pdf.Ln
-          end
-        end
-        pdf.Output
-      end
-
-      # Returns a PDF string of a set of wiki pages
-      def wiki_pages_to_pdf(pages, project)
-        pdf = ITCPDF.new(current_language)
-        pdf.SetTitle(project.name)
-        pdf.alias_nb_pages
-        pdf.footer_date = format_date(Date.today)
-        pdf.AddPage
-        pdf.SetFontStyle('B',11)
-        pdf.RDMMultiCell(190,5, project.name)
-        pdf.Ln
-        # Set resize image scale
-        pdf.SetImageScale(1.6)
-        pdf.SetFontStyle('',9)
-        write_page_hierarchy(pdf, pages.group_by(&:parent_id))
-        pdf.Output
-      end
-
-      # Returns a PDF string of a single wiki page
-      def wiki_page_to_pdf(page, project)
-        pdf = ITCPDF.new(current_language)
-        pdf.SetTitle("#{project} - #{page.title}")
-        pdf.alias_nb_pages
-        pdf.footer_date = format_date(Date.today)
-        pdf.AddPage
-        pdf.SetFontStyle('B',11)
-        pdf.RDMMultiCell(190,5,
-             "#{project} - #{page.title} - # #{page.content.version}")
-        pdf.Ln
-        # Set resize image scale
-        pdf.SetImageScale(1.6)
-        pdf.SetFontStyle('',9)
-        write_wiki_page(pdf, page)
-        pdf.Output
-      end
-
-      def write_page_hierarchy(pdf, pages, node=nil, level=0)
-        if pages[node]
-          pages[node].each do |page|
-            if @new_page
-              pdf.AddPage
-            else
-              @new_page = true
-            end
-            pdf.Bookmark page.title, level
-            write_wiki_page(pdf, page)
-            write_page_hierarchy(pdf, pages, page.id, level + 1) if pages[page.id]
-          end
-        end
-      end
-
-      def write_wiki_page(pdf, page)
-        pdf.RDMwriteHTMLCell(190,5,0,0,
-              page.content.text.to_s, page.attachments, 0)
-        if page.attachments.any?
-          pdf.Ln
-          pdf.SetFontStyle('B',9)
-          pdf.RDMCell(190,5, l(:label_attachment_plural), "B")
-          pdf.Ln
-          for attachment in page.attachments
-            pdf.SetFontStyle('',8)
-            pdf.RDMCell(80,5, attachment.filename)
-            pdf.RDMCell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
-            pdf.RDMCell(25,5, format_date(attachment.created_on),0,0,"R")
-            pdf.RDMCell(65,5, attachment.author.name,0,0,"R")
-            pdf.Ln
-          end
-        end
-      end
-
-      class RDMPdfEncoding
-        def self.rdm_from_utf8(txt, encoding)
-          txt ||= ''
-          txt = Redmine::CodesetUtil.from_utf8(txt, encoding)
-          if txt.respond_to?(:force_encoding)
-            txt.force_encoding('ASCII-8BIT')
-          end
-          txt
-        end
-
-        def self.attach(attachments, filename, encoding)
-          filename_utf8 = Redmine::CodesetUtil.to_utf8(filename, encoding)
-          atta = nil
-          if filename_utf8 =~ /^[^\/"]+\.(gif|jpg|jpe|jpeg|png)$/i
-            atta = Attachment.latest_attach(attachments, filename_utf8)
-          end
-          if atta && atta.readable? && atta.visible?
-            return atta
-          else
-            return nil
-          end
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/a3/a363794048b21aea80eb83bb41f65aa9764ee31a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingRolesTest < ActionController::IntegrationTest
-  def test_roles
-    assert_routing(
-        { :method => 'get', :path => "/roles" },
-        { :controller => 'roles', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/roles.xml" },
-        { :controller => 'roles', :action => 'index', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/roles/2.xml" },
-        { :controller => 'roles', :action => 'show', :id => '2', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/roles/new" },
-        { :controller => 'roles', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/roles" },
-        { :controller => 'roles', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/roles/2/edit" },
-        { :controller => 'roles', :action => 'edit', :id => '2' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/roles/2" },
-        { :controller => 'roles', :action => 'update', :id => '2' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/roles/2" },
-        { :controller => 'roles', :action => 'destroy', :id => '2' }
-      )
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/roles/permissions" },
-          { :controller => 'roles', :action => 'permissions' }
-        )
-    end
-  end
-end
--- a/.svn/pristine/a5/a5ff178355e2e2f0f7b0355d9d02e0157c346174.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class EnumerationsControllerTest < ActionController::TestCase
-  fixtures :enumerations, :issues, :users
-
-  def setup
-    @request.session[:user_id] = 1 # admin
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-  end
-
-  def test_index_should_require_admin
-    @request.session[:user_id] = nil
-    get :index
-    assert_response 302
-  end
-
-  def test_new
-    get :new, :type => 'IssuePriority'
-    assert_response :success
-    assert_template 'new'
-    assert_kind_of IssuePriority, assigns(:enumeration)
-    assert_tag 'input', :attributes => {:name => 'enumeration[type]', :value => 'IssuePriority'}
-    assert_tag 'input', :attributes => {:name => 'enumeration[name]'}
-  end
-
-  def test_new_with_invalid_type_should_respond_with_404
-    get :new, :type => 'UnknownType'
-    assert_response 404
-  end
-
-  def test_create
-    assert_difference 'IssuePriority.count' do
-      post :create, :enumeration => {:type => 'IssuePriority', :name => 'Lowest'}
-    end
-    assert_redirected_to '/enumerations'
-    e = IssuePriority.find_by_name('Lowest')
-    assert_not_nil e
-  end
-
-  def test_create_with_failure
-    assert_no_difference 'IssuePriority.count' do
-      post :create, :enumeration => {:type => 'IssuePriority', :name => ''}
-    end
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_edit
-    get :edit, :id => 6
-    assert_response :success
-    assert_template 'edit'
-    assert_tag 'input', :attributes => {:name => 'enumeration[name]', :value => 'High'}
-  end
-
-  def test_edit_invalid_should_respond_with_404
-    get :edit, :id => 999
-    assert_response 404
-  end
-
-  def test_update
-    assert_no_difference 'IssuePriority.count' do
-      put :update, :id => 6, :enumeration => {:type => 'IssuePriority', :name => 'New name'}
-    end
-    assert_redirected_to '/enumerations'
-    e = IssuePriority.find(6)
-    assert_equal 'New name', e.name
-  end
-
-  def test_update_with_failure
-    assert_no_difference 'IssuePriority.count' do
-      put :update, :id => 6, :enumeration => {:type => 'IssuePriority', :name => ''}
-    end
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_destroy_enumeration_not_in_use
-    assert_difference 'IssuePriority.count', -1 do
-      delete :destroy, :id => 7
-    end
-    assert_redirected_to :controller => 'enumerations', :action => 'index'
-    assert_nil Enumeration.find_by_id(7)
-  end
-
-  def test_destroy_enumeration_in_use
-    assert_no_difference 'IssuePriority.count' do
-      delete :destroy, :id => 4
-    end
-    assert_response :success
-    assert_template 'destroy'
-    assert_not_nil Enumeration.find_by_id(4)
-    assert_select 'select[name=reassign_to_id]' do
-      assert_select 'option[value=6]', :text => 'High'
-    end
-  end
-
-  def test_destroy_enumeration_in_use_with_reassignment
-    issue = Issue.where(:priority_id => 4).first
-    assert_difference 'IssuePriority.count', -1 do
-      delete :destroy, :id => 4, :reassign_to_id => 6
-    end
-    assert_redirected_to :controller => 'enumerations', :action => 'index'
-    assert_nil Enumeration.find_by_id(4)
-    # check that the issue was reassign
-    assert_equal 6, issue.reload.priority_id
-  end
-
-  def test_destroy_enumeration_in_use_with_blank_reassignment
-    assert_no_difference 'IssuePriority.count' do
-      delete :destroy, :id => 4, :reassign_to_id => ''
-    end
-    assert_response :success
-  end
-end
--- a/.svn/pristine/a6/a6c2d0d0b8c42346610cefc80f58028a31c51655.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class MemberRole < ActiveRecord::Base
-  belongs_to :member
-  belongs_to :role
-
-  after_destroy :remove_member_if_empty
-
-  after_create :add_role_to_group_users, :add_role_to_subprojects
-  after_destroy :remove_inherited_roles
-
-  validates_presence_of :role
-  validate :validate_role_member
-
-  def validate_role_member
-    errors.add :role_id, :invalid if role && !role.member?
-  end
-
-  def inherited?
-    !inherited_from.nil?
-  end
-
-  private
-
-  def remove_member_if_empty
-    if member.roles.empty?
-      member.destroy
-    end
-  end
-
-  def add_role_to_group_users
-    if member.principal.is_a?(Group) && !inherited?
-      member.principal.users.each do |user|
-        user_member = Member.find_or_new(member.project_id, user.id)
-        user_member.member_roles << MemberRole.new(:role => role, :inherited_from => id)
-        user_member.save!
-      end
-    end
-  end
-
-  def add_role_to_subprojects
-    member.project.children.each do |subproject|
-      if subproject.inherit_members?
-        child_member = Member.find_or_new(subproject.id, member.user_id)
-        child_member.member_roles << MemberRole.new(:role => role, :inherited_from => id)
-        child_member.save!
-      end
-    end
-  end
-
-  def remove_inherited_roles
-    MemberRole.where(:inherited_from => id).all.group_by(&:member).each do |member, member_roles|
-      member_roles.each(&:destroy)
-    end
-  end
-end
--- a/.svn/pristine/a9/a913b8238cb5eb5f60c33b311ea63769c5ce7d24.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,956 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WikiControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :enabled_modules, :wikis, :wiki_pages, :wiki_contents,
-           :wiki_content_versions, :attachments
-
-  def setup
-    User.current = nil
-  end
-
-  def test_show_start_page
-    get :show, :project_id => 'ecookbook'
-    assert_response :success
-    assert_template 'show'
-    assert_tag :tag => 'h1', :content => /CookBook documentation/
-
-    # child_pages macro
-    assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
-               :child => { :tag => 'li',
-                           :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
-                                                    :content => 'Page with an inline image' } }
-  end
-  
-  def test_export_link
-    Role.anonymous.add_permission! :export_wiki_pages
-    get :show, :project_id => 'ecookbook'
-    assert_response :success
-    assert_tag 'a', :attributes => {:href => '/projects/ecookbook/wiki/CookBook_documentation.txt'}
-  end
-
-  def test_show_page_with_name
-    get :show, :project_id => 1, :id => 'Another_page'
-    assert_response :success
-    assert_template 'show'
-    assert_tag :tag => 'h1', :content => /Another page/
-    # Included page with an inline image
-    assert_tag :tag => 'p', :content => /This is an inline image/
-    assert_tag :tag => 'img', :attributes => { :src => '/attachments/download/3/logo.gif',
-                                               :alt => 'This is a logo' }
-  end
-
-  def test_show_old_version
-    get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
-    assert_response :success
-    assert_template 'show'
-
-    assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/1', :text => /Previous/
-    assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/diff', :text => /diff/
-    assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/3', :text => /Next/
-    assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => /Current version/
-  end
-
-  def test_show_old_version_with_attachments
-    page = WikiPage.find(4)
-    assert page.attachments.any?
-    content = page.content
-    content.text = "update"
-    content.save!
-
-    get :show, :project_id => 'ecookbook', :id => page.title, :version => '1'
-    assert_kind_of WikiContent::Version, assigns(:content)
-    assert_response :success
-    assert_template 'show'
-  end
-
-  def test_show_old_version_without_permission_should_be_denied
-    Role.anonymous.remove_permission! :view_wiki_edits
-
-    get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
-    assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fprojects%2Fecookbook%2Fwiki%2FCookBook_documentation%2F2'
-  end
-
-  def test_show_first_version
-    get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '1'
-    assert_response :success
-    assert_template 'show'
-
-    assert_select 'a', :text => /Previous/, :count => 0
-    assert_select 'a', :text => /diff/, :count => 0
-    assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => /Next/
-    assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => /Current version/
-  end
-
-  def test_show_redirected_page
-    WikiRedirect.create!(:wiki_id => 1, :title => 'Old_title', :redirects_to => 'Another_page')
-
-    get :show, :project_id => 'ecookbook', :id => 'Old_title'
-    assert_redirected_to '/projects/ecookbook/wiki/Another_page'
-  end
-
-  def test_show_with_sidebar
-    page = Project.find(1).wiki.pages.new(:title => 'Sidebar')
-    page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
-    page.save!
-
-    get :show, :project_id => 1, :id => 'Another_page'
-    assert_response :success
-    assert_tag :tag => 'div', :attributes => {:id => 'sidebar'},
-                              :content => /Side bar content for test_show_with_sidebar/
-  end
-  
-  def test_show_should_display_section_edit_links
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :id => 'Page with sections'
-    assert_no_tag 'a', :attributes => {
-      :href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=1'
-    }
-    assert_tag 'a', :attributes => {
-      :href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
-    }
-    assert_tag 'a', :attributes => {
-      :href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=3'
-    }
-  end
-
-  def test_show_current_version_should_display_section_edit_links
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :id => 'Page with sections', :version => 3
-
-    assert_tag 'a', :attributes => {
-      :href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
-    }
-  end
-
-  def test_show_old_version_should_not_display_section_edit_links
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :id => 'Page with sections', :version => 2
-
-    assert_no_tag 'a', :attributes => {
-      :href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
-    }
-  end
-
-  def test_show_unexistent_page_without_edit_right
-    get :show, :project_id => 1, :id => 'Unexistent page'
-    assert_response 404
-  end
-
-  def test_show_unexistent_page_with_edit_right
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :id => 'Unexistent page'
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_show_unexistent_page_with_parent_should_preselect_parent
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :id => 'Unexistent page', :parent => 'Another_page'
-    assert_response :success
-    assert_template 'edit'
-    assert_tag 'select', :attributes => {:name => 'wiki_page[parent_id]'},
-      :child => {:tag => 'option', :attributes => {:value => '2', :selected => 'selected'}}
-  end
-
-  def test_show_should_not_show_history_without_permission
-    Role.anonymous.remove_permission! :view_wiki_edits
-    get :show, :project_id => 1, :id => 'Page with sections', :version => 2
-
-    assert_response 302
-  end
-
-  def test_show_page_without_content_should_display_the_edit_form
-    @request.session[:user_id] = 2
-    WikiPage.create!(:title => 'NoContent', :wiki => Project.find(1).wiki)
-
-    get :show, :project_id => 1, :id => 'NoContent'
-    assert_response :success
-    assert_template 'edit'
-    assert_select 'textarea[name=?]', 'content[text]'
-  end
-
-  def test_create_page
-    @request.session[:user_id] = 2
-    assert_difference 'WikiPage.count' do
-      assert_difference 'WikiContent.count' do
-        put :update, :project_id => 1,
-                    :id => 'New page',
-                    :content => {:comments => 'Created the page',
-                                 :text => "h1. New page\n\nThis is a new page",
-                                 :version => 0}
-      end
-    end
-    assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'New_page'
-    page = Project.find(1).wiki.find_page('New page')
-    assert !page.new_record?
-    assert_not_nil page.content
-    assert_nil page.parent
-    assert_equal 'Created the page', page.content.comments
-  end
-
-  def test_create_page_with_attachments
-    @request.session[:user_id] = 2
-    assert_difference 'WikiPage.count' do
-      assert_difference 'Attachment.count' do
-        put :update, :project_id => 1,
-                    :id => 'New page',
-                    :content => {:comments => 'Created the page',
-                                 :text => "h1. New page\n\nThis is a new page",
-                                 :version => 0},
-                    :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
-      end
-    end
-    page = Project.find(1).wiki.find_page('New page')
-    assert_equal 1, page.attachments.count
-    assert_equal 'testfile.txt', page.attachments.first.filename
-  end
-
-  def test_create_page_with_parent
-    @request.session[:user_id] = 2
-    assert_difference 'WikiPage.count' do
-      put :update, :project_id => 1, :id => 'New page',
-        :content => {:text => "h1. New page\n\nThis is a new page", :version => 0},
-        :wiki_page => {:parent_id => 2}
-    end
-    page = Project.find(1).wiki.find_page('New page')
-    assert_equal WikiPage.find(2), page.parent
-  end
-
-  def test_edit_page
-    @request.session[:user_id] = 2
-    get :edit, :project_id => 'ecookbook', :id => 'Another_page'
-
-    assert_response :success
-    assert_template 'edit'
-
-    assert_tag 'textarea',
-      :attributes => { :name => 'content[text]' },
-      :content => "\n"+WikiPage.find_by_title('Another_page').content.text
-  end
-
-  def test_edit_section
-    @request.session[:user_id] = 2
-    get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 2
-
-    assert_response :success
-    assert_template 'edit'
-    
-    page = WikiPage.find_by_title('Page_with_sections')
-    section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
-
-    assert_tag 'textarea',
-      :attributes => { :name => 'content[text]' },
-      :content => "\n"+section
-    assert_tag 'input',
-      :attributes => { :name => 'section', :type => 'hidden', :value => '2' }
-    assert_tag 'input',
-      :attributes => { :name => 'section_hash', :type => 'hidden', :value => hash }
-  end
-
-  def test_edit_invalid_section_should_respond_with_404
-    @request.session[:user_id] = 2
-    get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 10
-
-    assert_response 404
-  end
-
-  def test_update_page
-    @request.session[:user_id] = 2
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_difference 'WikiContent::Version.count' do
-          put :update, :project_id => 1,
-            :id => 'Another_page',
-            :content => {
-              :comments => "my comments",
-              :text => "edited",
-              :version => 1
-            }
-        end
-      end
-    end
-    assert_redirected_to '/projects/ecookbook/wiki/Another_page'
-
-    page = Wiki.find(1).pages.find_by_title('Another_page')
-    assert_equal "edited", page.content.text
-    assert_equal 2, page.content.version
-    assert_equal "my comments", page.content.comments
-  end
-
-  def test_update_page_with_parent
-    @request.session[:user_id] = 2
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_difference 'WikiContent::Version.count' do
-          put :update, :project_id => 1,
-            :id => 'Another_page',
-            :content => {
-              :comments => "my comments",
-              :text => "edited",
-              :version => 1
-            },
-            :wiki_page => {:parent_id => '1'}
-        end
-      end
-    end
-    assert_redirected_to '/projects/ecookbook/wiki/Another_page'
-
-    page = Wiki.find(1).pages.find_by_title('Another_page')
-    assert_equal "edited", page.content.text
-    assert_equal 2, page.content.version
-    assert_equal "my comments", page.content.comments
-    assert_equal WikiPage.find(1), page.parent
-  end
-
-  def test_update_page_with_failure
-    @request.session[:user_id] = 2
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_no_difference 'WikiContent::Version.count' do
-          put :update, :project_id => 1,
-            :id => 'Another_page',
-            :content => {
-              :comments => 'a' * 300,  # failure here, comment is too long
-              :text => 'edited',
-              :version => 1
-            }
-          end
-        end
-      end
-    assert_response :success
-    assert_template 'edit'
-
-    assert_error_tag :descendant => {:content => /Comment is too long/}
-    assert_tag :tag => 'textarea', :attributes => {:id => 'content_text'}, :content => "\nedited"
-    assert_tag :tag => 'input', :attributes => {:id => 'content_version', :value => '1'}
-  end
-
-  def test_update_page_with_parent_change_only_should_not_create_content_version
-    @request.session[:user_id] = 2
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_no_difference 'WikiContent::Version.count' do
-          put :update, :project_id => 1,
-            :id => 'Another_page',
-            :content => {
-              :comments => '',
-              :text => Wiki.find(1).find_page('Another_page').content.text,
-              :version => 1
-            },
-            :wiki_page => {:parent_id => '1'}
-        end
-      end
-    end
-    page = Wiki.find(1).pages.find_by_title('Another_page')
-    assert_equal 1, page.content.version
-    assert_equal WikiPage.find(1), page.parent
-  end
-
-  def test_update_page_with_attachments_only_should_not_create_content_version
-    @request.session[:user_id] = 2
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_no_difference 'WikiContent::Version.count' do
-          assert_difference 'Attachment.count' do
-            put :update, :project_id => 1,
-              :id => 'Another_page',
-              :content => {
-                :comments => '',
-                :text => Wiki.find(1).find_page('Another_page').content.text,
-                :version => 1
-              },
-              :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
-          end
-        end
-      end
-    end
-    page = Wiki.find(1).pages.find_by_title('Another_page')
-    assert_equal 1, page.content.version
-  end
-
-  def test_update_stale_page_should_not_raise_an_error
-    @request.session[:user_id] = 2
-    c = Wiki.find(1).find_page('Another_page').content
-    c.text = 'Previous text'
-    c.save!
-    assert_equal 2, c.version
-
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_no_difference 'WikiContent::Version.count' do
-          put :update, :project_id => 1,
-            :id => 'Another_page',
-            :content => {
-              :comments => 'My comments',
-              :text => 'Text should not be lost',
-              :version => 1
-            }
-        end
-      end
-    end
-    assert_response :success
-    assert_template 'edit'
-    assert_tag :div,
-      :attributes => { :class => /error/ },
-      :content => /Data has been updated by another user/
-    assert_tag 'textarea',
-      :attributes => { :name => 'content[text]' },
-      :content => /Text should not be lost/
-    assert_tag 'input',
-      :attributes => { :name => 'content[comments]', :value => 'My comments' }
-
-    c.reload
-    assert_equal 'Previous text', c.text
-    assert_equal 2, c.version
-  end
-
-  def test_update_page_without_content_should_create_content
-    @request.session[:user_id] = 2
-    page = WikiPage.create!(:title => 'NoContent', :wiki => Project.find(1).wiki)
-
-    assert_no_difference 'WikiPage.count' do
-      assert_difference 'WikiContent.count' do
-        put :update, :project_id => 1, :id => 'NoContent', :content => {:text => 'Some content'}
-        assert_response 302
-      end
-    end
-    assert_equal 'Some content', page.reload.content.text
-  end
-
-  def test_update_section
-    @request.session[:user_id] = 2
-    page = WikiPage.find_by_title('Page_with_sections')
-    section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
-    text = page.content.text
-
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_difference 'WikiContent::Version.count' do
-          put :update, :project_id => 1, :id => 'Page_with_sections',
-            :content => {
-              :text => "New section content",
-              :version => 3
-            },
-            :section => 2,
-            :section_hash => hash
-        end
-      end
-    end
-    assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections#section-2'
-    assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.reload.content.text
-  end
-
-  def test_update_section_should_allow_stale_page_update
-    @request.session[:user_id] = 2
-    page = WikiPage.find_by_title('Page_with_sections')
-    section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
-    text = page.content.text
-
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_difference 'WikiContent::Version.count' do
-          put :update, :project_id => 1, :id => 'Page_with_sections',
-            :content => {
-              :text => "New section content",
-              :version => 2 # Current version is 3
-            },
-            :section => 2,
-            :section_hash => hash
-        end
-      end
-    end
-    assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections#section-2'
-    page.reload
-    assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.content.text
-    assert_equal 4, page.content.version
-  end
-
-  def test_update_section_should_not_allow_stale_section_update
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent.count' do
-        assert_no_difference 'WikiContent::Version.count' do
-          put :update, :project_id => 1, :id => 'Page_with_sections',
-            :content => {
-              :comments => 'My comments',
-              :text => "Text should not be lost",
-              :version => 3
-            },
-            :section => 2,
-            :section_hash => Digest::MD5.hexdigest("wrong hash")
-        end
-      end
-    end
-    assert_response :success
-    assert_template 'edit'
-    assert_tag :div,
-      :attributes => { :class => /error/ },
-      :content => /Data has been updated by another user/
-    assert_tag 'textarea',
-      :attributes => { :name => 'content[text]' },
-      :content => /Text should not be lost/
-    assert_tag 'input',
-      :attributes => { :name => 'content[comments]', :value => 'My comments' }
-  end
-
-  def test_preview
-    @request.session[:user_id] = 2
-    xhr :post, :preview, :project_id => 1, :id => 'CookBook_documentation',
-                                   :content => { :comments => '',
-                                                 :text => 'this is a *previewed text*',
-                                                 :version => 3 }
-    assert_response :success
-    assert_template 'common/_preview'
-    assert_tag :tag => 'strong', :content => /previewed text/
-  end
-
-  def test_preview_new_page
-    @request.session[:user_id] = 2
-    xhr :post, :preview, :project_id => 1, :id => 'New page',
-                                   :content => { :text => 'h1. New page',
-                                                 :comments => '',
-                                                 :version => 0 }
-    assert_response :success
-    assert_template 'common/_preview'
-    assert_tag :tag => 'h1', :content => /New page/
-  end
-
-  def test_history
-    @request.session[:user_id] = 2
-    get :history, :project_id => 'ecookbook', :id => 'CookBook_documentation'
-    assert_response :success
-    assert_template 'history'
-    assert_not_nil assigns(:versions)
-    assert_equal 3, assigns(:versions).size
-
-    assert_select "input[type=submit][name=commit]"
-    assert_select 'td' do
-      assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => '2'
-      assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/annotate', :text => 'Annotate'
-      assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => 'Delete'
-    end
-  end
-
-  def test_history_with_one_version
-    @request.session[:user_id] = 2
-    get :history, :project_id => 'ecookbook', :id => 'Another_page'
-    assert_response :success
-    assert_template 'history'
-    assert_not_nil assigns(:versions)
-    assert_equal 1, assigns(:versions).size
-    assert_select "input[type=submit][name=commit]", false
-    assert_select 'td' do
-      assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => '1'
-      assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1/annotate', :text => 'Annotate'
-      assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => 'Delete', :count => 0
-    end
-  end
-
-  def test_diff
-    content = WikiPage.find(1).content
-    assert_difference 'WikiContent::Version.count', 2 do
-      content.text = "Line removed\nThis is a sample text for testing diffs"
-      content.save!
-      content.text = "This is a sample text for testing diffs\nLine added"
-      content.save!
-    end
-
-    get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => content.version, :version_from => (content.version - 1)
-    assert_response :success
-    assert_template 'diff'
-    assert_select 'span.diff_out', :text => 'Line removed'
-    assert_select 'span.diff_in', :text => 'Line added'
-  end
-
-  def test_diff_with_invalid_version_should_respond_with_404
-    get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => '99'
-    assert_response 404
-  end
-
-  def test_diff_with_invalid_version_from_should_respond_with_404
-    get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => '99', :version_from => '98'
-    assert_response 404
-  end
-
-  def test_annotate
-    get :annotate, :project_id => 1, :id =>  'CookBook_documentation', :version => 2
-    assert_response :success
-    assert_template 'annotate'
-
-    # Line 1
-    assert_tag :tag => 'tr', :child => {
-      :tag => 'th', :attributes => {:class => 'line-num'}, :content => '1', :sibling => {
-        :tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/, :sibling => {
-          :tag => 'td', :content => /h1\. CookBook documentation/
-        }
-      }
-    }
-
-    # Line 5
-    assert_tag :tag => 'tr', :child => {
-      :tag => 'th', :attributes => {:class => 'line-num'}, :content => '5', :sibling => {
-        :tag => 'td', :attributes => {:class => 'author'}, :content => /Redmine Admin/, :sibling => {
-          :tag => 'td', :content => /Some updated \[\[documentation\]\] here/
-        }
-      }
-    }
-  end
-
-  def test_annotate_with_invalid_version_should_respond_with_404
-    get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => '99'
-    assert_response 404
-  end
-
-  def test_get_rename
-    @request.session[:user_id] = 2
-    get :rename, :project_id => 1, :id => 'Another_page'
-    assert_response :success
-    assert_template 'rename'
-    assert_tag 'option',
-      :attributes => {:value => ''},
-      :content => '',
-      :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
-    assert_no_tag 'option',
-      :attributes => {:selected => 'selected'},
-      :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
-  end
-
-  def test_get_rename_child_page
-    @request.session[:user_id] = 2
-    get :rename, :project_id => 1, :id => 'Child_1'
-    assert_response :success
-    assert_template 'rename'
-    assert_tag 'option',
-      :attributes => {:value => ''},
-      :content => '',
-      :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
-    assert_tag 'option',
-      :attributes => {:value => '2', :selected => 'selected'},
-      :content => /Another page/,
-      :parent => {
-        :tag => 'select',
-        :attributes => {:name => 'wiki_page[parent_id]'}
-      }
-  end
-
-  def test_rename_with_redirect
-    @request.session[:user_id] = 2
-    post :rename, :project_id => 1, :id => 'Another_page',
-                            :wiki_page => { :title => 'Another renamed page',
-                                            :redirect_existing_links => 1 }
-    assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
-    wiki = Project.find(1).wiki
-    # Check redirects
-    assert_not_nil wiki.find_page('Another page')
-    assert_nil wiki.find_page('Another page', :with_redirect => false)
-  end
-
-  def test_rename_without_redirect
-    @request.session[:user_id] = 2
-    post :rename, :project_id => 1, :id => 'Another_page',
-                            :wiki_page => { :title => 'Another renamed page',
-                                            :redirect_existing_links => "0" }
-    assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
-    wiki = Project.find(1).wiki
-    # Check that there's no redirects
-    assert_nil wiki.find_page('Another page')
-  end
-
-  def test_rename_with_parent_assignment
-    @request.session[:user_id] = 2
-    post :rename, :project_id => 1, :id => 'Another_page',
-      :wiki_page => { :title => 'Another page', :redirect_existing_links => "0", :parent_id => '4' }
-    assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
-    assert_equal WikiPage.find(4), WikiPage.find_by_title('Another_page').parent
-  end
-
-  def test_rename_with_parent_unassignment
-    @request.session[:user_id] = 2
-    post :rename, :project_id => 1, :id => 'Child_1',
-      :wiki_page => { :title => 'Child 1', :redirect_existing_links => "0", :parent_id => '' }
-    assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Child_1'
-    assert_nil WikiPage.find_by_title('Child_1').parent
-  end
-
-  def test_destroy_a_page_without_children_should_not_ask_confirmation
-    @request.session[:user_id] = 2
-    delete :destroy, :project_id => 1, :id => 'Child_2'
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-  end
-
-  def test_destroy_parent_should_ask_confirmation
-    @request.session[:user_id] = 2
-    assert_no_difference('WikiPage.count') do
-      delete :destroy, :project_id => 1, :id => 'Another_page'
-    end
-    assert_response :success
-    assert_template 'destroy'
-    assert_select 'form' do
-      assert_select 'input[name=todo][value=nullify]'
-      assert_select 'input[name=todo][value=destroy]'
-      assert_select 'input[name=todo][value=reassign]'
-    end
-  end
-
-  def test_destroy_parent_with_nullify_should_delete_parent_only
-    @request.session[:user_id] = 2
-    assert_difference('WikiPage.count', -1) do
-      delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'nullify'
-    end
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    assert_nil WikiPage.find_by_id(2)
-  end
-
-  def test_destroy_parent_with_cascade_should_delete_descendants
-    @request.session[:user_id] = 2
-    assert_difference('WikiPage.count', -4) do
-      delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'destroy'
-    end
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    assert_nil WikiPage.find_by_id(2)
-    assert_nil WikiPage.find_by_id(5)
-  end
-
-  def test_destroy_parent_with_reassign
-    @request.session[:user_id] = 2
-    assert_difference('WikiPage.count', -1) do
-      delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'reassign', :reassign_to_id => 1
-    end
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    assert_nil WikiPage.find_by_id(2)
-    assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
-  end
-
-  def test_destroy_version
-    @request.session[:user_id] = 2
-    assert_difference 'WikiContent::Version.count', -1 do
-      assert_no_difference 'WikiContent.count' do
-        assert_no_difference 'WikiPage.count' do
-          delete :destroy_version, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => 2
-          assert_redirected_to '/projects/ecookbook/wiki/CookBook_documentation/history'
-        end
-      end
-    end
-  end
-
-  def test_index
-    get :index, :project_id => 'ecookbook'
-    assert_response :success
-    assert_template 'index'
-    pages = assigns(:pages)
-    assert_not_nil pages
-    assert_equal Project.find(1).wiki.pages.size, pages.size
-    assert_equal pages.first.content.updated_on, pages.first.updated_on
-
-    assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
-                    :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/CookBook_documentation' },
-                                              :content => 'CookBook documentation' },
-                                :child => { :tag => 'ul',
-                                            :child => { :tag => 'li',
-                                                        :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
-                                                                                 :content => 'Page with an inline image' } } } },
-                    :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Another_page' },
-                                                                       :content => 'Another page' } }
-  end
-
-  def test_index_should_include_atom_link
-    get :index, :project_id => 'ecookbook'
-    assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
-  end
-
-  def test_export_to_html
-    @request.session[:user_id] = 2
-    get :export, :project_id => 'ecookbook'
-
-    assert_response :success
-    assert_not_nil assigns(:pages)
-    assert assigns(:pages).any?
-    assert_equal "text/html", @response.content_type
-
-    assert_select "a[name=?]", "CookBook_documentation"
-    assert_select "a[name=?]", "Another_page"
-    assert_select "a[name=?]", "Page_with_an_inline_image"
-  end
-
-  def test_export_to_pdf
-    @request.session[:user_id] = 2
-    get :export, :project_id => 'ecookbook', :format => 'pdf'
-
-    assert_response :success
-    assert_not_nil assigns(:pages)
-    assert assigns(:pages).any?
-    assert_equal 'application/pdf', @response.content_type
-    assert_equal 'attachment; filename="ecookbook.pdf"', @response.headers['Content-Disposition']
-    assert @response.body.starts_with?('%PDF')
-  end
-
-  def test_export_without_permission_should_be_denied
-    @request.session[:user_id] = 2
-    Role.find_by_name('Manager').remove_permission! :export_wiki_pages
-    get :export, :project_id => 'ecookbook'
-
-    assert_response 403
-  end
-
-  def test_date_index
-    get :date_index, :project_id => 'ecookbook'
-
-    assert_response :success
-    assert_template 'date_index'
-    assert_not_nil assigns(:pages)
-    assert_not_nil assigns(:pages_by_date)
-
-    assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
-  end
-
-  def test_not_found
-    get :show, :project_id => 999
-    assert_response 404
-  end
-
-  def test_protect_page
-    page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
-    assert !page.protected?
-    @request.session[:user_id] = 2
-    post :protect, :project_id => 1, :id => page.title, :protected => '1'
-    assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
-    assert page.reload.protected?
-  end
-
-  def test_unprotect_page
-    page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
-    assert page.protected?
-    @request.session[:user_id] = 2
-    post :protect, :project_id => 1, :id => page.title, :protected => '0'
-    assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'CookBook_documentation'
-    assert !page.reload.protected?
-  end
-
-  def test_show_page_with_edit_link
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1
-    assert_response :success
-    assert_template 'show'
-    assert_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
-  end
-
-  def test_show_page_without_edit_link
-    @request.session[:user_id] = 4
-    get :show, :project_id => 1
-    assert_response :success
-    assert_template 'show'
-    assert_no_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
-  end
-
-  def test_show_pdf
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :format => 'pdf'
-    assert_response :success
-    assert_not_nil assigns(:page)
-    assert_equal 'application/pdf', @response.content_type
-    assert_equal 'attachment; filename="CookBook_documentation.pdf"',
-                  @response.headers['Content-Disposition']
-  end
-
-  def test_show_html
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :format => 'html'
-    assert_response :success
-    assert_not_nil assigns(:page)
-    assert_equal 'text/html', @response.content_type
-    assert_equal 'attachment; filename="CookBook_documentation.html"',
-                  @response.headers['Content-Disposition']
-    assert_tag 'h1', :content => 'CookBook documentation'
-  end
-
-  def test_show_versioned_html
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :format => 'html', :version => 2
-    assert_response :success
-    assert_not_nil assigns(:content)
-    assert_equal 2, assigns(:content).version
-    assert_equal 'text/html', @response.content_type
-    assert_equal 'attachment; filename="CookBook_documentation.html"',
-                  @response.headers['Content-Disposition']
-    assert_tag 'h1', :content => 'CookBook documentation'
-  end
-
-  def test_show_txt
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :format => 'txt'
-    assert_response :success
-    assert_not_nil assigns(:page)
-    assert_equal 'text/plain', @response.content_type
-    assert_equal 'attachment; filename="CookBook_documentation.txt"',
-                  @response.headers['Content-Disposition']
-    assert_include 'h1. CookBook documentation', @response.body
-  end
-
-  def test_show_versioned_txt
-    @request.session[:user_id] = 2
-    get :show, :project_id => 1, :format => 'txt', :version => 2
-    assert_response :success
-    assert_not_nil assigns(:content)
-    assert_equal 2, assigns(:content).version
-    assert_equal 'text/plain', @response.content_type
-    assert_equal 'attachment; filename="CookBook_documentation.txt"',
-                  @response.headers['Content-Disposition']
-    assert_include 'h1. CookBook documentation', @response.body
-  end
-
-  def test_edit_unprotected_page
-    # Non members can edit unprotected wiki pages
-    @request.session[:user_id] = 4
-    get :edit, :project_id => 1, :id => 'Another_page'
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_edit_protected_page_by_nonmember
-    # Non members can't edit protected wiki pages
-    @request.session[:user_id] = 4
-    get :edit, :project_id => 1, :id => 'CookBook_documentation'
-    assert_response 403
-  end
-
-  def test_edit_protected_page_by_member
-    @request.session[:user_id] = 2
-    get :edit, :project_id => 1, :id => 'CookBook_documentation'
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_history_of_non_existing_page_should_return_404
-    get :history, :project_id => 1, :id => 'Unknown_page'
-    assert_response 404
-  end
-
-  def test_add_attachment
-    @request.session[:user_id] = 2
-    assert_difference 'Attachment.count' do
-      post :add_attachment, :project_id => 1, :id => 'CookBook_documentation',
-        :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
-    end
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_equal Wiki.find(1).find_page('CookBook_documentation'), attachment.container
-  end
-end
--- a/.svn/pristine/a9/a9efaf1639993585b08f796d4994f7cfff12bb4e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class WatchersController < ApplicationController
-  before_filter :require_login, :find_watchables, :only => [:watch, :unwatch]
-
-  def watch
-    set_watcher(@watchables, User.current, true)
-  end
-
-  def unwatch
-    set_watcher(@watchables, User.current, false)
-  end
-
-  before_filter :find_project, :authorize, :only => [:new, :create, :append, :destroy, :autocomplete_for_user]
-  accept_api_auth :create, :destroy
-
-  def new
-  end
-
-  def create
-    user_ids = []
-    if params[:watcher].is_a?(Hash)
-      user_ids << (params[:watcher][:user_ids] || params[:watcher][:user_id])
-    else
-      user_ids << params[:user_id]
-    end
-    user_ids.flatten.compact.uniq.each do |user_id|
-      Watcher.create(:watchable => @watched, :user_id => user_id)
-    end
-    respond_to do |format|
-      format.html { redirect_to_referer_or {render :text => 'Watcher added.', :layout => true}}
-      format.js
-      format.api { render_api_ok }
-    end
-  end
-
-  def append
-    if params[:watcher].is_a?(Hash)
-      user_ids = params[:watcher][:user_ids] || [params[:watcher][:user_id]]
-      @users = User.active.find_all_by_id(user_ids)
-    end
-  end
-
-  def destroy
-    @watched.set_watcher(User.find(params[:user_id]), false)
-    respond_to do |format|
-      format.html { redirect_to :back }
-      format.js
-      format.api { render_api_ok }
-    end
-  end
-
-  def autocomplete_for_user
-    @users = User.active.sorted.like(params[:q]).limit(100).all
-    if @watched
-      @users -= @watched.watcher_users
-    end
-    render :layout => false
-  end
-
-  private
-
-  def find_project
-    if params[:object_type] && params[:object_id]
-      klass = Object.const_get(params[:object_type].camelcase)
-      return false unless klass.respond_to?('watched_by')
-      @watched = klass.find(params[:object_id])
-      @project = @watched.project
-    elsif params[:project_id]
-      @project = Project.visible.find_by_param(params[:project_id])
-    end
-  rescue
-    render_404
-  end
-
-  def find_watchables
-    klass = Object.const_get(params[:object_type].camelcase) rescue nil
-    if klass && klass.respond_to?('watched_by')
-      @watchables = klass.find_all_by_id(Array.wrap(params[:object_id]))
-      raise Unauthorized if @watchables.any? {|w| w.respond_to?(:visible?) && !w.visible?}
-    end
-    render_404 unless @watchables.present?
-  end
-
-  def set_watcher(watchables, user, watching)
-    watchables.each do |watchable|
-      watchable.set_watcher(user, watching)
-    end
-    respond_to do |format|
-      format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
-      format.js { render :partial => 'set_watcher', :locals => {:user => user, :watched => watchables} }
-    end
-  end
-end
--- a/.svn/pristine/aa/aa4319d8f7d992a29eec92a78f6cd5cf0f5f274a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module AccessKeys
-    ACCESSKEYS = {:edit => 'e',
-                  :preview => 'r',
-                  :quick_search => 'f',
-                  :search => '4',
-                  :new_issue => '7'
-                 }.freeze unless const_defined?(:ACCESSKEYS)
-
-    def self.key_for(action)
-      ACCESSKEYS[action]
-    end
-  end
-end
--- a/.svn/pristine/aa/aa4c68d001b78663e7227468cb64b231f259e013.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ContextMenusControllerTest < ActionController::TestCase
-  fixtures :projects,
-           :trackers,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :workflows,
-           :journals, :journal_details,
-           :versions,
-           :issues, :issue_statuses, :issue_categories,
-           :users,
-           :enumerations,
-           :time_entries
-
-  def test_context_menu_one_issue
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1]
-    assert_response :success
-    assert_template 'context_menu'
-
-    assert_select 'a.icon-edit[href=?]', '/issues/1/edit', :text => 'Edit'
-    assert_select 'a.icon-copy[href=?]', '/projects/ecookbook/issues/1/copy', :text => 'Copy'
-    assert_select 'a.icon-del[href=?]', '/issues?ids%5B%5D=1', :text => 'Delete'
-
-    # Statuses
-    assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bstatus_id%5D=5', :text => 'Closed'
-    assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bpriority_id%5D=8', :text => 'Immediate'
-    # No inactive priorities
-    assert_select 'a', :text => /Inactive Priority/, :count => 0
-    # Versions
-    assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=3', :text => '2.0'
-    assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=4', :text => 'eCookbook Subproject 1 - 2.0'
-    # Assignees
-    assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bassigned_to_id%5D=3', :text => 'Dave Lopper'
-  end
-
-  def test_context_menu_one_issue_by_anonymous
-    get :issues, :ids => [1]
-    assert_response :success
-    assert_template 'context_menu'
-    assert_tag :tag => 'a', :content => 'Delete',
-                            :attributes => { :href => '#',
-                                             :class => 'icon-del disabled' }
-  end
-
-  def test_context_menu_multiple_issues_of_same_project
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1, 2]
-    assert_response :success
-    assert_template 'context_menu'
-    assert_not_nil assigns(:issues)
-    assert_equal [1, 2], assigns(:issues).map(&:id).sort
-
-    ids = assigns(:issues).map(&:id).sort.map {|i| "ids%5B%5D=#{i}"}.join('&amp;')
-
-    assert_select 'a.icon-edit[href=?]', "/issues/bulk_edit?#{ids}", :text => 'Edit'
-    assert_select 'a.icon-copy[href=?]', "/issues/bulk_edit?copy=1&amp;#{ids}", :text => 'Copy'
-    assert_select 'a.icon-del[href=?]', "/issues?#{ids}", :text => 'Delete'
-
-    assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;issue%5Bstatus_id%5D=5", :text => 'Closed'
-    assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;issue%5Bpriority_id%5D=8", :text => 'Immediate'
-    assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;issue%5Bassigned_to_id%5D=3", :text => 'Dave Lopper'
-  end
-
-  def test_context_menu_multiple_issues_of_different_projects
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1, 2, 6]
-    assert_response :success
-    assert_template 'context_menu'
-    assert_not_nil assigns(:issues)
-    assert_equal [1, 2, 6], assigns(:issues).map(&:id).sort
-
-    ids = assigns(:issues).map(&:id).sort.map {|i| "ids%5B%5D=#{i}"}.join('&amp;')
-
-    assert_select 'a.icon-edit[href=?]', "/issues/bulk_edit?#{ids}", :text => 'Edit'
-    assert_select 'a.icon-del[href=?]', "/issues?#{ids}", :text => 'Delete'
-
-    assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;issue%5Bstatus_id%5D=5", :text => 'Closed'
-    assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;issue%5Bpriority_id%5D=8", :text => 'Immediate'
-    assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;issue%5Bassigned_to_id%5D=2", :text => 'John Smith'
-  end
-
-  def test_context_menu_should_include_list_custom_fields
-    field = IssueCustomField.create!(:name => 'List', :field_format => 'list',
-      :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1]
-
-    assert_select "li.cf_#{field.id}" do
-      assert_select 'a[href=#]', :text => 'List'
-      assert_select 'ul' do
-        assert_select 'a', 3
-        assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=Foo", :text => 'Foo'
-        assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=__none__", :text => 'none'
-      end
-    end
-  end
-
-  def test_context_menu_should_not_include_null_value_for_required_custom_fields
-    field = IssueCustomField.create!(:name => 'List', :is_required => true, :field_format => 'list',
-      :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1, 2]
-
-    assert_select "li.cf_#{field.id}" do
-      assert_select 'a[href=#]', :text => 'List'
-      assert_select 'ul' do
-        assert_select 'a', 2
-        assert_select 'a', :text => 'none', :count => 0
-      end
-    end
-  end
-
-  def test_context_menu_on_single_issue_should_select_current_custom_field_value
-    field = IssueCustomField.create!(:name => 'List', :field_format => 'list',
-      :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
-    issue = Issue.find(1)
-    issue.custom_field_values = {field.id => 'Bar'}
-    issue.save!
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1]
-
-    assert_select "li.cf_#{field.id}" do
-      assert_select 'a[href=#]', :text => 'List'
-      assert_select 'ul' do
-        assert_select 'a', 3
-        assert_select 'a.icon-checked', :text => 'Bar'
-      end
-    end
-  end
-
-  def test_context_menu_should_include_bool_custom_fields
-    field = IssueCustomField.create!(:name => 'Bool', :field_format => 'bool',
-      :is_for_all => true, :tracker_ids => [1, 2, 3])
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1]
-
-    assert_select "li.cf_#{field.id}" do
-      assert_select 'a[href=#]', :text => 'Bool'
-      assert_select 'ul' do
-        assert_select 'a', 3
-        assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=0", :text => 'No'
-        assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=1", :text => 'Yes'
-        assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=__none__", :text => 'none'
-      end
-    end
-  end
-
-  def test_context_menu_should_include_user_custom_fields
-    field = IssueCustomField.create!(:name => 'User', :field_format => 'user',
-      :is_for_all => true, :tracker_ids => [1, 2, 3])
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1]
-
-    assert_select "li.cf_#{field.id}" do
-      assert_select 'a[href=#]', :text => 'User'
-      assert_select 'ul' do
-        assert_select 'a', Project.find(1).members.count + 1
-        assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=2", :text => 'John Smith'
-        assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=__none__", :text => 'none'
-      end
-    end
-  end
-
-  def test_context_menu_should_include_version_custom_fields
-    field = IssueCustomField.create!(:name => 'Version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1, 2, 3])
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1]
-
-    assert_select "li.cf_#{field.id}" do
-      assert_select 'a[href=#]', :text => 'Version'
-      assert_select 'ul' do
-        assert_select 'a', Project.find(1).shared_versions.count + 1
-        assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=3", :text => '2.0'
-        assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=__none__", :text => 'none'
-      end
-    end
-  end
-
-  def test_context_menu_by_assignable_user_should_include_assigned_to_me_link
-    @request.session[:user_id] = 2
-    get :issues, :ids => [1]
-    assert_response :success
-    assert_template 'context_menu'
-
-    assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bassigned_to_id%5D=2', :text => / me /
-  end
-
-  def test_context_menu_should_propose_shared_versions_for_issues_from_different_projects
-    @request.session[:user_id] = 2
-    version = Version.create!(:name => 'Shared', :sharing => 'system', :project_id => 1)
-
-    get :issues, :ids => [1, 4]
-    assert_response :success
-    assert_template 'context_menu'
-
-    assert_include version, assigns(:versions)
-    assert_select 'a', :text => 'eCookbook - Shared'
-  end
-
-  def test_context_menu_with_issue_that_is_not_visible_should_fail
-    get :issues, :ids => [1, 4] # issue 4 is not visible
-    assert_response 302
-  end
-
-  def test_should_respond_with_404_without_ids
-    get :issues
-    assert_response 404
-  end
-
-  def test_time_entries_context_menu
-    @request.session[:user_id] = 2
-    get :time_entries, :ids => [1, 2]
-    assert_response :success
-    assert_template 'time_entries'
-
-    assert_select 'a:not(.disabled)', :text => 'Edit'
-  end
-
-  def test_time_entries_context_menu_without_edit_permission
-    @request.session[:user_id] = 2
-    Role.find_by_name('Manager').remove_permission! :edit_time_entries
-    
-    get :time_entries, :ids => [1, 2]
-    assert_response :success
-    assert_template 'time_entries'
-    assert_select 'a.disabled', :text => 'Edit'
-  end
-end
--- a/.svn/pristine/ab/ab38ea7d768f054184e434cc851f97e51bbb639f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WikiTest < ActiveSupport::TestCase
-  fixtures :projects, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
-
-  def test_create
-    wiki = Wiki.new(:project => Project.find(2))
-    assert !wiki.save
-    assert_equal 1, wiki.errors.count
-
-    wiki.start_page = "Start page"
-    assert wiki.save
-  end
-
-  def test_update
-    @wiki = Wiki.find(1)
-    @wiki.start_page = "Another start page"
-    assert @wiki.save
-    @wiki.reload
-    assert_equal "Another start page", @wiki.start_page
-  end
-
-  def test_find_page_should_not_be_case_sensitive
-    wiki = Wiki.find(1)
-    page = WikiPage.find(2)
-
-    assert_equal page, wiki.find_page('Another_page')
-    assert_equal page, wiki.find_page('Another page')
-    assert_equal page, wiki.find_page('ANOTHER page')
-  end
-
-  def test_find_page_with_cyrillic_characters
-    wiki = Wiki.find(1)
-    page = WikiPage.find(10)
-    assert_equal page, wiki.find_page('Этика_менеджмента')
-  end
-
-  def test_find_page_with_backslashes
-    wiki = Wiki.find(1)
-    page = WikiPage.create!(:wiki => wiki, :title => '2009\\02\\09')
-    assert_equal page, wiki.find_page('2009\\02\\09')
-  end
-
-  def test_find_page_without_redirect
-    wiki = Wiki.find(1)
-    page = wiki.find_page('Another_page')
-    assert_not_nil page
-    assert_equal 'Another_page', page.title
-    assert_equal false, wiki.page_found_with_redirect?
-  end
-
-  def test_find_page_with_redirect
-    wiki = Wiki.find(1)
-    WikiRedirect.create!(:wiki => wiki, :title => 'Old_title', :redirects_to => 'Another_page')
-    page = wiki.find_page('Old_title')
-    assert_not_nil page
-    assert_equal 'Another_page', page.title
-    assert_equal true, wiki.page_found_with_redirect?
-  end
-
-  def test_titleize
-    ja_test = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
-    ja_test.force_encoding('UTF-8') if ja_test.respond_to?(:force_encoding)
-    assert_equal 'Page_title_with_CAPITALES', Wiki.titleize('page title with CAPITALES')
-    assert_equal ja_test, Wiki.titleize(ja_test)
-  end
-
-  def test_sidebar_should_return_nil_if_undefined
-    @wiki = Wiki.find(1)
-    assert_nil @wiki.sidebar
-  end
-
-  def test_sidebar_should_return_a_wiki_page_if_defined
-    @wiki = Wiki.find(1)
-    page = @wiki.pages.new(:title => 'Sidebar')
-    page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
-    page.save!
-
-    assert_kind_of WikiPage, @wiki.sidebar
-    assert_equal 'Sidebar', @wiki.sidebar.title
-  end
-end
--- a/.svn/pristine/ab/ab6ce3c805128861a981af4815e85be081e803b8.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingWorkflowsTest < ActionController::IntegrationTest
-  def test_workflows
-    assert_routing(
-        { :method => 'get', :path => "/workflows" },
-        { :controller => 'workflows', :action => 'index' }
-      )
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/workflows/edit" },
-          { :controller => 'workflows', :action => 'edit' }
-        )
-    end
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/workflows/permissions" },
-          { :controller => 'workflows', :action => 'permissions' }
-        )
-    end
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/workflows/copy" },
-          { :controller => 'workflows', :action => 'copy' }
-        )
-    end
-  end
-end
--- a/.svn/pristine/ab/ab970c495cc7d5cb06380124a67cbb15101f1bd6.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class EnumerationsController < ApplicationController
-  layout 'admin'
-
-  before_filter :require_admin, :except => :index
-  before_filter :require_admin_or_api_request, :only => :index
-  before_filter :build_new_enumeration, :only => [:new, :create]
-  before_filter :find_enumeration, :only => [:edit, :update, :destroy]
-  accept_api_auth :index
-
-  helper :custom_fields
-
-  def index
-    respond_to do |format|
-      format.html
-      format.api {
-        @klass = Enumeration.get_subclass(params[:type])
-        if @klass
-          @enumerations = @klass.shared.sorted.all
-        else
-          render_404
-        end
-      }
-    end
-  end
-
-  def new
-  end
-
-  def create
-    if request.post? && @enumeration.save
-      flash[:notice] = l(:notice_successful_create)
-      redirect_to enumerations_path
-    else
-      render :action => 'new'
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    if request.put? && @enumeration.update_attributes(params[:enumeration])
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to enumerations_path
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def destroy
-    if !@enumeration.in_use?
-      # No associated objects
-      @enumeration.destroy
-      redirect_to enumerations_path
-      return
-    elsif params[:reassign_to_id].present? && (reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id].to_i))
-      @enumeration.destroy(reassign_to)
-      redirect_to enumerations_path
-      return
-    end
-    @enumerations = @enumeration.class.system.all - [@enumeration]
-  end
-
-  private
-
-  def build_new_enumeration
-    class_name = params[:enumeration] && params[:enumeration][:type] || params[:type]
-    @enumeration = Enumeration.new_subclass_instance(class_name, params[:enumeration])
-    if @enumeration.nil?
-      render_404
-    end
-  end
-
-  def find_enumeration
-    @enumeration = Enumeration.find(params[:id])
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/ab/abd5fdb1f4d3a8db5bc870f482b9f0ab10c084c0.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class JournalsController < ApplicationController
-  before_filter :find_journal, :only => [:edit, :diff]
-  before_filter :find_issue, :only => [:new]
-  before_filter :find_optional_project, :only => [:index]
-  before_filter :authorize, :only => [:new, :edit, :diff]
-  accept_rss_auth :index
-  menu_item :issues
-
-  helper :issues
-  helper :custom_fields
-  helper :queries
-  include QueriesHelper
-  helper :sort
-  include SortHelper
-
-  def index
-    retrieve_query
-    sort_init 'id', 'desc'
-    sort_update(@query.sortable_columns)
-
-    if @query.valid?
-      @journals = @query.journals(:order => "#{Journal.table_name}.created_on DESC",
-                                  :limit => 25)
-    end
-    @title = (@project ? @project.name : Setting.app_title) + ": " + (@query.new_record? ? l(:label_changes_details) : @query.name)
-    render :layout => false, :content_type => 'application/atom+xml'
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def diff
-    @issue = @journal.issue
-    if params[:detail_id].present?
-      @detail = @journal.details.find_by_id(params[:detail_id])
-    else
-      @detail = @journal.details.detect {|d| d.prop_key == 'description'}
-    end
-    (render_404; return false) unless @issue && @detail
-    @diff = Redmine::Helpers::Diff.new(@detail.value, @detail.old_value)
-  end
-
-  def new
-    @journal = Journal.visible.find(params[:journal_id]) if params[:journal_id]
-    if @journal
-      user = @journal.user
-      text = @journal.notes
-    else
-      user = @issue.author
-      text = @issue.description
-    end
-    # Replaces pre blocks with [...]
-    text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
-    @content = "#{ll(Setting.default_language, :text_user_wrote, user)}\n> "
-    @content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def edit
-    (render_403; return false) unless @journal.editable_by?(User.current)
-    if request.post?
-      @journal.update_attributes(:notes => params[:notes]) if params[:notes]
-      @journal.destroy if @journal.details.empty? && @journal.notes.blank?
-      call_hook(:controller_journals_edit_post, { :journal => @journal, :params => params})
-      respond_to do |format|
-        format.html { redirect_to issue_path(@journal.journalized) }
-        format.js { render :action => 'update' }
-      end
-    else
-      respond_to do |format|
-        format.html {
-          # TODO: implement non-JS journal update
-          render :nothing => true
-        }
-        format.js
-      end
-    end
-  end
-
-  private
-
-  def find_journal
-    @journal = Journal.visible.find(params[:id])
-    @project = @journal.journalized.project
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/ab/abf5211d324f321533d626e49b37b34c4b19ff77.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class DiffTest < ActiveSupport::TestCase
-  def test_diff
-    diff = Redmine::Helpers::Diff.new("foo", "bar")
-    assert_not_nil diff
-  end
-end
--- a/.svn/pristine/ad/ad7d965438bf3955ae38f984cef50fc157bb3a13.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,322 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssuesCustomFieldsVisibilityTest < ActionController::TestCase
-  tests IssuesController
-  fixtures :projects,
-           :users,
-           :roles,
-           :members,
-           :member_roles,
-           :issue_statuses,
-           :trackers,
-           :projects_trackers,
-           :enabled_modules,
-           :enumerations,
-           :workflows
-
-  def setup
-    CustomField.delete_all
-    Issue.delete_all
-    field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :trackers => Tracker.all}
-    @fields = []
-    @fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true)))
-    @fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2])))
-    @fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3])))
-    @issue = Issue.generate!(
-      :author_id => 1,
-      :project_id => 1,
-      :tracker_id => 1,
-      :custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'}
-    )
-
-    @user_with_role_on_other_project = User.generate!
-    User.add_to_project(@user_with_role_on_other_project, Project.find(2), Role.find(3))
-
-    @users_to_test = {
-      User.find(1) => [@field1, @field2, @field3],
-      User.find(3) => [@field1, @field2],
-      @user_with_role_on_other_project => [@field1], # should see field1 only on Project 1
-      User.generate! => [@field1],
-      User.anonymous => [@field1]
-    }
-
-    Member.where(:project_id => 1).each do |member|
-      member.destroy unless @users_to_test.keys.include?(member.principal)
-    end
-  end
-
-  def test_show_should_show_visible_custom_fields_only
-    @users_to_test.each do |user, fields|
-      @request.session[:user_id] = user.id
-      get :show, :id => @issue.id
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_select 'td', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}"
-        else
-          assert_select 'td', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}"
-        end
-      end
-    end
-  end
-
-  def test_show_should_show_visible_custom_fields_only_in_api
-    @users_to_test.each do |user, fields|
-      with_settings :rest_api_enabled => '1' do
-        get :show, :id => @issue.id, :format => 'xml', :include => 'custom_fields', :key => user.api_key
-      end
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_select "custom_field[id=#{field.id}] value", {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} in API"
-        else
-          assert_select "custom_field[id=#{field.id}] value", {:text => "Value#{i}", :count => 0}, "User #{user.id} was not able to view #{field.name} in API"
-        end
-      end
-    end
-  end
-
-  def test_show_should_show_visible_custom_fields_only_in_history
-    @issue.init_journal(User.find(1))
-    @issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'}
-    @issue.save!
-
-    @users_to_test.each do |user, fields|
-      @request.session[:user_id] = user.id
-      get :show, :id => @issue.id
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_select 'ul.details i', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change"
-        else
-          assert_select 'ul.details i', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change"
-        end
-      end
-    end
-  end
-
-  def test_show_should_show_visible_custom_fields_only_in_history_api
-    @issue.init_journal(User.find(1))
-    @issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'}
-    @issue.save!
-
-    @users_to_test.each do |user, fields|
-      with_settings :rest_api_enabled => '1' do
-        get :show, :id => @issue.id, :format => 'xml', :include => 'journals', :key => user.api_key
-      end
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_select 'details old_value', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change in API"
-        else
-          assert_select 'details old_value', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change in API"
-        end
-      end
-    end
-  end
-
-  def test_edit_should_show_visible_custom_fields_only
-    Role.anonymous.add_permission! :edit_issues
-
-    @users_to_test.each do |user, fields|
-      @request.session[:user_id] = user.id
-      get :edit, :id => @issue.id
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_select 'input[value=?]', "Value#{i}", 1, "User #{user.id} was not able to edit #{field.name}"
-        else
-          assert_select 'input[value=?]', "Value#{i}", 0, "User #{user.id} was able to edit #{field.name}"
-        end
-      end
-    end
-  end
-
-  def test_update_should_update_visible_custom_fields_only
-    Role.anonymous.add_permission! :edit_issues
-
-    @users_to_test.each do |user, fields|
-      @request.session[:user_id] = user.id
-      put :update, :id => @issue.id,
-        :issue => {:custom_field_values => {
-          @field1.id.to_s => "User#{user.id}Value0",
-          @field2.id.to_s => "User#{user.id}Value1",
-          @field3.id.to_s => "User#{user.id}Value2",
-        }}
-      @issue.reload
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was not able to update #{field.name}"
-        else
-          assert_not_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was able to update #{field.name}"
-        end
-      end
-    end
-  end
-
-  def test_index_should_show_visible_custom_fields_only
-    @users_to_test.each do |user, fields|
-      @request.session[:user_id] = user.id
-      get :index, :c => (["subject"] + @fields.map{|f| "cf_#{f.id}"})
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_select 'td', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}"
-        else
-          assert_select 'td', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}"
-        end
-      end
-    end
-  end
-
-  def test_index_as_csv_should_show_visible_custom_fields_only
-    @users_to_test.each do |user, fields|
-      @request.session[:user_id] = user.id
-      get :index, :c => (["subject"] + @fields.map{|f| "cf_#{f.id}"}), :format => 'csv'
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_include "Value#{i}", response.body, "User #{user.id} was not able to view #{field.name} in CSV"
-        else
-          assert_not_include "Value#{i}", response.body, "User #{user.id} was able to view #{field.name} in CSV"
-        end
-      end
-    end
-  end
-
-  def test_index_with_partial_custom_field_visibility
-    Issue.delete_all
-    p1 = Project.generate!
-    p2 = Project.generate!
-    user = User.generate!
-    User.add_to_project(user, p1, Role.find_all_by_id(1,3))
-    User.add_to_project(user, p2, Role.find_all_by_id(3))
-    Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueA'})
-    Issue.generate!(:project => p2, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueB'})
-    Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueC'})
-
-    @request.session[:user_id] = user.id
-    get :index, :c => ["subject", "cf_#{@field2.id}"]
-    assert_select 'td', :text => 'ValueA'
-    assert_select 'td', :text => 'ValueB', :count => 0
-    assert_select 'td', :text => 'ValueC'
-
-    get :index, :sort => "cf_#{@field2.id}"
-    # ValueB is not visible to user and ignored while sorting
-    assert_equal %w(ValueB ValueA ValueC), assigns(:issues).map{|i| i.custom_field_value(@field2)}
-
-    get :index, :set_filter => '1', "cf_#{@field2.id}" => '*'
-    assert_equal %w(ValueA ValueC), assigns(:issues).map{|i| i.custom_field_value(@field2)}
-
-    CustomField.update_all(:field_format => 'list')
-    get :index, :group => "cf_#{@field2.id}"
-    assert_equal %w(ValueA ValueC), assigns(:issues).map{|i| i.custom_field_value(@field2)}
-  end
-
-  def test_create_should_send_notifications_according_custom_fields_visibility
-    # anonymous user is never notified
-    users_to_test = @users_to_test.reject {|k,v| k.anonymous?}
-
-    ActionMailer::Base.deliveries.clear
-    @request.session[:user_id] = 1
-    with_settings :bcc_recipients => '1' do
-      assert_difference 'Issue.count' do
-        post :create,
-          :project_id => 1,
-          :issue => {
-            :tracker_id => 1,
-            :status_id => 1,
-            :subject => 'New issue',
-            :priority_id => 5,
-            :custom_field_values => {@field1.id.to_s => 'Value0', @field2.id.to_s => 'Value1', @field3.id.to_s => 'Value2'},
-            :watcher_user_ids => users_to_test.keys.map(&:id)
-          }
-        assert_response 302
-      end
-    end
-    assert_equal users_to_test.values.uniq.size, ActionMailer::Base.deliveries.size
-    # tests that each user receives 1 email with the custom fields he is allowed to see only
-    users_to_test.each do |user, fields|
-      mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail}
-      assert_equal 1, mails.size
-      mail = mails.first
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification"
-        else
-          assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification"
-        end
-      end
-    end
-  end
-
-  def test_update_should_send_notifications_according_custom_fields_visibility
-    # anonymous user is never notified
-    users_to_test = @users_to_test.reject {|k,v| k.anonymous?}
-
-    users_to_test.keys.each do |user|
-      Watcher.create!(:user => user, :watchable => @issue)
-    end
-    ActionMailer::Base.deliveries.clear
-    @request.session[:user_id] = 1
-    with_settings :bcc_recipients => '1' do
-      put :update,
-        :id => @issue.id,
-        :issue => {
-          :custom_field_values => {@field1.id.to_s => 'NewValue0', @field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'}
-        }
-      assert_response 302
-    end
-    assert_equal users_to_test.values.uniq.size, ActionMailer::Base.deliveries.size
-    # tests that each user receives 1 email with the custom fields he is allowed to see only
-    users_to_test.each do |user, fields|
-      mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail}
-      assert_equal 1, mails.size
-      mail = mails.first
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification"
-        else
-          assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification"
-        end
-      end
-    end
-  end
-
-  def test_updating_hidden_custom_fields_only_should_not_notifiy_user
-    # anonymous user is never notified
-    users_to_test = @users_to_test.reject {|k,v| k.anonymous?}
-
-    users_to_test.keys.each do |user|
-      Watcher.create!(:user => user, :watchable => @issue)
-    end
-    ActionMailer::Base.deliveries.clear
-    @request.session[:user_id] = 1
-    with_settings :bcc_recipients => '1' do
-      put :update,
-        :id => @issue.id,
-        :issue => {
-          :custom_field_values => {@field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'}
-        }
-      assert_response 302
-    end
-    users_to_test.each do |user, fields|
-      mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail}
-      if (fields & [@field2, @field3]).any?
-        assert_equal 1, mails.size, "User #{user.id} was not notified"
-      else
-        assert_equal 0, mails.size, "User #{user.id} was notified"
-      end
-    end
-  end
-end
--- a/.svn/pristine/ad/adfb2deb75a122f46087f28c026a73e83ce67dc5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# FileSystem adapter
-# File written by Paul Rivier, at Demotera.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/filesystem_adapter'
-
-class Repository::Filesystem < Repository
-  attr_protected :root_url
-  validates_presence_of :url
-
-  def self.human_attribute_name(attribute_key_name, *args)
-    attr_name = attribute_key_name.to_s
-    if attr_name == "url"
-      attr_name = "root_directory"
-    end
-    super(attr_name, *args)
-  end
-
-  def self.scm_adapter_class
-    Redmine::Scm::Adapters::FilesystemAdapter
-  end
-
-  def self.scm_name
-    'Filesystem'
-  end
-
-  def supports_all_revisions?
-    false
-  end
-
-  def fetch_changesets
-    nil
-  end
-end
--- a/.svn/pristine/ae/ae59ba764b863f990d0884c0c55bada9eb65b729.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class UsersController < ApplicationController
-  layout 'admin'
-
-  before_filter :require_admin, :except => :show
-  before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership]
-  accept_api_auth :index, :show, :create, :update, :destroy
-
-  helper :sort
-  include SortHelper
-  helper :custom_fields
-  include CustomFieldsHelper
-
-  def index
-    sort_init 'login', 'asc'
-    sort_update %w(login firstname lastname mail admin created_on last_login_on)
-
-    case params[:format]
-    when 'xml', 'json'
-      @offset, @limit = api_offset_and_limit
-    else
-      @limit = per_page_option
-    end
-
-    @status = params[:status] || 1
-
-    scope = User.logged.status(@status)
-    scope = scope.like(params[:name]) if params[:name].present?
-    scope = scope.in_group(params[:group_id]) if params[:group_id].present?
-
-    @user_count = scope.count
-    @user_pages = Paginator.new @user_count, @limit, params['page']
-    @offset ||= @user_pages.offset
-    @users =  scope.order(sort_clause).limit(@limit).offset(@offset).all
-
-    respond_to do |format|
-      format.html {
-        @groups = Group.all.sort
-        render :layout => !request.xhr?
-      }
-      format.api
-    end
-  end
-
-  def show
-    # show projects based on current user visibility
-    @memberships = @user.memberships.where(Project.visible_condition(User.current)).all
-
-    events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
-    @events_by_day = events.group_by(&:event_date)
-
-    unless User.current.admin?
-      if !@user.active? || (@user != User.current  && @memberships.empty? && events.empty?)
-        render_404
-        return
-      end
-    end
-
-    respond_to do |format|
-      format.html { render :layout => 'base' }
-      format.api
-    end
-  end
-
-  def new
-    @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
-    @user.safe_attributes = params[:user]
-    @auth_sources = AuthSource.all
-  end
-
-  def create
-    @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
-    @user.safe_attributes = params[:user]
-    @user.admin = params[:user][:admin] || false
-    @user.login = params[:user][:login]
-    @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id
-
-    if @user.save
-      @user.pref.attributes = params[:pref]
-      @user.pref.save
-
-      Mailer.account_information(@user, @user.password).deliver if params[:send_information]
-
-      respond_to do |format|
-        format.html {
-          flash[:notice] = l(:notice_user_successful_create, :id => view_context.link_to(@user.login, user_path(@user)))
-          if params[:continue]
-            attrs = params[:user].slice(:generate_password)
-            redirect_to new_user_path(:user => attrs)
-          else
-            redirect_to edit_user_path(@user)
-          end
-        }
-        format.api  { render :action => 'show', :status => :created, :location => user_url(@user) }
-      end
-    else
-      @auth_sources = AuthSource.all
-      # Clear password input
-      @user.password = @user.password_confirmation = nil
-
-      respond_to do |format|
-        format.html { render :action => 'new' }
-        format.api  { render_validation_errors(@user) }
-      end
-    end
-  end
-
-  def edit
-    @auth_sources = AuthSource.all
-    @membership ||= Member.new
-  end
-
-  def update
-    @user.admin = params[:user][:admin] if params[:user][:admin]
-    @user.login = params[:user][:login] if params[:user][:login]
-    if params[:user][:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?)
-      @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation]
-    end
-    @user.safe_attributes = params[:user]
-    # Was the account actived ? (do it before User#save clears the change)
-    was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE])
-    # TODO: Similar to My#account
-    @user.pref.attributes = params[:pref]
-
-    if @user.save
-      @user.pref.save
-
-      if was_activated
-        Mailer.account_activated(@user).deliver
-      elsif @user.active? && params[:send_information] && @user.password.present? && @user.auth_source_id.nil?
-        Mailer.account_information(@user, @user.password).deliver
-      end
-
-      respond_to do |format|
-        format.html {
-          flash[:notice] = l(:notice_successful_update)
-          redirect_to_referer_or edit_user_path(@user)
-        }
-        format.api  { render_api_ok }
-      end
-    else
-      @auth_sources = AuthSource.all
-      @membership ||= Member.new
-      # Clear password input
-      @user.password = @user.password_confirmation = nil
-
-      respond_to do |format|
-        format.html { render :action => :edit }
-        format.api  { render_validation_errors(@user) }
-      end
-    end
-  end
-
-  def destroy
-    @user.destroy
-    respond_to do |format|
-      format.html { redirect_back_or_default(users_path) }
-      format.api  { render_api_ok }
-    end
-  end
-
-  def edit_membership
-    @membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
-    @membership.save
-    respond_to do |format|
-      format.html { redirect_to edit_user_path(@user, :tab => 'memberships') }
-      format.js
-    end
-  end
-
-  def destroy_membership
-    @membership = Member.find(params[:membership_id])
-    if @membership.deletable?
-      @membership.destroy
-    end
-    respond_to do |format|
-      format.html { redirect_to edit_user_path(@user, :tab => 'memberships') }
-      format.js
-    end
-  end
-
-  private
-
-  def find_user
-    if params[:id] == 'current'
-      require_login || return
-      @user = User.current
-    else
-      @user = User.find(params[:id])
-    end
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/ae/aefa10621da29d1174e5f170d627124a0e405f4e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :enabled_modules, :wikis, :wiki_pages, :wiki_contents,
-           :wiki_content_versions, :attachments
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /projects/:project_id/wiki/index.xml should return wiki pages" do
-    get '/projects/ecookbook/wiki/index.xml'
-    assert_response 200
-    assert_equal 'application/xml', response.content_type
-    assert_select 'wiki_pages[type=array]' do
-      assert_select 'wiki_page', :count => Wiki.find(1).pages.count
-      assert_select 'wiki_page' do
-        assert_select 'title', :text => 'CookBook_documentation'
-        assert_select 'version', :text => '3'
-        assert_select 'created_on'
-        assert_select 'updated_on'
-      end
-      assert_select 'wiki_page' do
-        assert_select 'title', :text => 'Page_with_an_inline_image'
-        assert_select 'parent[title=?]', 'CookBook_documentation'
-      end
-    end
-  end
-
-  test "GET /projects/:project_id/wiki/:title.xml should return wiki page" do
-    get '/projects/ecookbook/wiki/CookBook_documentation.xml'
-    assert_response 200
-    assert_equal 'application/xml', response.content_type
-    assert_select 'wiki_page' do
-      assert_select 'title', :text => 'CookBook_documentation'
-      assert_select 'version', :text => '3'
-      assert_select 'text'
-      assert_select 'author'
-      assert_select 'comments'
-      assert_select 'created_on'
-      assert_select 'updated_on'
-    end
-  end
-
-  test "GET /projects/:project_id/wiki/:title.xml?include=attachments should include attachments" do
-    get '/projects/ecookbook/wiki/Page_with_an_inline_image.xml?include=attachments'
-    assert_response 200
-    assert_equal 'application/xml', response.content_type
-    assert_select 'wiki_page' do
-      assert_select 'title', :text => 'Page_with_an_inline_image'
-      assert_select 'attachments[type=array]' do
-        assert_select 'attachment' do
-          assert_select 'id', :text => '3'
-          assert_select 'filename', :text => 'logo.gif'
-        end
-      end
-    end
-  end
-
-  test "GET /projects/:project_id/wiki/:title.xml with unknown title and edit permission should respond with 404" do
-    get '/projects/ecookbook/wiki/Invalid_Page.xml', {}, credentials('jsmith')
-    assert_response 404
-    assert_equal 'application/xml', response.content_type
-  end
-
-  test "GET /projects/:project_id/wiki/:title/:version.xml should return wiki page version" do
-    get '/projects/ecookbook/wiki/CookBook_documentation/2.xml'
-    assert_response 200
-    assert_equal 'application/xml', response.content_type
-    assert_select 'wiki_page' do
-      assert_select 'title', :text => 'CookBook_documentation'
-      assert_select 'version', :text => '2'
-      assert_select 'text'
-      assert_select 'author'
-      assert_select 'comments', :text => 'Small update'
-      assert_select 'created_on'
-      assert_select 'updated_on'
-    end
-  end
-
-  test "GET /projects/:project_id/wiki/:title/:version.xml without permission should be denied" do
-    Role.anonymous.remove_permission! :view_wiki_edits
-
-    get '/projects/ecookbook/wiki/CookBook_documentation/2.xml'
-    assert_response 401
-    assert_equal 'application/xml', response.content_type
-  end
-
-  test "PUT /projects/:project_id/wiki/:title.xml should update wiki page" do
-    assert_no_difference 'WikiPage.count' do
-      assert_difference 'WikiContent::Version.count' do
-        put '/projects/ecookbook/wiki/CookBook_documentation.xml',
-          {:wiki_page => {:text => 'New content from API', :comments => 'API update'}},
-          credentials('jsmith')
-        assert_response 200
-      end
-    end
-
-    page = WikiPage.find(1)
-    assert_equal 'New content from API', page.content.text
-    assert_equal 4, page.content.version
-    assert_equal 'API update', page.content.comments
-    assert_equal 'jsmith', page.content.author.login
-  end
-
-  test "PUT /projects/:project_id/wiki/:title.xml with current versino should update wiki page" do
-    assert_no_difference 'WikiPage.count' do
-      assert_difference 'WikiContent::Version.count' do
-        put '/projects/ecookbook/wiki/CookBook_documentation.xml',
-          {:wiki_page => {:text => 'New content from API', :comments => 'API update', :version => '3'}},
-          credentials('jsmith')
-        assert_response 200
-      end
-    end
-
-    page = WikiPage.find(1)
-    assert_equal 'New content from API', page.content.text
-    assert_equal 4, page.content.version
-    assert_equal 'API update', page.content.comments
-    assert_equal 'jsmith', page.content.author.login
-  end
-
-  test "PUT /projects/:project_id/wiki/:title.xml with stale version should respond with 409" do
-    assert_no_difference 'WikiPage.count' do
-      assert_no_difference 'WikiContent::Version.count' do
-        put '/projects/ecookbook/wiki/CookBook_documentation.xml',
-          {:wiki_page => {:text => 'New content from API', :comments => 'API update', :version => '2'}},
-          credentials('jsmith')
-        assert_response 409
-      end
-    end
-  end
-
-  test "PUT /projects/:project_id/wiki/:title.xml should create the page if it does not exist" do
-    assert_difference 'WikiPage.count' do
-      assert_difference 'WikiContent::Version.count' do
-        put '/projects/ecookbook/wiki/New_page_from_API.xml',
-          {:wiki_page => {:text => 'New content from API', :comments => 'API create'}},
-          credentials('jsmith')
-        assert_response 201
-      end
-    end
-
-    page = WikiPage.order('id DESC').first
-    assert_equal 'New_page_from_API', page.title
-    assert_equal 'New content from API', page.content.text
-    assert_equal 1, page.content.version
-    assert_equal 'API create', page.content.comments
-    assert_equal 'jsmith', page.content.author.login
-    assert_nil page.parent
-  end
-
-  test "PUT /projects/:project_id/wiki/:title.xml with parent" do
-    assert_difference 'WikiPage.count' do
-      assert_difference 'WikiContent::Version.count' do
-        put '/projects/ecookbook/wiki/New_subpage_from_API.xml',
-          {:wiki_page => {:parent_title => 'CookBook_documentation', :text => 'New content from API', :comments => 'API create'}},
-          credentials('jsmith')
-        assert_response 201
-      end
-    end
-
-    page = WikiPage.order('id DESC').first
-    assert_equal 'New_subpage_from_API', page.title
-    assert_equal WikiPage.find(1), page.parent
-  end
-
-  test "DELETE /projects/:project_id/wiki/:title.xml should destroy the page" do
-    assert_difference 'WikiPage.count', -1 do
-      delete '/projects/ecookbook/wiki/CookBook_documentation.xml', {}, credentials('jsmith')
-      assert_response 200
-    end
-
-    assert_nil WikiPage.find_by_id(1)
-  end
-end
--- a/.svn/pristine/af/af02303e44f5e8e86d7123690a664101ce5a8f66.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Message < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  belongs_to :board
-  belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
-  acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
-  acts_as_attachable
-  belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
-
-  acts_as_searchable :columns => ['subject', 'content'],
-                     :include => {:board => :project},
-                     :project_key => "#{Board.table_name}.project_id",
-                     :date_column => "#{table_name}.created_on"
-  acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
-                :description => :content,
-                :group => :parent,
-                :type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'},
-                :url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} :
-                                                                                                                                       {:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
-
-  acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
-                            :author_key => :author_id
-  acts_as_watchable
-
-  validates_presence_of :board, :subject, :content
-  validates_length_of :subject, :maximum => 255
-  validate :cannot_reply_to_locked_topic, :on => :create
-
-  after_create :add_author_as_watcher, :reset_counters!
-  after_update :update_messages_board
-  after_destroy :reset_counters!
-  after_create :send_notification
-
-  scope :visible, lambda {|*args|
-    includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
-  }
-
-  safe_attributes 'subject', 'content'
-  safe_attributes 'locked', 'sticky', 'board_id',
-    :if => lambda {|message, user|
-      user.allowed_to?(:edit_messages, message.project)
-    }
-
-  def visible?(user=User.current)
-    !user.nil? && user.allowed_to?(:view_messages, project)
-  end
-
-  def cannot_reply_to_locked_topic
-    # Can not reply to a locked topic
-    errors.add :base, 'Topic is locked' if root.locked? && self != root
-  end
-
-  def update_messages_board
-    if board_id_changed?
-      Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id])
-      Board.reset_counters!(board_id_was)
-      Board.reset_counters!(board_id)
-    end
-  end
-
-  def reset_counters!
-    if parent && parent.id
-      Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
-    end
-    board.reset_counters!
-  end
-
-  def sticky=(arg)
-    write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
-  end
-
-  def sticky?
-    sticky == 1
-  end
-
-  def project
-    board.project
-  end
-
-  def editable_by?(usr)
-    usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)))
-  end
-
-  def destroyable_by?(usr)
-    usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
-  end
-
-  private
-
-  def add_author_as_watcher
-    Watcher.create(:watchable => self.root, :user => author)
-  end
-
-  def send_notification
-    if Setting.notified_events.include?('message_posted')
-      Mailer.message_posted(self).deliver
-    end
-  end
-end
--- a/.svn/pristine/af/afff6ebb421c46aa468f585b7d8909132a409f4d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,248 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class MyControllerTest < ActionController::TestCase
-  fixtures :users, :user_preferences, :roles, :projects, :members, :member_roles,
-  :issues, :issue_statuses, :trackers, :enumerations, :custom_fields, :auth_sources
-
-  def setup
-    @request.session[:user_id] = 2
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'page'
-  end
-
-  def test_page
-    get :page
-    assert_response :success
-    assert_template 'page'
-  end
-
-  def test_page_with_timelog_block
-    preferences = User.find(2).pref
-    preferences[:my_page_layout] = {'top' => ['timelog']}
-    preferences.save!
-    TimeEntry.create!(:user => User.find(2), :spent_on => Date.yesterday, :issue_id => 1, :hours => 2.5, :activity_id => 10)
-
-    get :page
-    assert_response :success
-    assert_select 'tr.time-entry' do
-      assert_select 'td.subject a[href=/issues/1]'
-      assert_select 'td.hours', :text => '2.50'
-    end
-  end
-
-  def test_page_with_all_blocks
-    blocks = MyController::BLOCKS.keys
-    preferences = User.find(2).pref
-    preferences[:my_page_layout] = {'top' => blocks}
-    preferences.save!
-
-    get :page
-    assert_response :success
-    assert_select 'div.mypage-box', blocks.size
-  end
-
-  def test_my_account_should_show_editable_custom_fields
-    get :account
-    assert_response :success
-    assert_template 'account'
-    assert_equal User.find(2), assigns(:user)
-
-    assert_tag :input, :attributes => { :name => 'user[custom_field_values][4]'}
-  end
-
-  def test_my_account_should_not_show_non_editable_custom_fields
-    UserCustomField.find(4).update_attribute :editable, false
-
-    get :account
-    assert_response :success
-    assert_template 'account'
-    assert_equal User.find(2), assigns(:user)
-
-    assert_no_tag :input, :attributes => { :name => 'user[custom_field_values][4]'}
-  end
-
-  def test_update_account
-    post :account,
-      :user => {
-        :firstname => "Joe",
-        :login => "root",
-        :admin => 1,
-        :group_ids => ['10'],
-        :custom_field_values => {"4" => "0100562500"}
-      }
-
-    assert_redirected_to '/my/account'
-    user = User.find(2)
-    assert_equal user, assigns(:user)
-    assert_equal "Joe", user.firstname
-    assert_equal "jsmith", user.login
-    assert_equal "0100562500", user.custom_value_for(4).value
-    # ignored
-    assert !user.admin?
-    assert user.groups.empty?
-  end
-
-  def test_my_account_should_show_destroy_link
-    get :account
-    assert_select 'a[href=/my/account/destroy]'
-  end
-
-  def test_get_destroy_should_display_the_destroy_confirmation
-    get :destroy
-    assert_response :success
-    assert_template 'destroy'
-    assert_select 'form[action=/my/account/destroy]' do
-      assert_select 'input[name=confirm]'
-    end
-  end
-
-  def test_post_destroy_without_confirmation_should_not_destroy_account
-    assert_no_difference 'User.count' do
-      post :destroy
-    end
-    assert_response :success
-    assert_template 'destroy'
-  end
-
-  def test_post_destroy_without_confirmation_should_destroy_account
-    assert_difference 'User.count', -1 do
-      post :destroy, :confirm => '1'
-    end
-    assert_redirected_to '/'
-    assert_match /deleted/i, flash[:notice]
-  end
-
-  def test_post_destroy_with_unsubscribe_not_allowed_should_not_destroy_account
-    User.any_instance.stubs(:own_account_deletable?).returns(false)
-
-    assert_no_difference 'User.count' do
-      post :destroy, :confirm => '1'
-    end
-    assert_redirected_to '/my/account'
-  end
-
-  def test_change_password
-    get :password
-    assert_response :success
-    assert_template 'password'
-
-    # non matching password confirmation
-    post :password, :password => 'jsmith',
-                    :new_password => 'secret123',
-                    :new_password_confirmation => 'secret1234'
-    assert_response :success
-    assert_template 'password'
-    assert_error_tag :content => /Password doesn&#x27;t match confirmation/
-
-    # wrong password
-    post :password, :password => 'wrongpassword',
-                    :new_password => 'secret123',
-                    :new_password_confirmation => 'secret123'
-    assert_response :success
-    assert_template 'password'
-    assert_equal 'Wrong password', flash[:error]
-
-    # good password
-    post :password, :password => 'jsmith',
-                    :new_password => 'secret123',
-                    :new_password_confirmation => 'secret123'
-    assert_redirected_to '/my/account'
-    assert User.try_to_login('jsmith', 'secret123')
-  end
-
-  def test_change_password_should_redirect_if_user_cannot_change_its_password
-    User.find(2).update_attribute(:auth_source_id, 1)
-
-    get :password
-    assert_not_nil flash[:error]
-    assert_redirected_to '/my/account'
-  end
-
-  def test_page_layout
-    get :page_layout
-    assert_response :success
-    assert_template 'page_layout'
-  end
-
-  def test_add_block
-    post :add_block, :block => 'issuesreportedbyme'
-    assert_redirected_to '/my/page_layout'
-    assert User.find(2).pref[:my_page_layout]['top'].include?('issuesreportedbyme')
-  end
-
-  def test_add_invalid_block_should_redirect
-    post :add_block, :block => 'invalid'
-    assert_redirected_to '/my/page_layout'
-  end
-
-  def test_remove_block
-    post :remove_block, :block => 'issuesassignedtome'
-    assert_redirected_to '/my/page_layout'
-    assert !User.find(2).pref[:my_page_layout].values.flatten.include?('issuesassignedtome')
-  end
-
-  def test_order_blocks
-    xhr :post, :order_blocks, :group => 'left', 'blocks' => ['documents', 'calendar', 'latestnews']
-    assert_response :success
-    assert_equal ['documents', 'calendar', 'latestnews'], User.find(2).pref[:my_page_layout]['left']
-  end
-
-  def test_reset_rss_key_with_existing_key
-    @previous_token_value = User.find(2).rss_key # Will generate one if it's missing
-    post :reset_rss_key
-
-    assert_not_equal @previous_token_value, User.find(2).rss_key
-    assert User.find(2).rss_token
-    assert_match /reset/, flash[:notice]
-    assert_redirected_to '/my/account'
-  end
-
-  def test_reset_rss_key_without_existing_key
-    assert_nil User.find(2).rss_token
-    post :reset_rss_key
-
-    assert User.find(2).rss_token
-    assert_match /reset/, flash[:notice]
-    assert_redirected_to '/my/account'
-  end
-
-  def test_reset_api_key_with_existing_key
-    @previous_token_value = User.find(2).api_key # Will generate one if it's missing
-    post :reset_api_key
-
-    assert_not_equal @previous_token_value, User.find(2).api_key
-    assert User.find(2).api_token
-    assert_match /reset/, flash[:notice]
-    assert_redirected_to '/my/account'
-  end
-
-  def test_reset_api_key_without_existing_key
-    assert_nil User.find(2).api_token
-    post :reset_api_key
-
-    assert User.find(2).api_token
-    assert_match /reset/, flash[:notice]
-    assert_redirected_to '/my/account'
-  end
-end
--- a/.svn/pristine/b1/b11a4104da3bd4ac01a0f204b3deb8706ff5132c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WikisControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :wikis
-
-  def setup
-    User.current = nil
-  end
-
-  def test_create
-    @request.session[:user_id] = 1
-    assert_nil Project.find(3).wiki
-
-    assert_difference 'Wiki.count' do
-      xhr :post, :edit, :id => 3, :wiki => { :start_page => 'Start page' }
-      assert_response :success
-      assert_template 'edit'
-      assert_equal 'text/javascript', response.content_type
-    end
-
-    wiki = Project.find(3).wiki
-    assert_not_nil wiki
-    assert_equal 'Start page', wiki.start_page
-  end
-
-  def test_create_with_failure
-    @request.session[:user_id] = 1
-
-    assert_no_difference 'Wiki.count' do
-      xhr :post, :edit, :id => 3, :wiki => { :start_page => '' }
-      assert_response :success
-      assert_template 'edit'
-      assert_equal 'text/javascript', response.content_type
-    end
-
-    assert_include 'errorExplanation', response.body
-    assert_include 'Start page can&#x27;t be blank', response.body
-  end
-
-  def test_update
-    @request.session[:user_id] = 1
-
-    assert_no_difference 'Wiki.count' do
-      xhr :post, :edit, :id => 1, :wiki => { :start_page => 'Other start page' }
-      assert_response :success
-      assert_template 'edit'
-      assert_equal 'text/javascript', response.content_type
-    end
-
-    wiki = Project.find(1).wiki
-    assert_equal 'Other start page', wiki.start_page
-  end
-
-  def test_destroy
-    @request.session[:user_id] = 1
-    post :destroy, :id => 1, :confirm => 1
-    assert_redirected_to :controller => 'projects', :action => 'settings', :id => 'ecookbook', :tab => 'wiki'
-    assert_nil Project.find(1).wiki
-  end
-
-  def test_not_found
-    @request.session[:user_id] = 1
-    post :destroy, :id => 999, :confirm => 1
-    assert_response 404
-  end
-end
--- a/.svn/pristine/b3/b3d91192dd0d431ce304ba9c869d32014ebbfc38.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueStatusTest < ActiveSupport::TestCase
-  fixtures :issue_statuses, :issues, :roles, :trackers
-
-  def test_create
-    status = IssueStatus.new :name => "Assigned"
-    assert !status.save
-    # status name uniqueness
-    assert_equal 1, status.errors.count
-
-    status.name = "Test Status"
-    assert status.save
-    assert !status.is_default
-  end
-
-  def test_destroy
-    status = IssueStatus.find(3)
-    assert_difference 'IssueStatus.count', -1 do
-      assert status.destroy
-    end
-    assert_nil WorkflowTransition.where(:old_status_id => status.id).first
-    assert_nil WorkflowTransition.where(:new_status_id => status.id).first
-  end
-
-  def test_destroy_status_in_use
-    # Status assigned to an Issue
-    status = Issue.find(1).status
-    assert_raise(RuntimeError, "Can't delete status") { status.destroy }
-  end
-
-  def test_default
-    status = IssueStatus.default
-    assert_kind_of IssueStatus, status
-  end
-
-  def test_change_default
-    status = IssueStatus.find(2)
-    assert !status.is_default
-    status.is_default = true
-    assert status.save
-    status.reload
-
-    assert_equal status, IssueStatus.default
-    assert !IssueStatus.find(1).is_default
-  end
-
-  def test_reorder_should_not_clear_default_status
-    status = IssueStatus.default
-    status.move_to_bottom
-    status.reload
-    assert status.is_default?
-  end
-
-  def test_new_statuses_allowed_to
-    WorkflowTransition.delete_all
-
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
-    status = IssueStatus.find(1)
-    role = Role.find(1)
-    tracker = Tracker.find(1)
-
-    assert_equal [2], status.new_statuses_allowed_to([role], tracker, false, false).map(&:id)
-    assert_equal [2], status.find_new_statuses_allowed_to([role], tracker, false, false).map(&:id)
-
-    assert_equal [2, 3, 5], status.new_statuses_allowed_to([role], tracker, true, false).map(&:id)
-    assert_equal [2, 3, 5], status.find_new_statuses_allowed_to([role], tracker, true, false).map(&:id)
-
-    assert_equal [2, 4, 5], status.new_statuses_allowed_to([role], tracker, false, true).map(&:id)
-    assert_equal [2, 4, 5], status.find_new_statuses_allowed_to([role], tracker, false, true).map(&:id)
-
-    assert_equal [2, 3, 4, 5], status.new_statuses_allowed_to([role], tracker, true, true).map(&:id)
-    assert_equal [2, 3, 4, 5], status.find_new_statuses_allowed_to([role], tracker, true, true).map(&:id)
-  end
-
-  def test_update_done_ratios_with_issue_done_ratio_set_to_issue_field_should_change_nothing
-    IssueStatus.find(1).update_attribute(:default_done_ratio, 50)
-
-    with_settings :issue_done_ratio => 'issue_field' do
-      IssueStatus.update_issue_done_ratios
-      assert_equal 0, Issue.where(:done_ratio => 50).count
-    end
-  end
-
-  def test_update_done_ratios_with_issue_done_ratio_set_to_issue_status_should_update_issues
-    IssueStatus.find(1).update_attribute(:default_done_ratio, 50)
-
-    with_settings :issue_done_ratio => 'issue_status' do
-      IssueStatus.update_issue_done_ratios
-      issues = Issue.where(:status_id => 1).all
-      assert_equal [50], issues.map {|issue| issue.read_attribute(:done_ratio)}.uniq
-    end
-  end
-
-  def test_sorted_scope
-    assert_equal IssueStatus.all.sort, IssueStatus.sorted.all
-  end
-
-  def test_named_scope
-    status = IssueStatus.named("resolved").first
-    assert_not_nil status
-    assert_equal "Resolved", status.name
-  end
-end
--- a/.svn/pristine/b4/b4795ced5acceb3bc06993b762ac31de2976a1c3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class WatchersHelperTest < ActionView::TestCase
-  include WatchersHelper
-  include Redmine::I18n
-
-  fixtures :users, :issues
-
-  def setup
-    super
-    set_language_if_valid('en')
-    User.current = nil
-  end
-
-  test '#watcher_link with a non-watched object' do
-    expected = link_to(
-      "Watch",
-      "/watchers/watch?object_id=1&object_type=issue",
-      :remote => true, :method => 'post', :class => "issue-1-watcher icon icon-fav-off"
-    )
-    assert_equal expected, watcher_link(Issue.find(1), User.find(1))
-  end
-
-  test '#watcher_link with a single objet array' do
-    expected = link_to(
-      "Watch",
-      "/watchers/watch?object_id=1&object_type=issue",
-      :remote => true, :method => 'post', :class => "issue-1-watcher icon icon-fav-off"
-    )
-    assert_equal expected, watcher_link([Issue.find(1)], User.find(1))
-  end
-
-  test '#watcher_link with a multiple objets array' do
-    expected = link_to(
-      "Watch",
-      "/watchers/watch?object_id%5B%5D=1&object_id%5B%5D=3&object_type=issue",
-      :remote => true, :method => 'post', :class => "issue-bulk-watcher icon icon-fav-off"
-    )
-    assert_equal expected, watcher_link([Issue.find(1), Issue.find(3)], User.find(1))
-  end
-
-  test '#watcher_link with a watched object' do
-    Watcher.create!(:watchable => Issue.find(1), :user => User.find(1))
-
-    expected = link_to(
-      "Unwatch",
-      "/watchers/watch?object_id=1&object_type=issue",
-      :remote => true, :method => 'delete', :class => "issue-1-watcher icon icon-fav"
-    )
-    assert_equal expected, watcher_link(Issue.find(1), User.find(1))
-  end
-end
--- a/.svn/pristine/b4/b4b121a602e6db678b41699ec2d4ceada140049b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class GroupsController < ApplicationController
-  layout 'admin'
-
-  before_filter :require_admin
-  before_filter :find_group, :except => [:index, :new, :create]
-  accept_api_auth :index, :show, :create, :update, :destroy, :add_users, :remove_user
-
-  helper :custom_fields
-
-  def index
-    @groups = Group.sorted.all
-
-    respond_to do |format|
-      format.html
-      format.api
-    end
-  end
-
-  def show
-    respond_to do |format|
-      format.html
-      format.api
-    end
-  end
-
-  def new
-    @group = Group.new
-  end
-
-  def create
-    @group = Group.new
-    @group.safe_attributes = params[:group]
-
-    respond_to do |format|
-      if @group.save
-        format.html {
-          flash[:notice] = l(:notice_successful_create)
-          redirect_to(params[:continue] ? new_group_path : groups_path)
-        }
-        format.api  { render :action => 'show', :status => :created, :location => group_url(@group) }
-      else
-        format.html { render :action => "new" }
-        format.api  { render_validation_errors(@group) }
-      end
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    @group.safe_attributes = params[:group]
-
-    respond_to do |format|
-      if @group.save
-        flash[:notice] = l(:notice_successful_update)
-        format.html { redirect_to(groups_path) }
-        format.api  { render_api_ok }
-      else
-        format.html { render :action => "edit" }
-        format.api  { render_validation_errors(@group) }
-      end
-    end
-  end
-
-  def destroy
-    @group.destroy
-
-    respond_to do |format|
-      format.html { redirect_to(groups_path) }
-      format.api  { render_api_ok }
-    end
-  end
-
-  def add_users
-    @users = User.find_all_by_id(params[:user_id] || params[:user_ids])
-    @group.users << @users if request.post?
-    respond_to do |format|
-      format.html { redirect_to edit_group_path(@group, :tab => 'users') }
-      format.js
-      format.api { render_api_ok }
-    end
-  end
-
-  def remove_user
-    @group.users.delete(User.find(params[:user_id])) if request.delete?
-    respond_to do |format|
-      format.html { redirect_to edit_group_path(@group, :tab => 'users') }
-      format.js
-      format.api { render_api_ok }
-    end
-  end
-
-  def autocomplete_for_user
-    respond_to do |format|
-      format.js
-    end
-  end
-
-  def edit_membership
-    @membership = Member.edit_membership(params[:membership_id], params[:membership], @group)
-    @membership.save if request.post?
-    respond_to do |format|
-      format.html { redirect_to edit_group_path(@group, :tab => 'memberships') }
-      format.js
-    end
-  end
-
-  def destroy_membership
-    Member.find(params[:membership_id]).destroy if request.post?
-    respond_to do |format|
-      format.html { redirect_to edit_group_path(@group, :tab => 'memberships') }
-      format.js
-    end
-  end
-
-  private
-
-  def find_group
-    @group = Group.find(params[:id])
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/b4/b4cfef9e8223bd39d2080e9087f88b2607c14914.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ProjectsTest < ActionController::IntegrationTest
-  fixtures :projects, :users, :members, :enabled_modules
-
-  def test_archive_project
-    subproject = Project.find(1).children.first
-    log_user("admin", "admin")
-    get "admin/projects"
-    assert_response :success
-    assert_template "admin/projects"
-    post "projects/1/archive"
-    assert_redirected_to "/admin/projects"
-    assert !Project.find(1).active?
-
-    get 'projects/1'
-    assert_response 403
-    get "projects/#{subproject.id}"
-    assert_response 403
-
-    post "projects/1/unarchive"
-    assert_redirected_to "/admin/projects"
-    assert Project.find(1).active?
-    get "projects/1"
-    assert_response :success
-  end
-
-  def test_modules_should_not_allow_get
-    assert_no_difference 'EnabledModule.count' do
-      get '/projects/1/modules', {:enabled_module_names => ['']}, credentials('jsmith')
-      assert_response 404
-    end
-  end
-end
--- a/.svn/pristine/b5/b5912509c719c19cefc865fb8a655b03174ed731.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ActivitiesControllerTest < ActionController::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :groups_users,
-           :enabled_modules,
-           :journals, :journal_details
-
-
-  def test_project_index
-    get :index, :id => 1, :with_subprojects => 0
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:events_by_day)
-
-    assert_select 'h3', :text => /#{2.days.ago.to_date.day}/
-    assert_select 'dl dt.issue-edit a', :text => /(#{IssueStatus.find(2).name})/
-  end
-
-  def test_project_index_with_invalid_project_id_should_respond_404
-    get :index, :id => 299
-    assert_response 404
-  end
-
-  def test_previous_project_index
-    get :index, :id => 1, :from => 2.days.ago.to_date
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:events_by_day)
-
-    assert_select 'h3', :text => /#{3.days.ago.to_date.day}/
-    assert_select 'dl dt.issue a', :text => /Can&#x27;t print recipes/
-  end
-
-  def test_global_index
-    @request.session[:user_id] = 1
-    get :index
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:events_by_day)
-
-    i5 = Issue.find(5)
-    d5 = User.find(1).time_to_date(i5.created_on)
-
-    assert_select 'h3', :text => /#{d5.day}/
-    assert_select 'dl dt.issue a', :text => /Subproject issue/
-  end
-
-  def test_user_index
-    @request.session[:user_id] = 1
-    get :index, :user_id => 2
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:events_by_day)
-
-    assert_select 'h2 a[href=/users/2]', :text => 'John Smith'
-
-    i1 = Issue.find(1)
-    d1 = User.find(1).time_to_date(i1.created_on)
-
-    assert_select 'h3', :text => /#{d1.day}/
-    assert_select 'dl dt.issue a', :text => /Can&#x27;t print recipes/
-  end
-
-  def test_user_index_with_invalid_user_id_should_respond_404
-    get :index, :user_id => 299
-    assert_response 404
-  end
-
-  def test_index_atom_feed
-    get :index, :format => 'atom', :with_subprojects => 0
-    assert_response :success
-    assert_template 'common/feed'
-
-    assert_select 'feed' do
-      assert_select 'link[rel=self][href=?]', 'http://test.host/activity.atom?with_subprojects=0'
-      assert_select 'link[rel=alternate][href=?]', 'http://test.host/activity?with_subprojects=0'
-      assert_select 'entry' do
-        assert_select 'link[href=?]', 'http://test.host/issues/11'
-      end
-    end
-  end
-
-  def test_index_atom_feed_with_explicit_selection
-    get :index, :format => 'atom', :with_subprojects => 0,
-      :show_changesets => 1,
-      :show_documents => 1,
-      :show_files => 1,
-      :show_issues => 1,
-      :show_messages => 1,
-      :show_news => 1,
-      :show_time_entries => 1,
-      :show_wiki_edits => 1
-
-    assert_response :success
-    assert_template 'common/feed'
-
-    assert_select 'feed' do
-      assert_select 'link[rel=self][href=?]', 'http://test.host/activity.atom?show_changesets=1&amp;show_documents=1&amp;show_files=1&amp;show_issues=1&amp;show_messages=1&amp;show_news=1&amp;show_time_entries=1&amp;show_wiki_edits=1&amp;with_subprojects=0'
-      assert_select 'link[rel=alternate][href=?]', 'http://test.host/activity?show_changesets=1&amp;show_documents=1&amp;show_files=1&amp;show_issues=1&amp;show_messages=1&amp;show_news=1&amp;show_time_entries=1&amp;show_wiki_edits=1&amp;with_subprojects=0'
-      assert_select 'entry' do
-        assert_select 'link[href=?]', 'http://test.host/issues/11'
-      end
-    end
-  end
-
-  def test_index_atom_feed_with_one_item_type
-    get :index, :format => 'atom', :show_issues => '1'
-    assert_response :success
-    assert_template 'common/feed'
-
-    assert_select 'title', :text => /Issues/
-  end
-
-  def test_index_should_show_private_notes_with_permission_only
-    journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Private notes with searchkeyword', :private_notes => true)
-    @request.session[:user_id] = 2
-
-    get :index
-    assert_response :success
-    assert_include journal, assigns(:events_by_day).values.flatten
-
-    Role.find(1).remove_permission! :view_private_notes
-    get :index
-    assert_response :success
-    assert_not_include journal, assigns(:events_by_day).values.flatten
-  end
-end
--- a/.svn/pristine/b5/b5d1f708535cf3262ade1830dcd9a0a3f72b68c4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,404 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueNestedSetTest < ActiveSupport::TestCase
-  fixtures :projects, :users, :roles,
-           :trackers, :projects_trackers,
-           :issue_statuses, :issue_categories, :issue_relations,
-           :enumerations,
-           :issues
-
-  def test_create_root_issue
-    issue1 = Issue.generate!
-    issue2 = Issue.generate!
-    issue1.reload
-    issue2.reload
-
-    assert_equal [issue1.id, nil, 1, 2], [issue1.root_id, issue1.parent_id, issue1.lft, issue1.rgt]
-    assert_equal [issue2.id, nil, 1, 2], [issue2.root_id, issue2.parent_id, issue2.lft, issue2.rgt]
-  end
-
-  def test_create_child_issue
-    parent = Issue.generate!
-    child =  Issue.generate!(:parent_issue_id => parent.id)
-    parent.reload
-    child.reload
-
-    assert_equal [parent.id, nil, 1, 4], [parent.root_id, parent.parent_id, parent.lft, parent.rgt]
-    assert_equal [parent.id, parent.id, 2, 3], [child.root_id, child.parent_id, child.lft, child.rgt]
-  end
-
-  def test_creating_a_child_in_a_subproject_should_validate
-    issue = Issue.generate!
-    child = Issue.new(:project_id => 3, :tracker_id => 2, :author_id => 1,
-                      :subject => 'child', :parent_issue_id => issue.id)
-    assert_save child
-    assert_equal issue, child.reload.parent
-  end
-
-  def test_creating_a_child_in_an_invalid_project_should_not_validate
-    issue = Issue.generate!
-    child = Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
-                      :subject => 'child', :parent_issue_id => issue.id)
-    assert !child.save
-    assert_not_equal [], child.errors[:parent_issue_id]
-  end
-
-  def test_move_a_root_to_child
-    parent1 = Issue.generate!
-    parent2 = Issue.generate!
-    child = Issue.generate!(:parent_issue_id => parent1.id)
-
-    parent2.parent_issue_id = parent1.id
-    parent2.save!
-    child.reload
-    parent1.reload
-    parent2.reload
-
-    assert_equal [parent1.id, 1, 6], [parent1.root_id, parent1.lft, parent1.rgt]
-    assert_equal [parent1.id, 4, 5], [parent2.root_id, parent2.lft, parent2.rgt]
-    assert_equal [parent1.id, 2, 3], [child.root_id, child.lft, child.rgt]
-  end
-
-  def test_move_a_child_to_root
-    parent1 = Issue.generate!
-    parent2 = Issue.generate!
-    child =   Issue.generate!(:parent_issue_id => parent1.id)
-
-    child.parent_issue_id = nil
-    child.save!
-    child.reload
-    parent1.reload
-    parent2.reload
-
-    assert_equal [parent1.id, 1, 2], [parent1.root_id, parent1.lft, parent1.rgt]
-    assert_equal [parent2.id, 1, 2], [parent2.root_id, parent2.lft, parent2.rgt]
-    assert_equal [child.id, 1, 2], [child.root_id, child.lft, child.rgt]
-  end
-
-  def test_move_a_child_to_another_issue
-    parent1 = Issue.generate!
-    parent2 = Issue.generate!
-    child =   Issue.generate!(:parent_issue_id => parent1.id)
-
-    child.parent_issue_id = parent2.id
-    child.save!
-    child.reload
-    parent1.reload
-    parent2.reload
-
-    assert_equal [parent1.id, 1, 2], [parent1.root_id, parent1.lft, parent1.rgt]
-    assert_equal [parent2.id, 1, 4], [parent2.root_id, parent2.lft, parent2.rgt]
-    assert_equal [parent2.id, 2, 3], [child.root_id, child.lft, child.rgt]
-  end
-
-  def test_move_a_child_with_descendants_to_another_issue
-    parent1 = Issue.generate!
-    parent2 = Issue.generate!
-    child =   Issue.generate!(:parent_issue_id => parent1.id)
-    grandchild = Issue.generate!(:parent_issue_id => child.id)
-
-    parent1.reload
-    parent2.reload
-    child.reload
-    grandchild.reload
-
-    assert_equal [parent1.id, 1, 6], [parent1.root_id, parent1.lft, parent1.rgt]
-    assert_equal [parent2.id, 1, 2], [parent2.root_id, parent2.lft, parent2.rgt]
-    assert_equal [parent1.id, 2, 5], [child.root_id, child.lft, child.rgt]
-    assert_equal [parent1.id, 3, 4], [grandchild.root_id, grandchild.lft, grandchild.rgt]
-
-    child.reload.parent_issue_id = parent2.id
-    child.save!
-    child.reload
-    grandchild.reload
-    parent1.reload
-    parent2.reload
-
-    assert_equal [parent1.id, 1, 2], [parent1.root_id, parent1.lft, parent1.rgt]
-    assert_equal [parent2.id, 1, 6], [parent2.root_id, parent2.lft, parent2.rgt]
-    assert_equal [parent2.id, 2, 5], [child.root_id, child.lft, child.rgt]
-    assert_equal [parent2.id, 3, 4], [grandchild.root_id, grandchild.lft, grandchild.rgt]
-  end
-
-  def test_move_a_child_with_descendants_to_another_project
-    parent1 = Issue.generate!
-    child =   Issue.generate!(:parent_issue_id => parent1.id)
-    grandchild = Issue.generate!(:parent_issue_id => child.id)
-
-    child.reload
-    child.project = Project.find(2)
-    assert child.save
-    child.reload
-    grandchild.reload
-    parent1.reload
-
-    assert_equal [1, parent1.id, 1, 2], [parent1.project_id, parent1.root_id, parent1.lft, parent1.rgt]
-    assert_equal [2, child.id, 1, 4], [child.project_id, child.root_id, child.lft, child.rgt]
-    assert_equal [2, child.id, 2, 3], [grandchild.project_id, grandchild.root_id, grandchild.lft, grandchild.rgt]
-  end
-
-  def test_moving_an_issue_to_a_descendant_should_not_validate
-    parent1 = Issue.generate!
-    parent2 = Issue.generate!
-    child =   Issue.generate!(:parent_issue_id => parent1.id)
-    grandchild = Issue.generate!(:parent_issue_id => child.id)
-
-    child.reload
-    child.parent_issue_id = grandchild.id
-    assert !child.save
-    assert_not_equal [], child.errors[:parent_issue_id]
-  end
-
-  def test_updating_a_root_issue_should_not_trigger_update_nested_set_attributes_on_parent_change
-    issue = Issue.find(Issue.generate!.id)
-    issue.parent_issue_id = ""
-    issue.expects(:update_nested_set_attributes_on_parent_change).never
-    issue.save!
-  end
-
-  def test_updating_a_child_issue_should_not_trigger_update_nested_set_attributes_on_parent_change
-    issue = Issue.find(Issue.generate!(:parent_issue_id => 1).id)
-    issue.parent_issue_id = "1"
-    issue.expects(:update_nested_set_attributes_on_parent_change).never
-    issue.save!
-  end
-
-  def test_moving_a_root_issue_should_trigger_update_nested_set_attributes_on_parent_change
-    issue = Issue.find(Issue.generate!.id)
-    issue.parent_issue_id = "1"
-    issue.expects(:update_nested_set_attributes_on_parent_change).once
-    issue.save!
-  end
-
-  def test_moving_a_child_issue_to_another_parent_should_trigger_update_nested_set_attributes_on_parent_change
-    issue = Issue.find(Issue.generate!(:parent_issue_id => 1).id)
-    issue.parent_issue_id = "2"
-    issue.expects(:update_nested_set_attributes_on_parent_change).once
-    issue.save!
-  end
-
-  def test_moving_a_child_issue_to_root_should_trigger_update_nested_set_attributes_on_parent_change
-    issue = Issue.find(Issue.generate!(:parent_issue_id => 1).id)
-    issue.parent_issue_id = ""
-    issue.expects(:update_nested_set_attributes_on_parent_change).once
-    issue.save!
-  end
-
-  def test_destroy_should_destroy_children
-    issue1 = Issue.generate!
-    issue2 = Issue.generate!
-    issue3 = Issue.generate!(:parent_issue_id => issue2.id)
-    issue4 = Issue.generate!(:parent_issue_id => issue1.id)
-
-    issue3.init_journal(User.find(2))
-    issue3.subject = 'child with journal'
-    issue3.save!
-
-    assert_difference 'Issue.count', -2 do
-      assert_difference 'Journal.count', -1 do
-        assert_difference 'JournalDetail.count', -1 do
-          Issue.find(issue2.id).destroy
-        end
-      end
-    end
-
-    issue1.reload
-    issue4.reload
-    assert !Issue.exists?(issue2.id)
-    assert !Issue.exists?(issue3.id)
-    assert_equal [issue1.id, 1, 4], [issue1.root_id, issue1.lft, issue1.rgt]
-    assert_equal [issue1.id, 2, 3], [issue4.root_id, issue4.lft, issue4.rgt]
-  end
-  
-  def test_destroy_child_should_update_parent
-    issue = Issue.generate!
-    child1 = Issue.generate!(:parent_issue_id => issue.id)
-    child2 = Issue.generate!(:parent_issue_id => issue.id)
-    
-    issue.reload
-    assert_equal [issue.id, 1, 6], [issue.root_id, issue.lft, issue.rgt]
-    
-    child2.reload.destroy
-    
-    issue.reload
-    assert_equal [issue.id, 1, 4], [issue.root_id, issue.lft, issue.rgt]
-  end
-
-  def test_destroy_parent_issue_updated_during_children_destroy
-    parent = Issue.generate!
-    Issue.generate!(:start_date => Date.today, :parent_issue_id => parent.id)
-    Issue.generate!(:start_date => 2.days.from_now, :parent_issue_id => parent.id)
-
-    assert_difference 'Issue.count', -3 do
-      Issue.find(parent.id).destroy
-    end
-  end
-
-  def test_destroy_child_issue_with_children
-    root = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'root')
-    child = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => root.id)
-    leaf = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'leaf', :parent_issue_id => child.id)
-    leaf.init_journal(User.find(2))
-    leaf.subject = 'leaf with journal'
-    leaf.save!
-
-    assert_difference 'Issue.count', -2 do
-      assert_difference 'Journal.count', -1 do
-        assert_difference 'JournalDetail.count', -1 do
-          Issue.find(child.id).destroy
-        end
-      end
-    end
-
-    root = Issue.find(root.id)
-    assert root.leaf?, "Root issue is not a leaf (lft: #{root.lft}, rgt: #{root.rgt})"
-  end
-
-  def test_destroy_issue_with_grand_child
-    parent = Issue.generate!
-    issue = Issue.generate!(:parent_issue_id => parent.id)
-    child = Issue.generate!(:parent_issue_id => issue.id)
-    grandchild1 = Issue.generate!(:parent_issue_id => child.id)
-    grandchild2 = Issue.generate!(:parent_issue_id => child.id)
-
-    assert_difference 'Issue.count', -4 do
-      Issue.find(issue.id).destroy
-      parent.reload
-      assert_equal [1, 2], [parent.lft, parent.rgt]
-    end
-  end
-
-  def test_parent_priority_should_be_the_highest_child_priority
-    parent = Issue.generate!(:priority => IssuePriority.find_by_name('Normal'))
-    # Create children
-    child1 = Issue.generate!(:priority => IssuePriority.find_by_name('High'), :parent_issue_id => parent.id)
-    assert_equal 'High', parent.reload.priority.name
-    child2 = Issue.generate!(:priority => IssuePriority.find_by_name('Immediate'), :parent_issue_id => child1.id)
-    assert_equal 'Immediate', child1.reload.priority.name
-    assert_equal 'Immediate', parent.reload.priority.name
-    child3 = Issue.generate!(:priority => IssuePriority.find_by_name('Low'), :parent_issue_id => parent.id)
-    assert_equal 'Immediate', parent.reload.priority.name
-    # Destroy a child
-    child1.destroy
-    assert_equal 'Low', parent.reload.priority.name
-    # Update a child
-    child3.reload.priority = IssuePriority.find_by_name('Normal')
-    child3.save!
-    assert_equal 'Normal', parent.reload.priority.name
-  end
-
-  def test_parent_dates_should_be_lowest_start_and_highest_due_dates
-    parent = Issue.generate!
-    Issue.generate!(:start_date => '2010-01-25', :due_date => '2010-02-15', :parent_issue_id => parent.id)
-    Issue.generate!(                             :due_date => '2010-02-13', :parent_issue_id => parent.id)
-    Issue.generate!(:start_date => '2010-02-01', :due_date => '2010-02-22', :parent_issue_id => parent.id)
-    parent.reload
-    assert_equal Date.parse('2010-01-25'), parent.start_date
-    assert_equal Date.parse('2010-02-22'), parent.due_date
-  end
-
-  def test_parent_done_ratio_should_be_average_done_ratio_of_leaves
-    parent = Issue.generate!
-    Issue.generate!(:done_ratio => 20, :parent_issue_id => parent.id)
-    assert_equal 20, parent.reload.done_ratio
-    Issue.generate!(:done_ratio => 70, :parent_issue_id => parent.id)
-    assert_equal 45, parent.reload.done_ratio
-
-    child = Issue.generate!(:done_ratio => 0, :parent_issue_id => parent.id)
-    assert_equal 30, parent.reload.done_ratio
-
-    Issue.generate!(:done_ratio => 30, :parent_issue_id => child.id)
-    assert_equal 30, child.reload.done_ratio
-    assert_equal 40, parent.reload.done_ratio
-  end
-
-  def test_parent_done_ratio_should_be_weighted_by_estimated_times_if_any
-    parent = Issue.generate!
-    Issue.generate!(:estimated_hours => 10, :done_ratio => 20, :parent_issue_id => parent.id)
-    assert_equal 20, parent.reload.done_ratio
-    Issue.generate!(:estimated_hours => 20, :done_ratio => 50, :parent_issue_id => parent.id)
-    assert_equal (50 * 20 + 20 * 10) / 30, parent.reload.done_ratio
-  end
-
-  def test_parent_done_ratio_with_child_estimate_to_0_should_reach_100
-    parent = Issue.generate!
-    issue1 = Issue.generate!(:parent_issue_id => parent.id)
-    issue2 = Issue.generate!(:parent_issue_id => parent.id, :estimated_hours => 0)
-    assert_equal 0, parent.reload.done_ratio
-    issue1.reload.update_attribute :status_id, 5
-    assert_equal 50, parent.reload.done_ratio
-    issue2.reload.update_attribute :status_id, 5
-    assert_equal 100, parent.reload.done_ratio
-  end
-
-  def test_parent_estimate_should_be_sum_of_leaves
-    parent = Issue.generate!
-    Issue.generate!(:estimated_hours => nil, :parent_issue_id => parent.id)
-    assert_equal nil, parent.reload.estimated_hours
-    Issue.generate!(:estimated_hours => 5, :parent_issue_id => parent.id)
-    assert_equal 5, parent.reload.estimated_hours
-    Issue.generate!(:estimated_hours => 7, :parent_issue_id => parent.id)
-    assert_equal 12, parent.reload.estimated_hours
-  end
-
-  def test_move_parent_updates_old_parent_attributes
-    first_parent = Issue.generate!
-    second_parent = Issue.generate!
-    child = Issue.generate!(:estimated_hours => 5, :parent_issue_id => first_parent.id)
-    assert_equal 5, first_parent.reload.estimated_hours
-    child.update_attributes(:estimated_hours => 7, :parent_issue_id => second_parent.id)
-    assert_equal 7, second_parent.reload.estimated_hours
-    assert_nil first_parent.reload.estimated_hours
-  end
-
-  def test_reschuling_a_parent_should_reschedule_subtasks
-    parent = Issue.generate!
-    c1 = Issue.generate!(:start_date => '2010-05-12', :due_date => '2010-05-18', :parent_issue_id => parent.id)
-    c2 = Issue.generate!(:start_date => '2010-06-03', :due_date => '2010-06-10', :parent_issue_id => parent.id)
-    parent.reload
-    parent.reschedule_on!(Date.parse('2010-06-02'))
-    c1.reload
-    assert_equal [Date.parse('2010-06-02'), Date.parse('2010-06-08')], [c1.start_date, c1.due_date]
-    c2.reload
-    assert_equal [Date.parse('2010-06-03'), Date.parse('2010-06-10')], [c2.start_date, c2.due_date] # no change
-    parent.reload
-    assert_equal [Date.parse('2010-06-02'), Date.parse('2010-06-10')], [parent.start_date, parent.due_date]
-  end
-
-  def test_project_copy_should_copy_issue_tree
-    p = Project.create!(:name => 'Tree copy', :identifier => 'tree-copy', :tracker_ids => [1, 2])
-    i1 = Issue.generate!(:project => p, :subject => 'i1')
-    i2 = Issue.generate!(:project => p, :subject => 'i2', :parent_issue_id => i1.id)
-    i3 = Issue.generate!(:project => p, :subject => 'i3', :parent_issue_id => i1.id)
-    i4 = Issue.generate!(:project => p, :subject => 'i4', :parent_issue_id => i2.id)
-    i5 = Issue.generate!(:project => p, :subject => 'i5')
-    c = Project.new(:name => 'Copy', :identifier => 'copy', :tracker_ids => [1, 2])
-    c.copy(p, :only => 'issues')
-    c.reload
-
-    assert_equal 5, c.issues.count
-    ic1, ic2, ic3, ic4, ic5 = c.issues.order('subject').all
-    assert ic1.root?
-    assert_equal ic1, ic2.parent
-    assert_equal ic1, ic3.parent
-    assert_equal ic2, ic4.parent
-    assert ic5.root?
-  end
-end
--- a/.svn/pristine/b6/b60c09f950ca3bc2a75c168cc7ffe809b3b36299.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::AuthenticationTest < Redmine::ApiTest::Base
-  fixtures :users
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  def teardown
-    Setting.rest_api_enabled = '0'
-  end
-
-  def test_api_request_should_not_use_user_session
-    log_user('jsmith', 'jsmith')
-
-    get '/users/current'
-    assert_response :success
-
-    get '/users/current.json'
-    assert_response 401
-  end
-
-  def test_api_should_accept_switch_user_header_for_admin_user
-    user = User.find(1)
-    su = User.find(4)
-
-    get '/users/current', {}, {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login}
-    assert_response :success
-    assert_equal su, assigns(:user)
-    assert_equal su, User.current
-  end
-
-  def test_api_should_respond_with_412_when_trying_to_switch_to_a_invalid_user
-    get '/users/current', {}, {'X-Redmine-API-Key' => User.find(1).api_key, 'X-Redmine-Switch-User' => 'foobar'}
-    assert_response 412
-  end
-
-  def test_api_should_respond_with_412_when_trying_to_switch_to_a_locked_user
-    user = User.find(5)
-    assert user.locked?
-
-    get '/users/current', {}, {'X-Redmine-API-Key' => User.find(1).api_key, 'X-Redmine-Switch-User' => user.login}
-    assert_response 412
-  end
-
-  def test_api_should_not_accept_switch_user_header_for_non_admin_user
-    user = User.find(2)
-    su = User.find(4)
-
-    get '/users/current', {}, {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login}
-    assert_response :success
-    assert_equal user, assigns(:user)
-    assert_equal user, User.current
-  end
-end
--- a/.svn/pristine/b7/b7b9cbccc43c521f9ee2bd4c48abf815b2cf5508.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class News < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  belongs_to :project
-  belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
-  has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
-
-  validates_presence_of :title, :description
-  validates_length_of :title, :maximum => 60
-  validates_length_of :summary, :maximum => 255
-
-  acts_as_attachable :delete_permission => :manage_news
-  acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
-  acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
-  acts_as_activity_provider :find_options => {:include => [:project, :author]},
-                            :author_key => :author_id
-  acts_as_watchable
-
-  after_create :add_author_as_watcher
-  after_create :send_notification
-
-  scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args))
-  }
-
-  safe_attributes 'title', 'summary', 'description'
-
-  def visible?(user=User.current)
-    !user.nil? && user.allowed_to?(:view_news, project)
-  end
-
-  # Returns true if the news can be commented by user
-  def commentable?(user=User.current)
-    user.allowed_to?(:comment_news, project)
-  end
-
-  def recipients
-    project.users.select {|user| user.notify_about?(self)}.map(&:mail)
-  end
-
-  # returns latest news for projects visible by user
-  def self.latest(user = User.current, count = 5)
-    visible(user).includes([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).all
-  end
-
-  private
-
-  def add_author_as_watcher
-    Watcher.create(:watchable => self, :user => author)
-  end
-
-  def send_notification
-    if Setting.notified_events.include?('news_added')
-      Mailer.news_added(self).deliver
-    end
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/b8/b89495372bc55506424effd6c3e5df5c0cb09a12.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,84 @@
+# Redmine - project management software
+# Copyright (C) 2006-2014  Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+class AdminController < ApplicationController
+  layout 'admin'
+  menu_item :projects, :only => :projects
+  menu_item :plugins, :only => :plugins
+  menu_item :info, :only => :info
+
+  before_filter :require_admin
+  helper :sort
+  include SortHelper
+
+  def index
+    @no_configuration_data = Redmine::DefaultData::Loader::no_data?
+  end
+
+  def projects
+    @status = params[:status] || 1
+
+    scope = Project.status(@status).order('lft')
+    scope = scope.like(params[:name]) if params[:name].present?
+    @projects = scope.all
+
+    render :action => "projects", :layout => false if request.xhr?
+  end
+
+  def plugins
+    @plugins = Redmine::Plugin.all
+  end
+
+  # Loads the default configuration
+  # (roles, trackers, statuses, workflow, enumerations)
+  def default_configuration
+    if request.post?
+      begin
+        Redmine::DefaultData::Loader::load(params[:lang])
+        flash[:notice] = l(:notice_default_data_loaded)
+      rescue Exception => e
+        flash[:error] = l(:error_can_t_load_default_data, e.message)
+      end
+    end
+    redirect_to admin_path
+  end
+
+  def test_email
+    raise_delivery_errors = ActionMailer::Base.raise_delivery_errors
+    # Force ActionMailer to raise delivery errors so we can catch it
+    ActionMailer::Base.raise_delivery_errors = true
+    begin
+      @test = Mailer.test_email(User.current).deliver
+      flash[:notice] = l(:notice_email_sent, User.current.mail)
+    rescue Exception => e
+      flash[:error] = l(:notice_email_error, Redmine::CodesetUtil.replace_invalid_utf8(e.message.dup))
+    end
+    ActionMailer::Base.raise_delivery_errors = raise_delivery_errors
+    redirect_to settings_path(:tab => 'notifications')
+  end
+
+  def info
+    @db_adapter_name = ActiveRecord::Base.connection.adapter_name
+    @checklist = [
+      [:text_default_administrator_account_changed, User.default_admin_account_changed?],
+      [:text_file_repository_writable, File.writable?(Attachment.storage_path)],
+      [:text_plugin_assets_writable,   File.writable?(Redmine::Plugin.public_directory)],
+      [:text_rmagick_available,        Object.const_defined?(:Magick)],
+      [:text_convert_available,        Redmine::Thumbnail.convert_available?]
+    ]
+  end
+end
--- a/.svn/pristine/b8/b8c4a4f62502265603b5dac16f30aca8838956d0.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,341 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/abstract_adapter'
-require 'cgi'
-
-module Redmine
-  module Scm
-    module Adapters
-      class MercurialAdapter < AbstractAdapter
-
-        # Mercurial executable name
-        HG_BIN = Redmine::Configuration['scm_mercurial_command'] || "hg"
-        HELPERS_DIR = File.dirname(__FILE__) + "/mercurial"
-        HG_HELPER_EXT = "#{HELPERS_DIR}/redminehelper.py"
-        TEMPLATE_NAME = "hg-template"
-        TEMPLATE_EXTENSION = "tmpl"
-
-        # raised if hg command exited with error, e.g. unknown revision.
-        class HgCommandAborted < CommandFailed; end
-
-        class << self
-          def client_command
-            @@bin    ||= HG_BIN
-          end
-
-          def sq_bin
-            @@sq_bin ||= shell_quote_command
-          end
-
-          def client_version
-            @@client_version ||= (hgversion || [])
-          end
-
-          def client_available
-            client_version_above?([1, 2])
-          end
-
-          def hgversion
-            # The hg version is expressed either as a
-            # release number (eg 0.9.5 or 1.0) or as a revision
-            # id composed of 12 hexa characters.
-            theversion = hgversion_from_command_line.dup
-            if theversion.respond_to?(:force_encoding)
-              theversion.force_encoding('ASCII-8BIT')
-            end
-            if m = theversion.match(%r{\A(.*?)((\d+\.)+\d+)})
-              m[2].scan(%r{\d+}).collect(&:to_i)
-            end
-          end
-
-          def hgversion_from_command_line
-            shellout("#{sq_bin} --version") { |io| io.read }.to_s
-          end
-
-          def template_path
-            @@template_path ||= template_path_for(client_version)
-          end
-
-          def template_path_for(version)
-            "#{HELPERS_DIR}/#{TEMPLATE_NAME}-1.0.#{TEMPLATE_EXTENSION}"
-          end
-        end
-
-        def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
-          super
-          @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
-        end
-
-        def path_encoding
-          @path_encoding
-        end
-
-        def info
-          tip = summary['repository']['tip']
-          Info.new(:root_url => CGI.unescape(summary['repository']['root']),
-                   :lastrev => Revision.new(:revision => tip['revision'],
-                                            :scmid => tip['node']))
-        # rescue HgCommandAborted
-        rescue Exception => e
-          logger.error "hg: error during getting info: #{e.message}"
-          nil
-        end
-
-        def tags
-          as_ary(summary['repository']['tag']).map { |e| e['name'] }
-        end
-
-        # Returns map of {'tag' => 'nodeid', ...}
-        def tagmap
-          alist = as_ary(summary['repository']['tag']).map do |e|
-            e.values_at('name', 'node')
-          end
-          Hash[*alist.flatten]
-        end
-
-        def branches
-          brs = []
-          as_ary(summary['repository']['branch']).each do |e|
-            br = Branch.new(e['name'])
-            br.revision =  e['revision']
-            br.scmid    =  e['node']
-            brs << br
-          end
-          brs
-        end
-
-        # Returns map of {'branch' => 'nodeid', ...}
-        def branchmap
-          alist = as_ary(summary['repository']['branch']).map do |e|
-            e.values_at('name', 'node')
-          end
-          Hash[*alist.flatten]
-        end
-
-        def summary
-          return @summary if @summary
-          hg 'rhsummary' do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
-            begin
-              @summary = parse_xml(output)['rhsummary']
-            rescue
-            end
-          end
-        end
-        private :summary
-
-        def entries(path=nil, identifier=nil, options={})
-          p1 = scm_iconv(@path_encoding, 'UTF-8', path)
-          manifest = hg('rhmanifest', '-r', CGI.escape(hgrev(identifier)),
-                        CGI.escape(without_leading_slash(p1.to_s))) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
-            begin
-              parse_xml(output)['rhmanifest']['repository']['manifest']
-            rescue
-            end
-          end
-          path_prefix = path.blank? ? '' : with_trailling_slash(path)
-
-          entries = Entries.new
-          as_ary(manifest['dir']).each do |e|
-            n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name']))
-            p = "#{path_prefix}#{n}"
-            entries << Entry.new(:name => n, :path => p, :kind => 'dir')
-          end
-
-          as_ary(manifest['file']).each do |e|
-            n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name']))
-            p = "#{path_prefix}#{n}"
-            lr = Revision.new(:revision => e['revision'], :scmid => e['node'],
-                              :identifier => e['node'],
-                              :time => Time.at(e['time'].to_i))
-            entries << Entry.new(:name => n, :path => p, :kind => 'file',
-                                 :size => e['size'].to_i, :lastrev => lr)
-          end
-
-          entries
-        rescue HgCommandAborted
-          nil  # means not found
-        end
-
-        def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
-          revs = Revisions.new
-          each_revision(path, identifier_from, identifier_to, options) { |e| revs << e }
-          revs
-        end
-
-        # Iterates the revisions by using a template file that
-        # makes Mercurial produce a xml output.
-        def each_revision(path=nil, identifier_from=nil, identifier_to=nil, options={})
-          hg_args = ['log', '--debug', '-C', '--style', self.class.template_path]
-          hg_args << '-r' << "#{hgrev(identifier_from)}:#{hgrev(identifier_to)}"
-          hg_args << '--limit' << options[:limit] if options[:limit]
-          hg_args << hgtarget(path) unless path.blank?
-          log = hg(*hg_args) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
-            begin
-              # Mercurial < 1.5 does not support footer template for '</log>'
-              parse_xml("#{output}</log>")['log']
-            rescue
-            end
-          end
-          as_ary(log['logentry']).each do |le|
-            cpalist = as_ary(le['paths']['path-copied']).map do |e|
-              [e['__content__'], e['copyfrom-path']].map do |s|
-                scm_iconv('UTF-8', @path_encoding, CGI.unescape(s))
-              end
-            end
-            cpmap = Hash[*cpalist.flatten]
-            paths = as_ary(le['paths']['path']).map do |e|
-              p = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['__content__']) )
-              {:action        => e['action'],
-               :path          => with_leading_slash(p),
-               :from_path     => (cpmap.member?(p) ? with_leading_slash(cpmap[p]) : nil),
-               :from_revision => (cpmap.member?(p) ? le['node'] : nil)}
-            end.sort { |a, b| a[:path] <=> b[:path] }
-            parents_ary = []
-            as_ary(le['parents']['parent']).map do |par|
-              parents_ary << par['__content__'] if par['__content__'] != "000000000000"
-            end
-            yield Revision.new(:revision => le['revision'],
-                               :scmid    => le['node'],
-                               :author   => (le['author']['__content__'] rescue ''),
-                               :time     => Time.parse(le['date']['__content__']),
-                               :message  => le['msg']['__content__'],
-                               :paths    => paths,
-                               :parents  => parents_ary)
-          end
-          self
-        end
-
-        # Returns list of nodes in the specified branch
-        def nodes_in_branch(branch, options={})
-          hg_args = ['rhlog', '--template', '{node|short}\n', '--rhbranch', CGI.escape(branch)]
-          hg_args << '--from' << CGI.escape(branch)
-          hg_args << '--to'   << '0'
-          hg_args << '--limit' << options[:limit] if options[:limit]
-          hg(*hg_args) { |io| io.readlines.map { |e| e.chomp } }
-        end
-
-        def diff(path, identifier_from, identifier_to=nil)
-          hg_args = %w|rhdiff|
-          if identifier_to
-            hg_args << '-r' << hgrev(identifier_to) << '-r' << hgrev(identifier_from)
-          else
-            hg_args << '-c' << hgrev(identifier_from)
-          end
-          unless path.blank?
-            p = scm_iconv(@path_encoding, 'UTF-8', path)
-            hg_args << CGI.escape(hgtarget(p))
-          end
-          diff = []
-          hg *hg_args do |io|
-            io.each_line do |line|
-              diff << line
-            end
-          end
-          diff
-        rescue HgCommandAborted
-          nil  # means not found
-        end
-
-        def cat(path, identifier=nil)
-          p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path))
-          hg 'rhcat', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
-            io.binmode
-            io.read
-          end
-        rescue HgCommandAborted
-          nil  # means not found
-        end
-
-        def annotate(path, identifier=nil)
-          p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path))
-          blame = Annotate.new
-          hg 'rhannotate', '-ncu', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
-            io.each_line do |line|
-              line.force_encoding('ASCII-8BIT') if line.respond_to?(:force_encoding)
-              next unless line =~ %r{^([^:]+)\s(\d+)\s([0-9a-f]+):\s(.*)$}
-              r = Revision.new(:author => $1.strip, :revision => $2, :scmid => $3,
-                               :identifier => $3)
-              blame.add_line($4.rstrip, r)
-            end
-          end
-          blame
-        rescue HgCommandAborted
-          # means not found or cannot be annotated
-          Annotate.new
-        end
-
-        class Revision < Redmine::Scm::Adapters::Revision
-          # Returns the readable identifier
-          def format_identifier
-            "#{revision}:#{scmid}"
-          end
-        end
-
-        # Runs 'hg' command with the given args
-        def hg(*args, &block)
-          repo_path = root_url || url
-          full_args = ['-R', repo_path, '--encoding', 'utf-8']
-          full_args << '--config' << "extensions.redminehelper=#{HG_HELPER_EXT}"
-          full_args << '--config' << 'diff.git=false'
-          full_args += args
-          ret = shellout(
-                   self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
-                   &block
-                   )
-          if $? && $?.exitstatus != 0
-            raise HgCommandAborted, "hg exited with non-zero status: #{$?.exitstatus}"
-          end
-          ret
-        end
-        private :hg
-
-        # Returns correct revision identifier
-        def hgrev(identifier, sq=false)
-          rev = identifier.blank? ? 'tip' : identifier.to_s
-          rev = shell_quote(rev) if sq
-          rev
-        end
-        private :hgrev
-
-        def hgtarget(path)
-          path ||= ''
-          root_url + '/' + without_leading_slash(path)
-        end
-        private :hgtarget
-
-        def as_ary(o)
-          return [] unless o
-          o.is_a?(Array) ? o : Array[o]
-        end
-        private :as_ary
-      end
-    end
-  end
-end
--- a/.svn/pristine/b9/b90cd149441f836cbc1e4f50f6a53eb280e646a6.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine #:nodoc:
-  module CoreExtensions #:nodoc:
-    module String #:nodoc:
-      # Custom string conversions
-      module Conversions
-        # Parses hours format and returns a float
-        def to_hours
-          s = self.dup
-          s.strip!
-          if s =~ %r{^(\d+([.,]\d+)?)h?$}
-            s = $1
-          else
-            # 2:30 => 2.5
-            s.gsub!(%r{^(\d+):(\d+)$}) { $1.to_i + $2.to_i / 60.0 }
-            # 2h30, 2h, 30m => 2.5, 2, 0.5
-            s.gsub!(%r{^((\d+)\s*(h|hours?))?\s*((\d+)\s*(m|min)?)?$}i) { |m| ($1 || $4) ? ($2.to_i + $5.to_i / 60.0) : m[0] }
-          end
-          # 2,5 => 2.5
-          s.gsub!(',', '.')
-          begin; Kernel.Float(s); rescue; nil; end
-        end
-
-        # Object#to_a removed in ruby1.9
-        if RUBY_VERSION > '1.9'
-          def to_a
-            [self.dup]
-          end
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/b9/b94e9d09ba0ad12320000d9bdc7207a4e6a55736.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::MenuManagerTest < ActiveSupport::TestCase
-  def test_map_should_yield_a_mapper
-    assert_difference 'Redmine::MenuManager.items(:project_menu).size' do
-      Redmine::MenuManager.map :project_menu do |mapper|
-        assert_kind_of  Redmine::MenuManager::Mapper, mapper
-        mapper.push :new_item, '/'
-      end
-    end
-  end
-
-  def test_items_should_return_menu_items
-    items = Redmine::MenuManager.items(:project_menu)
-    assert_kind_of Redmine::MenuManager::MenuNode, items.first
-  end
-end
--- a/.svn/pristine/ba/bac21e03aae70ae56858e7065d4f49d3a53cf7d7.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Setting < ActiveRecord::Base
-
-  DATE_FORMATS = [
-        '%Y-%m-%d',
-        '%d/%m/%Y',
-        '%d.%m.%Y',
-        '%d-%m-%Y',
-        '%m/%d/%Y',
-        '%d %b %Y',
-        '%d %B %Y',
-        '%b %d, %Y',
-        '%B %d, %Y'
-    ]
-
-  TIME_FORMATS = [
-    '%H:%M',
-    '%I:%M %p'
-    ]
-
-  ENCODINGS = %w(US-ASCII
-                  windows-1250
-                  windows-1251
-                  windows-1252
-                  windows-1253
-                  windows-1254
-                  windows-1255
-                  windows-1256
-                  windows-1257
-                  windows-1258
-                  windows-31j
-                  ISO-2022-JP
-                  ISO-2022-KR
-                  ISO-8859-1
-                  ISO-8859-2
-                  ISO-8859-3
-                  ISO-8859-4
-                  ISO-8859-5
-                  ISO-8859-6
-                  ISO-8859-7
-                  ISO-8859-8
-                  ISO-8859-9
-                  ISO-8859-13
-                  ISO-8859-15
-                  KOI8-R
-                  UTF-8
-                  UTF-16
-                  UTF-16BE
-                  UTF-16LE
-                  EUC-JP
-                  Shift_JIS
-                  CP932
-                  GB18030
-                  GBK
-                  ISCII91
-                  EUC-KR
-                  Big5
-                  Big5-HKSCS
-                  TIS-620)
-
-  cattr_accessor :available_settings
-  @@available_settings = YAML::load(File.open("#{Rails.root}/config/settings.yml"))
-  Redmine::Plugin.all.each do |plugin|
-    next unless plugin.settings
-    @@available_settings["plugin_#{plugin.id}"] = {'default' => plugin.settings[:default], 'serialized' => true}
-  end
-
-  validates_uniqueness_of :name
-  validates_inclusion_of :name, :in => @@available_settings.keys
-  validates_numericality_of :value, :only_integer => true, :if => Proc.new { |setting| @@available_settings[setting.name]['format'] == 'int' }
-
-  # Hash used to cache setting values
-  @cached_settings = {}
-  @cached_cleared_on = Time.now
-
-  def value
-    v = read_attribute(:value)
-    # Unserialize serialized settings
-    v = YAML::load(v) if @@available_settings[name]['serialized'] && v.is_a?(String)
-    v = v.to_sym if @@available_settings[name]['format'] == 'symbol' && !v.blank?
-    v
-  end
-
-  def value=(v)
-    v = v.to_yaml if v && @@available_settings[name] && @@available_settings[name]['serialized']
-    write_attribute(:value, v.to_s)
-  end
-
-  # Returns the value of the setting named name
-  def self.[](name)
-    v = @cached_settings[name]
-    v ? v : (@cached_settings[name] = find_or_default(name).value)
-  end
-
-  def self.[]=(name, v)
-    setting = find_or_default(name)
-    setting.value = (v ? v : "")
-    @cached_settings[name] = nil
-    setting.save
-    setting.value
-  end
-
-  # Defines getter and setter for each setting
-  # Then setting values can be read using: Setting.some_setting_name
-  # or set using Setting.some_setting_name = "some value"
-  @@available_settings.each do |name, params|
-    src = <<-END_SRC
-    def self.#{name}
-      self[:#{name}]
-    end
-
-    def self.#{name}?
-      self[:#{name}].to_i > 0
-    end
-
-    def self.#{name}=(value)
-      self[:#{name}] = value
-    end
-END_SRC
-    class_eval src, __FILE__, __LINE__
-  end
-
-  # Sets a setting value from params
-  def self.set_from_params(name, params)
-    params = params.dup
-    params.delete_if {|v| v.blank? } if params.is_a?(Array)
-
-    m = "#{name}_from_params"
-    if respond_to? m
-      self[name.to_sym] = send m, params
-    else
-      self[name.to_sym] = params
-    end
-  end
-
-  # Returns a hash suitable for commit_update_keywords setting
-  #
-  # Example:
-  # params = {:keywords => ['fixes', 'closes'], :status_id => ["3", "5"], :done_ratio => ["", "100"]}
-  # Setting.commit_update_keywords_from_params(params)
-  # # => [{'keywords => 'fixes', 'status_id' => "3"}, {'keywords => 'closes', 'status_id' => "5", 'done_ratio' => "100"}]
-  def self.commit_update_keywords_from_params(params)
-    s = []
-    if params.is_a?(Hash) && params.key?(:keywords) && params.values.all? {|v| v.is_a? Array}
-      attributes = params.except(:keywords).keys
-      params[:keywords].each_with_index do |keywords, i|
-        next if keywords.blank?
-        s << attributes.inject({}) {|h, a|
-          value = params[a][i].to_s
-          h[a.to_s] = value if value.present?
-          h
-        }.merge('keywords' => keywords)
-      end
-    end
-    s
-  end
-
-  # Helper that returns an array based on per_page_options setting
-  def self.per_page_options_array
-    per_page_options.split(%r{[\s,]}).collect(&:to_i).select {|n| n > 0}.sort
-  end
-
-  # Helper that returns a Hash with single update keywords as keys
-  def self.commit_update_keywords_array
-    a = []
-    if commit_update_keywords.is_a?(Array)
-      commit_update_keywords.each do |rule|
-        next unless rule.is_a?(Hash)
-        rule = rule.dup
-        rule.delete_if {|k, v| v.blank?}
-        keywords = rule['keywords'].to_s.downcase.split(",").map(&:strip).reject(&:blank?)
-        next if keywords.empty?
-        a << rule.merge('keywords' => keywords)
-      end
-    end
-    a
-  end
-
-  def self.commit_fix_keywords
-    ActiveSupport::Deprecation.warn "Setting.commit_fix_keywords is deprecated and will be removed in Redmine 3"
-    if commit_update_keywords.is_a?(Array)
-      commit_update_keywords.first && commit_update_keywords.first['keywords']
-    end
-  end
-
-  def self.commit_fix_status_id
-    ActiveSupport::Deprecation.warn "Setting.commit_fix_status_id is deprecated and will be removed in Redmine 3"
-    if commit_update_keywords.is_a?(Array)
-      commit_update_keywords.first && commit_update_keywords.first['status_id']
-    end
-  end
-
-  def self.commit_fix_done_ratio
-    ActiveSupport::Deprecation.warn "Setting.commit_fix_done_ratio is deprecated and will be removed in Redmine 3"
-    if commit_update_keywords.is_a?(Array)
-      commit_update_keywords.first && commit_update_keywords.first['done_ratio']
-    end
-  end
-
-  def self.openid?
-    Object.const_defined?(:OpenID) && self[:openid].to_i > 0
-  end
-
-  # Checks if settings have changed since the values were read
-  # and clears the cache hash if it's the case
-  # Called once per request
-  def self.check_cache
-    settings_updated_on = Setting.maximum(:updated_on)
-    if settings_updated_on && @cached_cleared_on <= settings_updated_on
-      clear_cache
-    end
-  end
-
-  # Clears the settings cache
-  def self.clear_cache
-    @cached_settings.clear
-    @cached_cleared_on = Time.now
-    logger.info "Settings cache cleared." if logger
-  end
-
-private
-  # Returns the Setting instance for the setting named name
-  # (record found in database or new record with default value)
-  def self.find_or_default(name)
-    name = name.to_s
-    raise "There's no setting named #{name}" unless @@available_settings.has_key?(name)
-    setting = find_by_name(name)
-    unless setting
-      setting = new(:name => name)
-      setting.value = @@available_settings[name]['default']
-    end
-    setting
-  end
-end
--- a/.svn/pristine/ba/bad7988dc8d7b98fa49d927fe46638bead208bbb.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module MailHandlerHelper
-end
--- a/.svn/pristine/bb/bb61dbaf687876f4655cd52d6481c38fded7a21c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/* Redmine - project management software
-   Copyright (C) 2006-2013  Jean-Philippe Lang */
-
-function addFile(inputEl, file, eagerUpload) {
-
-  if ($('#attachments_fields').children().length < 10) {
-
-    var attachmentId = addFile.nextAttachmentId++;
-
-    var fileSpan = $('<span>', { id: 'attachments_' + attachmentId });
-
-    fileSpan.append(
-        $('<input>', { type: 'text', 'class': 'filename readonly', name: 'attachments[' + attachmentId + '][filename]', readonly: 'readonly'} ).val(file.name),
-        $('<input>', { type: 'text', 'class': 'description', name: 'attachments[' + attachmentId + '][description]', maxlength: 255, placeholder: $(inputEl).data('description-placeholder') } ).toggle(!eagerUpload),
-        $('<a>&nbsp</a>').attr({ href: "#", 'class': 'remove-upload' }).click(removeFile).toggle(!eagerUpload)
-    ).appendTo('#attachments_fields');
-
-    if(eagerUpload) {
-      ajaxUpload(file, attachmentId, fileSpan, inputEl);
-    }
-
-    return attachmentId;
-  }
-  return null;
-}
-
-addFile.nextAttachmentId = 1;
-
-function ajaxUpload(file, attachmentId, fileSpan, inputEl) {
-
-  function onLoadstart(e) {
-    fileSpan.removeClass('ajax-waiting');
-    fileSpan.addClass('ajax-loading');
-    $('input:submit', $(this).parents('form')).attr('disabled', 'disabled');
-  }
-
-  function onProgress(e) {
-    if(e.lengthComputable) {
-      this.progressbar( 'value', e.loaded * 100 / e.total );
-    }
-  }
-
-  function actualUpload(file, attachmentId, fileSpan, inputEl) {
-
-    ajaxUpload.uploading++;
-
-    uploadBlob(file, $(inputEl).data('upload-path'), attachmentId, {
-        loadstartEventHandler: onLoadstart.bind(progressSpan),
-        progressEventHandler: onProgress.bind(progressSpan)
-      })
-      .done(function(result) {
-        progressSpan.progressbar( 'value', 100 ).remove();
-        fileSpan.find('input.description, a').css('display', 'inline-block');
-      })
-      .fail(function(result) {
-        progressSpan.text(result.statusText);
-      }).always(function() {
-        ajaxUpload.uploading--;
-        fileSpan.removeClass('ajax-loading');
-        var form = fileSpan.parents('form');
-        if (form.queue('upload').length == 0 && ajaxUpload.uploading == 0) {
-          $('input:submit', form).removeAttr('disabled');
-        }
-        form.dequeue('upload');
-      });
-  }
-
-  var progressSpan = $('<div>').insertAfter(fileSpan.find('input.filename'));
-  progressSpan.progressbar();
-  fileSpan.addClass('ajax-waiting');
-
-  var maxSyncUpload = $(inputEl).data('max-concurrent-uploads');
-
-  if(maxSyncUpload == null || maxSyncUpload <= 0 || ajaxUpload.uploading < maxSyncUpload)
-    actualUpload(file, attachmentId, fileSpan, inputEl);
-  else
-    $(inputEl).parents('form').queue('upload', actualUpload.bind(this, file, attachmentId, fileSpan, inputEl));
-}
-
-ajaxUpload.uploading = 0;
-
-function removeFile() {
-  $(this).parent('span').remove();
-  return false;
-}
-
-function uploadBlob(blob, uploadUrl, attachmentId, options) {
-
-  var actualOptions = $.extend({
-    loadstartEventHandler: $.noop,
-    progressEventHandler: $.noop
-  }, options);
-
-  uploadUrl = uploadUrl + '?attachment_id=' + attachmentId;
-  if (blob instanceof window.File) {
-    uploadUrl += '&filename=' + encodeURIComponent(blob.name);
-  }
-
-  return $.ajax(uploadUrl, {
-    type: 'POST',
-    contentType: 'application/octet-stream',
-    beforeSend: function(jqXhr) {
-      jqXhr.setRequestHeader('Accept', 'application/js');
-    },
-    xhr: function() {
-      var xhr = $.ajaxSettings.xhr();
-      xhr.upload.onloadstart = actualOptions.loadstartEventHandler;
-      xhr.upload.onprogress = actualOptions.progressEventHandler;
-      return xhr;
-    },
-    data: blob,
-    cache: false,
-    processData: false
-  });
-}
-
-function addInputFiles(inputEl) {
-  var clearedFileInput = $(inputEl).clone().val('');
-
-  if (inputEl.files) {
-    // upload files using ajax
-    uploadAndAttachFiles(inputEl.files, inputEl);
-    $(inputEl).remove();
-  } else {
-    // browser not supporting the file API, upload on form submission
-    var attachmentId;
-    var aFilename = inputEl.value.split(/\/|\\/);
-    attachmentId = addFile(inputEl, { name: aFilename[ aFilename.length - 1 ] }, false);
-    if (attachmentId) {
-      $(inputEl).attr({ name: 'attachments[' + attachmentId + '][file]', style: 'display:none;' }).appendTo('#attachments_' + attachmentId);
-    }
-  }
-
-  clearedFileInput.insertAfter('#attachments_fields');
-}
-
-function uploadAndAttachFiles(files, inputEl) {
-
-  var maxFileSize = $(inputEl).data('max-file-size');
-  var maxFileSizeExceeded = $(inputEl).data('max-file-size-message');
-
-  var sizeExceeded = false;
-  $.each(files, function() {
-    if (this.size && maxFileSize != null && this.size > parseInt(maxFileSize)) {sizeExceeded=true;}
-  });
-  if (sizeExceeded) {
-    window.alert(maxFileSizeExceeded);
-  } else {
-    $.each(files, function() {addFile(inputEl, this, true);});
-  }
-}
-
-function handleFileDropEvent(e) {
-
-  $(this).removeClass('fileover');
-  blockEventPropagation(e);
-
-  if ($.inArray('Files', e.dataTransfer.types) > -1) {
-    uploadAndAttachFiles(e.dataTransfer.files, $('input:file.file_selector'));
-  }
-}
-
-function dragOverHandler(e) {
-  $(this).addClass('fileover');
-  blockEventPropagation(e);
-}
-
-function dragOutHandler(e) {
-  $(this).removeClass('fileover');
-  blockEventPropagation(e);
-}
-
-function setupFileDrop() {
-  if (window.File && window.FileList && window.ProgressEvent && window.FormData) {
-
-    $.event.fixHooks.drop = { props: [ 'dataTransfer' ] };
-
-    $('form div.box').has('input:file').each(function() {
-      $(this).on({
-          dragover: dragOverHandler,
-          dragleave: dragOutHandler,
-          drop: handleFileDropEvent
-      });
-    });
-  }
-}
-
-$(document).ready(setupFileDrop);
--- a/.svn/pristine/bd/bd14f74ff8fe3ceb6d84b4dbead570fb4b8e960a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-
-class FilesystemAdapterTest < ActiveSupport::TestCase
-  REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s
-
-  if File.directory?(REPOSITORY_PATH)
-    def setup
-      @adapter = Redmine::Scm::Adapters::FilesystemAdapter.new(REPOSITORY_PATH)
-    end
-
-    def test_entries
-      assert_equal 3, @adapter.entries.size
-      assert_equal ["dir", "japanese", "test"], @adapter.entries.collect(&:name)
-      assert_equal ["dir", "japanese", "test"], @adapter.entries(nil).collect(&:name)
-      assert_equal ["dir", "japanese", "test"], @adapter.entries("/").collect(&:name)
-      ["dir", "/dir", "/dir/", "dir/"].each do |path|
-        assert_equal ["subdir", "dirfile"], @adapter.entries(path).collect(&:name)
-      end
-      # If y try to use "..", the path is ignored
-      ["/../","dir/../", "..", "../", "/..", "dir/.."].each do |path|
-        assert_equal ["dir", "japanese", "test"], @adapter.entries(path).collect(&:name),
-             ".. must be ignored in path argument"
-      end
-    end
-
-    def test_cat
-      assert_equal "TEST CAT\n", @adapter.cat("test")
-      assert_equal "TEST CAT\n", @adapter.cat("/test")
-      # Revision number is ignored
-      assert_equal "TEST CAT\n", @adapter.cat("/test", 1)
-    end
-
-    def test_path_encoding_default_utf8
-      adpt1 = Redmine::Scm::Adapters::FilesystemAdapter.new(
-                                  REPOSITORY_PATH
-                                )
-      assert_equal "UTF-8", adpt1.path_encoding
-      adpt2 = Redmine::Scm::Adapters::FilesystemAdapter.new(
-                                  REPOSITORY_PATH,
-                                  nil,
-                                  nil,
-                                  nil,
-                                  ""
-                                )
-      assert_equal "UTF-8", adpt2.path_encoding
-    end
-  else
-    puts "Filesystem test repository NOT FOUND. Skipping unit tests !!! See doc/RUNNING_TESTS."
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/bd/bd8a41367104b158b51a98ef53d62e3672373a68.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WorkflowTest < ActiveSupport::TestCase
-  fixtures :roles, :trackers, :issue_statuses
-
-  def test_copy
-    WorkflowTransition.delete_all
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :new_status_id => 2)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :new_status_id => 3, :assignee => true)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :new_status_id => 4, :author => true)
-
-    assert_difference 'WorkflowTransition.count', 3 do
-      WorkflowTransition.copy(Tracker.find(2), Role.find(1), Tracker.find(3), Role.find(2))
-    end
-
-    assert WorkflowTransition.where(:role_id => 2, :tracker_id => 3, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false).first
-    assert WorkflowTransition.where(:role_id => 2, :tracker_id => 3, :old_status_id => 1, :new_status_id => 3, :author => false, :assignee => true).first
-    assert WorkflowTransition.where(:role_id => 2, :tracker_id => 3, :old_status_id => 1, :new_status_id => 4, :author => true, :assignee => false).first
-  end
-
-  def test_workflow_permission_should_validate_rule
-    wp = WorkflowPermission.new(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :field_name => 'due_date')
-    assert !wp.save
-
-    wp.rule = 'foo'
-    assert !wp.save
-
-    wp.rule = 'required'
-    assert wp.save
-
-    wp.rule = 'readonly'
-    assert wp.save
-  end
-
-  def test_workflow_permission_should_validate_field_name
-    wp = WorkflowPermission.new(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :rule => 'required')
-    assert !wp.save
-
-    wp.field_name = 'foo'
-    assert !wp.save
-
-    wp.field_name = 'due_date'
-    assert wp.save
-
-    wp.field_name = '1'
-    assert wp.save
-  end
-end
--- a/.svn/pristine/be/be8651657bb8574f8d5bb330df4828685014b41d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Platform
-    class << self
-      def mswin?
-        (RUBY_PLATFORM =~ /(:?mswin|mingw)/) ||
-           (RUBY_PLATFORM == 'java' && (ENV['OS'] || ENV['os']) =~ /windows/i)
-      end
-    end
-  end
-end
--- a/.svn/pristine/bf/bfe1171346960c651d4d5f6f55c3e48b3102dcc1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::WikiFormattingTest < ActiveSupport::TestCase
-  fixtures :issues
-
-  def test_textile_formatter
-    assert_equal Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting.formatter_for('textile')
-    assert_equal Redmine::WikiFormatting::Textile::Helper, Redmine::WikiFormatting.helper_for('textile')
-  end
-
-  def test_null_formatter
-    assert_equal Redmine::WikiFormatting::NullFormatter::Formatter, Redmine::WikiFormatting.formatter_for('')
-    assert_equal Redmine::WikiFormatting::NullFormatter::Helper, Redmine::WikiFormatting.helper_for('')
-  end
-
-  def test_should_link_urls_and_email_addresses
-    raw = <<-DIFF
-This is a sample *text* with a link: http://www.redmine.org
-and an email address foo@example.net
-DIFF
-
-    expected = <<-EXPECTED
-<p>This is a sample *text* with a link: <a class="external" href="http://www.redmine.org">http://www.redmine.org</a><br />
-and an email address <a class="email" href="mailto:foo@example.net">foo@example.net</a></p>
-EXPECTED
-
-    assert_equal expected.gsub(%r{[\r\n\t]}, ''), Redmine::WikiFormatting::NullFormatter::Formatter.new(raw).to_html.gsub(%r{[\r\n\t]}, '')
-  end
-
-  def test_supports_section_edit
-    with_settings :text_formatting => 'textile' do
-      assert_equal true, Redmine::WikiFormatting.supports_section_edit?
-    end
-    
-    with_settings :text_formatting => '' do
-      assert_equal false, Redmine::WikiFormatting.supports_section_edit?
-    end
-  end
-
-  def test_cache_key_for_saved_object_should_no_be_nil
-    assert_not_nil Redmine::WikiFormatting.cache_key_for('textile', 'Text', Issue.find(1), :description)
-  end
-end
--- a/.svn/pristine/c1/c13203b8c9801034c2e99e8551c74a2c3c923252.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class AuthSourcesController < ApplicationController
-  layout 'admin'
-  menu_item :ldap_authentication
-
-  before_filter :require_admin
-  before_filter :find_auth_source, :only => [:edit, :update, :test_connection, :destroy]
-
-  def index
-    @auth_source_pages, @auth_sources = paginate AuthSource, :per_page => 25
-  end
-
-  def new
-    klass_name = params[:type] || 'AuthSourceLdap'
-    @auth_source = AuthSource.new_subclass_instance(klass_name, params[:auth_source])
-    render_404 unless @auth_source
-  end
-
-  def create
-    @auth_source = AuthSource.new_subclass_instance(params[:type], params[:auth_source])
-    if @auth_source.save
-      flash[:notice] = l(:notice_successful_create)
-      redirect_to auth_sources_path
-    else
-      render :action => 'new'
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    if @auth_source.update_attributes(params[:auth_source])
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to auth_sources_path
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def test_connection
-    begin
-      @auth_source.test_connection
-      flash[:notice] = l(:notice_successful_connection)
-    rescue Exception => e
-      flash[:error] = l(:error_unable_to_connect, e.message)
-    end
-    redirect_to auth_sources_path
-  end
-
-  def destroy
-    unless @auth_source.users.exists?
-      @auth_source.destroy
-      flash[:notice] = l(:notice_successful_delete)
-    end
-    redirect_to auth_sources_path
-  end
-
-  def autocomplete_for_new_user
-    results = AuthSource.search(params[:term])
-
-    render :json => results.map {|result| {
-      'value' => result[:login],
-      'label' => "#{result[:login]} (#{result[:firstname]} #{result[:lastname]})",
-      'login' => result[:login].to_s,
-      'firstname' => result[:firstname].to_s,
-      'lastname' => result[:lastname].to_s,
-      'mail' => result[:mail].to_s,
-      'auth_source_id' => result[:auth_source_id].to_s
-    }}
-  end
-
-  private
-
-  def find_auth_source
-    @auth_source = AuthSource.find(params[:id])
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/c2/c2efec7daff7304595ce1ecc0edb5b5532a60347.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module BoardsHelper
-  def board_breadcrumb(item)
-    board = item.is_a?(Message) ? item.board : item
-    links = [link_to(l(:label_board_plural), project_boards_path(item.project))]
-    boards = board.ancestors.reverse
-    if item.is_a?(Message)
-      boards << board
-    end
-    links += boards.map {|ancestor| link_to(h(ancestor.name), project_board_path(ancestor.project, ancestor))}
-    breadcrumb links
-  end
-
-  def boards_options_for_select(boards)
-    options = []
-    Board.board_tree(boards) do |board, level|
-      label = (level > 0 ? '&nbsp;' * 2 * level + '&#187; ' : '').html_safe
-      label << board.name
-      options << [label, board.id]
-    end
-    options
-  end
-end
--- a/.svn/pristine/c3/c33e922cc9977630c5c48bda98d379ff7df6c700.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,937 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ProjectTest < ActiveSupport::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :journals, :journal_details,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :custom_fields,
-           :custom_fields_projects,
-           :custom_fields_trackers,
-           :custom_values,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :versions,
-           :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
-           :groups_users,
-           :boards, :messages,
-           :repositories,
-           :news, :comments,
-           :documents
-
-  def setup
-    @ecookbook = Project.find(1)
-    @ecookbook_sub1 = Project.find(3)
-    set_tmp_attachments_directory
-    User.current = nil
-  end
-
-  def test_truth
-    assert_kind_of Project, @ecookbook
-    assert_equal "eCookbook", @ecookbook.name
-  end
-
-  def test_default_attributes
-    with_settings :default_projects_public => '1' do
-      assert_equal true, Project.new.is_public
-      assert_equal false, Project.new(:is_public => false).is_public
-    end
-
-    with_settings :default_projects_public => '0' do
-      assert_equal false, Project.new.is_public
-      assert_equal true, Project.new(:is_public => true).is_public
-    end
-
-    with_settings :sequential_project_identifiers => '1' do
-      assert !Project.new.identifier.blank?
-      assert Project.new(:identifier => '').identifier.blank?
-    end
-
-    with_settings :sequential_project_identifiers => '0' do
-      assert Project.new.identifier.blank?
-      assert !Project.new(:identifier => 'test').blank?
-    end
-
-    with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
-      assert_equal ['issue_tracking', 'repository'], Project.new.enabled_module_names
-    end
-  end
-
-  def test_default_trackers_should_match_default_tracker_ids_setting
-    with_settings :default_projects_tracker_ids => ['1', '3'] do
-      assert_equal Tracker.find(1, 3).sort, Project.new.trackers.sort
-    end
-  end
-
-  def test_default_trackers_should_be_all_trackers_with_blank_setting
-    with_settings :default_projects_tracker_ids => nil do
-      assert_equal Tracker.all.sort, Project.new.trackers.sort
-    end
-  end
-
-  def test_default_trackers_should_be_empty_with_empty_setting
-    with_settings :default_projects_tracker_ids => [] do
-      assert_equal [], Project.new.trackers
-    end
-  end
-
-  def test_default_trackers_should_not_replace_initialized_trackers
-    with_settings :default_projects_tracker_ids => ['1', '3'] do
-      assert_equal Tracker.find(1, 2).sort, Project.new(:tracker_ids => [1, 2]).trackers.sort
-    end
-  end
-
-  def test_update
-    assert_equal "eCookbook", @ecookbook.name
-    @ecookbook.name = "eCook"
-    assert @ecookbook.save, @ecookbook.errors.full_messages.join("; ")
-    @ecookbook.reload
-    assert_equal "eCook", @ecookbook.name
-  end
-
-  def test_validate_identifier
-    to_test = {"abc" => true,
-               "ab12" => true,
-               "ab-12" => true,
-               "ab_12" => true,
-               "12" => false,
-               "new" => false}
-
-    to_test.each do |identifier, valid|
-      p = Project.new
-      p.identifier = identifier
-      p.valid?
-      if valid
-        assert p.errors['identifier'].blank?, "identifier #{identifier} was not valid"
-      else
-        assert p.errors['identifier'].present?, "identifier #{identifier} was valid"
-      end
-    end
-  end
-
-  def test_identifier_should_not_be_frozen_for_a_new_project
-    assert_equal false, Project.new.identifier_frozen?
-  end
-
-  def test_identifier_should_not_be_frozen_for_a_saved_project_with_blank_identifier
-    Project.update_all(["identifier = ''"], "id = 1")
-
-    assert_equal false, Project.find(1).identifier_frozen?
-  end
-
-  def test_identifier_should_be_frozen_for_a_saved_project_with_valid_identifier
-    assert_equal true, Project.find(1).identifier_frozen?
-  end
-
-  def test_members_should_be_active_users
-    Project.all.each do |project|
-      assert_nil project.members.detect {|m| !(m.user.is_a?(User) && m.user.active?) }
-    end
-  end
-
-  def test_users_should_be_active_users
-    Project.all.each do |project|
-      assert_nil project.users.detect {|u| !(u.is_a?(User) && u.active?) }
-    end
-  end
-
-  def test_open_scope_on_issues_association
-    assert_kind_of Issue, Project.find(1).issues.open.first
-  end
-
-  def test_archive
-    user = @ecookbook.members.first.user
-    @ecookbook.archive
-    @ecookbook.reload
-
-    assert !@ecookbook.active?
-    assert @ecookbook.archived?
-    assert !user.projects.include?(@ecookbook)
-    # Subproject are also archived
-    assert !@ecookbook.children.empty?
-    assert @ecookbook.descendants.active.empty?
-  end
-
-  def test_archive_should_fail_if_versions_are_used_by_non_descendant_projects
-    # Assign an issue of a project to a version of a child project
-    Issue.find(4).update_attribute :fixed_version_id, 4
-
-    assert_no_difference "Project.where(:status => Project::STATUS_ARCHIVED).count" do
-      assert_equal false, @ecookbook.archive
-    end
-    @ecookbook.reload
-    assert @ecookbook.active?
-  end
-
-  def test_unarchive
-    user = @ecookbook.members.first.user
-    @ecookbook.archive
-    # A subproject of an archived project can not be unarchived
-    assert !@ecookbook_sub1.unarchive
-
-    # Unarchive project
-    assert @ecookbook.unarchive
-    @ecookbook.reload
-    assert @ecookbook.active?
-    assert !@ecookbook.archived?
-    assert user.projects.include?(@ecookbook)
-    # Subproject can now be unarchived
-    @ecookbook_sub1.reload
-    assert @ecookbook_sub1.unarchive
-  end
-
-  def test_destroy
-    # 2 active members
-    assert_equal 2, @ecookbook.members.size
-    # and 1 is locked
-    assert_equal 3, Member.where('project_id = ?', @ecookbook.id).all.size
-    # some boards
-    assert @ecookbook.boards.any?
-
-    @ecookbook.destroy
-    # make sure that the project non longer exists
-    assert_raise(ActiveRecord::RecordNotFound) { Project.find(@ecookbook.id) }
-    # make sure related data was removed
-    assert_nil Member.where(:project_id => @ecookbook.id).first
-    assert_nil Board.where(:project_id => @ecookbook.id).first
-    assert_nil Issue.where(:project_id => @ecookbook.id).first
-  end
-
-  def test_destroy_should_destroy_subtasks
-    issues = (0..2).to_a.map {Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :subject => 'test')}
-    issues[0].update_attribute :parent_issue_id, issues[1].id
-    issues[2].update_attribute :parent_issue_id, issues[1].id
-    assert_equal 2, issues[1].children.count
-
-    assert_nothing_raised do
-      Project.find(1).destroy
-    end
-    assert Issue.find_all_by_id(issues.map(&:id)).empty?
-  end
-
-  def test_destroying_root_projects_should_clear_data
-    Project.roots.each do |root|
-      root.destroy
-    end
-
-    assert_equal 0, Project.count, "Projects were not deleted: #{Project.all.inspect}"
-    assert_equal 0, Member.count, "Members were not deleted: #{Member.all.inspect}"
-    assert_equal 0, MemberRole.count
-    assert_equal 0, Issue.count
-    assert_equal 0, Journal.count
-    assert_equal 0, JournalDetail.count
-    assert_equal 0, Attachment.count, "Attachments were not deleted: #{Attachment.all.inspect}"
-    assert_equal 0, EnabledModule.count
-    assert_equal 0, IssueCategory.count
-    assert_equal 0, IssueRelation.count
-    assert_equal 0, Board.count
-    assert_equal 0, Message.count
-    assert_equal 0, News.count
-    assert_equal 0, Query.where("project_id IS NOT NULL").count
-    assert_equal 0, Repository.count
-    assert_equal 0, Changeset.count
-    assert_equal 0, Change.count
-    assert_equal 0, Comment.count
-    assert_equal 0, TimeEntry.count
-    assert_equal 0, Version.count
-    assert_equal 0, Watcher.count
-    assert_equal 0, Wiki.count
-    assert_equal 0, WikiPage.count
-    assert_equal 0, WikiContent.count
-    assert_equal 0, WikiContent::Version.count
-    assert_equal 0, Project.connection.select_all("SELECT * FROM projects_trackers").size
-    assert_equal 0, Project.connection.select_all("SELECT * FROM custom_fields_projects").size
-    assert_equal 0, CustomValue.where(:customized_type => ['Project', 'Issue', 'TimeEntry', 'Version']).count
-  end
-
-  def test_move_an_orphan_project_to_a_root_project
-    sub = Project.find(2)
-    sub.set_parent! @ecookbook
-    assert_equal @ecookbook.id, sub.parent.id
-    @ecookbook.reload
-    assert_equal 4, @ecookbook.children.size
-  end
-
-  def test_move_an_orphan_project_to_a_subproject
-    sub = Project.find(2)
-    assert sub.set_parent!(@ecookbook_sub1)
-  end
-
-  def test_move_a_root_project_to_a_project
-    sub = @ecookbook
-    assert sub.set_parent!(Project.find(2))
-  end
-
-  def test_should_not_move_a_project_to_its_children
-    sub = @ecookbook
-    assert !(sub.set_parent!(Project.find(3)))
-  end
-
-  def test_set_parent_should_add_roots_in_alphabetical_order
-    ProjectCustomField.delete_all
-    Project.delete_all
-    Project.create!(:name => 'Project C', :identifier => 'project-c').set_parent!(nil)
-    Project.create!(:name => 'Project B', :identifier => 'project-b').set_parent!(nil)
-    Project.create!(:name => 'Project D', :identifier => 'project-d').set_parent!(nil)
-    Project.create!(:name => 'Project A', :identifier => 'project-a').set_parent!(nil)
-
-    assert_equal 4, Project.count
-    assert_equal Project.all.sort_by(&:name), Project.all.sort_by(&:lft)
-  end
-
-  def test_set_parent_should_add_children_in_alphabetical_order
-    ProjectCustomField.delete_all
-    parent = Project.create!(:name => 'Parent', :identifier => 'parent')
-    Project.create!(:name => 'Project C', :identifier => 'project-c').set_parent!(parent)
-    Project.create!(:name => 'Project B', :identifier => 'project-b').set_parent!(parent)
-    Project.create!(:name => 'Project D', :identifier => 'project-d').set_parent!(parent)
-    Project.create!(:name => 'Project A', :identifier => 'project-a').set_parent!(parent)
-
-    parent.reload
-    assert_equal 4, parent.children.size
-    assert_equal parent.children.all.sort_by(&:name), parent.children.all
-  end
-
-  def test_set_parent_should_update_issue_fixed_version_associations_when_a_fixed_version_is_moved_out_of_the_hierarchy
-    # Parent issue with a hierarchy project's fixed version
-    parent_issue = Issue.find(1)
-    parent_issue.update_attribute(:fixed_version_id, 4)
-    parent_issue.reload
-    assert_equal 4, parent_issue.fixed_version_id
-
-    # Should keep fixed versions for the issues
-    issue_with_local_fixed_version = Issue.find(5)
-    issue_with_local_fixed_version.update_attribute(:fixed_version_id, 4)
-    issue_with_local_fixed_version.reload
-    assert_equal 4, issue_with_local_fixed_version.fixed_version_id
-
-    # Local issue with hierarchy fixed_version
-    issue_with_hierarchy_fixed_version = Issue.find(13)
-    issue_with_hierarchy_fixed_version.update_attribute(:fixed_version_id, 6)
-    issue_with_hierarchy_fixed_version.reload
-    assert_equal 6, issue_with_hierarchy_fixed_version.fixed_version_id
-
-    # Move project out of the issue's hierarchy
-    moved_project = Project.find(3)
-    moved_project.set_parent!(Project.find(2))
-    parent_issue.reload
-    issue_with_local_fixed_version.reload
-    issue_with_hierarchy_fixed_version.reload
-
-    assert_equal 4, issue_with_local_fixed_version.fixed_version_id, "Fixed version was not keep on an issue local to the moved project"
-    assert_equal nil, issue_with_hierarchy_fixed_version.fixed_version_id, "Fixed version is still set after moving the Project out of the hierarchy where the version is defined in"
-    assert_equal nil, parent_issue.fixed_version_id, "Fixed version is still set after moving the Version out of the hierarchy for the issue."
-  end
-
-  def test_parent
-    p = Project.find(6).parent
-    assert p.is_a?(Project)
-    assert_equal 5, p.id
-  end
-
-  def test_ancestors
-    a = Project.find(6).ancestors
-    assert a.first.is_a?(Project)
-    assert_equal [1, 5], a.collect(&:id)
-  end
-
-  def test_root
-    r = Project.find(6).root
-    assert r.is_a?(Project)
-    assert_equal 1, r.id
-  end
-
-  def test_children
-    c = Project.find(1).children
-    assert c.first.is_a?(Project)
-    assert_equal [5, 3, 4], c.collect(&:id)
-  end
-
-  def test_descendants
-    d = Project.find(1).descendants
-    assert d.first.is_a?(Project)
-    assert_equal [5, 6, 3, 4], d.collect(&:id)
-  end
-
-  def test_allowed_parents_should_be_empty_for_non_member_user
-    Role.non_member.add_permission!(:add_project)
-    user = User.find(9)
-    assert user.memberships.empty?
-    User.current = user
-    assert Project.new.allowed_parents.compact.empty?
-  end
-
-  def test_allowed_parents_with_add_subprojects_permission
-    Role.find(1).remove_permission!(:add_project)
-    Role.find(1).add_permission!(:add_subprojects)
-    User.current = User.find(2)
-    # new project
-    assert !Project.new.allowed_parents.include?(nil)
-    assert Project.new.allowed_parents.include?(Project.find(1))
-    # existing root project
-    assert Project.find(1).allowed_parents.include?(nil)
-    # existing child
-    assert Project.find(3).allowed_parents.include?(Project.find(1))
-    assert !Project.find(3).allowed_parents.include?(nil)
-  end
-
-  def test_allowed_parents_with_add_project_permission
-    Role.find(1).add_permission!(:add_project)
-    Role.find(1).remove_permission!(:add_subprojects)
-    User.current = User.find(2)
-    # new project
-    assert Project.new.allowed_parents.include?(nil)
-    assert !Project.new.allowed_parents.include?(Project.find(1))
-    # existing root project
-    assert Project.find(1).allowed_parents.include?(nil)
-    # existing child
-    assert Project.find(3).allowed_parents.include?(Project.find(1))
-    assert Project.find(3).allowed_parents.include?(nil)
-  end
-
-  def test_allowed_parents_with_add_project_and_subprojects_permission
-    Role.find(1).add_permission!(:add_project)
-    Role.find(1).add_permission!(:add_subprojects)
-    User.current = User.find(2)
-    # new project
-    assert Project.new.allowed_parents.include?(nil)
-    assert Project.new.allowed_parents.include?(Project.find(1))
-    # existing root project
-    assert Project.find(1).allowed_parents.include?(nil)
-    # existing child
-    assert Project.find(3).allowed_parents.include?(Project.find(1))
-    assert Project.find(3).allowed_parents.include?(nil)
-  end
-
-  def test_users_by_role
-    users_by_role = Project.find(1).users_by_role
-    assert_kind_of Hash, users_by_role
-    role = Role.find(1)
-    assert_kind_of Array, users_by_role[role]
-    assert users_by_role[role].include?(User.find(2))
-  end
-
-  def test_rolled_up_trackers
-    parent = Project.find(1)
-    parent.trackers = Tracker.find([1,2])
-    child = parent.children.find(3)
-
-    assert_equal [1, 2], parent.tracker_ids
-    assert_equal [2, 3], child.trackers.collect(&:id)
-
-    assert_kind_of Tracker, parent.rolled_up_trackers.first
-    assert_equal Tracker.find(1), parent.rolled_up_trackers.first
-
-    assert_equal [1, 2, 3], parent.rolled_up_trackers.collect(&:id)
-    assert_equal [2, 3], child.rolled_up_trackers.collect(&:id)
-  end
-
-  def test_rolled_up_trackers_should_ignore_archived_subprojects
-    parent = Project.find(1)
-    parent.trackers = Tracker.find([1,2])
-    child = parent.children.find(3)
-    child.trackers = Tracker.find([1,3])
-    parent.children.each(&:archive)
-
-    assert_equal [1,2], parent.rolled_up_trackers.collect(&:id)
-  end
-
-  test "#rolled_up_trackers should ignore projects with issue_tracking module disabled" do
-    parent = Project.generate!
-    parent.trackers = Tracker.find([1, 2])
-    child = Project.generate_with_parent!(parent)
-    child.trackers = Tracker.find([2, 3])
-
-    assert_equal [1, 2, 3], parent.rolled_up_trackers.collect(&:id).sort
-
-    assert child.disable_module!(:issue_tracking)
-    parent.reload
-    assert_equal [1, 2], parent.rolled_up_trackers.collect(&:id).sort
-  end
-
-  test "#rolled_up_versions should include the versions for the current project" do
-    project = Project.generate!
-    parent_version_1 = Version.generate!(:project => project)
-    parent_version_2 = Version.generate!(:project => project)
-    assert_same_elements [parent_version_1, parent_version_2], project.rolled_up_versions
-  end
-
-  test "#rolled_up_versions should include versions for a subproject" do
-    project = Project.generate!
-    parent_version_1 = Version.generate!(:project => project)
-    parent_version_2 = Version.generate!(:project => project)
-    subproject = Project.generate_with_parent!(project)
-    subproject_version = Version.generate!(:project => subproject)
-
-    assert_same_elements [
-                          parent_version_1,
-                          parent_version_2,
-                          subproject_version
-                         ], project.rolled_up_versions
-  end
-
-  test "#rolled_up_versions should include versions for a sub-subproject" do
-    project = Project.generate!
-    parent_version_1 = Version.generate!(:project => project)
-    parent_version_2 = Version.generate!(:project => project)
-    subproject = Project.generate_with_parent!(project)
-    sub_subproject = Project.generate_with_parent!(subproject)
-    sub_subproject_version = Version.generate!(:project => sub_subproject)
-    project.reload
-
-    assert_same_elements [
-                          parent_version_1,
-                          parent_version_2,
-                          sub_subproject_version
-                         ], project.rolled_up_versions
-  end
-
-  test "#rolled_up_versions should only check active projects" do
-    project = Project.generate!
-    parent_version_1 = Version.generate!(:project => project)
-    parent_version_2 = Version.generate!(:project => project)
-    subproject = Project.generate_with_parent!(project)
-    subproject_version = Version.generate!(:project => subproject)
-    assert subproject.archive
-    project.reload
-
-    assert !subproject.active?
-    assert_same_elements [parent_version_1, parent_version_2], project.rolled_up_versions
-  end
-
-  def test_shared_versions_none_sharing
-    p = Project.find(5)
-    v = Version.create!(:name => 'none_sharing', :project => p, :sharing => 'none')
-    assert p.shared_versions.include?(v)
-    assert !p.children.first.shared_versions.include?(v)
-    assert !p.root.shared_versions.include?(v)
-    assert !p.siblings.first.shared_versions.include?(v)
-    assert !p.root.siblings.first.shared_versions.include?(v)
-  end
-
-  def test_shared_versions_descendants_sharing
-    p = Project.find(5)
-    v = Version.create!(:name => 'descendants_sharing', :project => p, :sharing => 'descendants')
-    assert p.shared_versions.include?(v)
-    assert p.children.first.shared_versions.include?(v)
-    assert !p.root.shared_versions.include?(v)
-    assert !p.siblings.first.shared_versions.include?(v)
-    assert !p.root.siblings.first.shared_versions.include?(v)
-  end
-
-  def test_shared_versions_hierarchy_sharing
-    p = Project.find(5)
-    v = Version.create!(:name => 'hierarchy_sharing', :project => p, :sharing => 'hierarchy')
-    assert p.shared_versions.include?(v)
-    assert p.children.first.shared_versions.include?(v)
-    assert p.root.shared_versions.include?(v)
-    assert !p.siblings.first.shared_versions.include?(v)
-    assert !p.root.siblings.first.shared_versions.include?(v)
-  end
-
-  def test_shared_versions_tree_sharing
-    p = Project.find(5)
-    v = Version.create!(:name => 'tree_sharing', :project => p, :sharing => 'tree')
-    assert p.shared_versions.include?(v)
-    assert p.children.first.shared_versions.include?(v)
-    assert p.root.shared_versions.include?(v)
-    assert p.siblings.first.shared_versions.include?(v)
-    assert !p.root.siblings.first.shared_versions.include?(v)
-  end
-
-  def test_shared_versions_system_sharing
-    p = Project.find(5)
-    v = Version.create!(:name => 'system_sharing', :project => p, :sharing => 'system')
-    assert p.shared_versions.include?(v)
-    assert p.children.first.shared_versions.include?(v)
-    assert p.root.shared_versions.include?(v)
-    assert p.siblings.first.shared_versions.include?(v)
-    assert p.root.siblings.first.shared_versions.include?(v)
-  end
-
-  def test_shared_versions
-    parent = Project.find(1)
-    child = parent.children.find(3)
-    private_child = parent.children.find(5)
-
-    assert_equal [1,2,3], parent.version_ids.sort
-    assert_equal [4], child.version_ids
-    assert_equal [6], private_child.version_ids
-    assert_equal [7], Version.find_all_by_sharing('system').collect(&:id)
-
-    assert_equal 6, parent.shared_versions.size
-    parent.shared_versions.each do |version|
-      assert_kind_of Version, version
-    end
-
-    assert_equal [1,2,3,4,6,7], parent.shared_versions.collect(&:id).sort
-  end
-
-  def test_shared_versions_should_ignore_archived_subprojects
-    parent = Project.find(1)
-    child = parent.children.find(3)
-    child.archive
-    parent.reload
-
-    assert_equal [1,2,3], parent.version_ids.sort
-    assert_equal [4], child.version_ids
-    assert !parent.shared_versions.collect(&:id).include?(4)
-  end
-
-  def test_shared_versions_visible_to_user
-    user = User.find(3)
-    parent = Project.find(1)
-    child = parent.children.find(5)
-
-    assert_equal [1,2,3], parent.version_ids.sort
-    assert_equal [6], child.version_ids
-
-    versions = parent.shared_versions.visible(user)
-
-    assert_equal 4, versions.size
-    versions.each do |version|
-      assert_kind_of Version, version
-    end
-
-    assert !versions.collect(&:id).include?(6)
-  end
-
-  def test_shared_versions_for_new_project_should_include_system_shared_versions
-    p = Project.find(5)
-    v = Version.create!(:name => 'system_sharing', :project => p, :sharing => 'system')
-
-    assert_include v, Project.new.shared_versions
-  end
-
-  def test_next_identifier
-    ProjectCustomField.delete_all
-    Project.create!(:name => 'last', :identifier => 'p2008040')
-    assert_equal 'p2008041', Project.next_identifier
-  end
-
-  def test_next_identifier_first_project
-    Project.delete_all
-    assert_nil Project.next_identifier
-  end
-
-  def test_enabled_module_names
-    with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
-      project = Project.new
-
-      project.enabled_module_names = %w(issue_tracking news)
-      assert_equal %w(issue_tracking news), project.enabled_module_names.sort
-    end
-  end
-
-  test "enabled_modules should define module by names and preserve ids" do
-    @project = Project.find(1)
-    # Remove one module
-    modules = @project.enabled_modules.slice(0..-2)
-    assert modules.any?
-    assert_difference 'EnabledModule.count', -1 do
-      @project.enabled_module_names = modules.collect(&:name)
-    end
-    @project.reload
-    # Ids should be preserved
-    assert_equal @project.enabled_module_ids.sort, modules.collect(&:id).sort
-  end
-
-  test "enabled_modules should enable a module" do
-    @project = Project.find(1)
-    @project.enabled_module_names = []
-    @project.reload
-    assert_equal [], @project.enabled_module_names
-    #with string
-    @project.enable_module!("issue_tracking")
-    assert_equal ["issue_tracking"], @project.enabled_module_names
-    #with symbol
-    @project.enable_module!(:gantt)
-    assert_equal ["issue_tracking", "gantt"], @project.enabled_module_names
-    #don't add a module twice
-    @project.enable_module!("issue_tracking")
-    assert_equal ["issue_tracking", "gantt"], @project.enabled_module_names
-  end
-
-  test "enabled_modules should disable a module" do
-    @project = Project.find(1)
-    #with string
-    assert @project.enabled_module_names.include?("issue_tracking")
-    @project.disable_module!("issue_tracking")
-    assert ! @project.reload.enabled_module_names.include?("issue_tracking")
-    #with symbol
-    assert @project.enabled_module_names.include?("gantt")
-    @project.disable_module!(:gantt)
-    assert ! @project.reload.enabled_module_names.include?("gantt")
-    #with EnabledModule object
-    first_module = @project.enabled_modules.first
-    @project.disable_module!(first_module)
-    assert ! @project.reload.enabled_module_names.include?(first_module.name)
-  end
-
-  def test_enabled_module_names_should_not_recreate_enabled_modules
-    project = Project.find(1)
-    # Remove one module
-    modules = project.enabled_modules.slice(0..-2)
-    assert modules.any?
-    assert_difference 'EnabledModule.count', -1 do
-      project.enabled_module_names = modules.collect(&:name)
-    end
-    project.reload
-    # Ids should be preserved
-    assert_equal project.enabled_module_ids.sort, modules.collect(&:id).sort
-  end
-
-  def test_copy_from_existing_project
-    source_project = Project.find(1)
-    copied_project = Project.copy_from(1)
-
-    assert copied_project
-    # Cleared attributes
-    assert copied_project.id.blank?
-    assert copied_project.name.blank?
-    assert copied_project.identifier.blank?
-
-    # Duplicated attributes
-    assert_equal source_project.description, copied_project.description
-    assert_equal source_project.enabled_modules, copied_project.enabled_modules
-    assert_equal source_project.trackers, copied_project.trackers
-
-    # Default attributes
-    assert_equal 1, copied_project.status
-  end
-
-  def test_activities_should_use_the_system_activities
-    project = Project.find(1)
-    assert_equal project.activities, TimeEntryActivity.where(:active => true).all
-  end
-
-
-  def test_activities_should_use_the_project_specific_activities
-    project = Project.find(1)
-    overridden_activity = TimeEntryActivity.new({:name => "Project", :project => project})
-    assert overridden_activity.save!
-
-    assert project.activities.include?(overridden_activity), "Project specific Activity not found"
-  end
-
-  def test_activities_should_not_include_the_inactive_project_specific_activities
-    project = Project.find(1)
-    overridden_activity = TimeEntryActivity.new({:name => "Project", :project => project, :parent => TimeEntryActivity.first, :active => false})
-    assert overridden_activity.save!
-
-    assert !project.activities.include?(overridden_activity), "Inactive Project specific Activity found"
-  end
-
-  def test_activities_should_not_include_project_specific_activities_from_other_projects
-    project = Project.find(1)
-    overridden_activity = TimeEntryActivity.new({:name => "Project", :project => Project.find(2)})
-    assert overridden_activity.save!
-
-    assert !project.activities.include?(overridden_activity), "Project specific Activity found on a different project"
-  end
-
-  def test_activities_should_handle_nils
-    overridden_activity = TimeEntryActivity.new({:name => "Project", :project => Project.find(1), :parent => TimeEntryActivity.first})
-    TimeEntryActivity.delete_all
-
-    # No activities
-    project = Project.find(1)
-    assert project.activities.empty?
-
-    # No system, one overridden
-    assert overridden_activity.save!
-    project.reload
-    assert_equal [overridden_activity], project.activities
-  end
-
-  def test_activities_should_override_system_activities_with_project_activities
-    project = Project.find(1)
-    parent_activity = TimeEntryActivity.first
-    overridden_activity = TimeEntryActivity.new({:name => "Project", :project => project, :parent => parent_activity})
-    assert overridden_activity.save!
-
-    assert project.activities.include?(overridden_activity), "Project specific Activity not found"
-    assert !project.activities.include?(parent_activity), "System Activity found when it should have been overridden"
-  end
-
-  def test_activities_should_include_inactive_activities_if_specified
-    project = Project.find(1)
-    overridden_activity = TimeEntryActivity.new({:name => "Project", :project => project, :parent => TimeEntryActivity.first, :active => false})
-    assert overridden_activity.save!
-
-    assert project.activities(true).include?(overridden_activity), "Inactive Project specific Activity not found"
-  end
-
-  test 'activities should not include active System activities if the project has an override that is inactive' do
-    project = Project.find(1)
-    system_activity = TimeEntryActivity.find_by_name('Design')
-    assert system_activity.active?
-    overridden_activity = TimeEntryActivity.create!(:name => "Project", :project => project, :parent => system_activity, :active => false)
-    assert overridden_activity.save!
-
-    assert !project.activities.include?(overridden_activity), "Inactive Project specific Activity not found"
-    assert !project.activities.include?(system_activity), "System activity found when the project has an inactive override"
-  end
-
-  def test_close_completed_versions
-    Version.update_all("status = 'open'")
-    project = Project.find(1)
-    assert_not_nil project.versions.detect {|v| v.completed? && v.status == 'open'}
-    assert_not_nil project.versions.detect {|v| !v.completed? && v.status == 'open'}
-    project.close_completed_versions
-    project.reload
-    assert_nil project.versions.detect {|v| v.completed? && v.status != 'closed'}
-    assert_not_nil project.versions.detect {|v| !v.completed? && v.status == 'open'}
-  end
-
-  test "#start_date should be nil if there are no issues on the project" do
-    project = Project.generate!
-    assert_nil project.start_date
-  end
-
-  test "#start_date should be nil when issues have no start date" do
-    project = Project.generate!
-    project.trackers << Tracker.generate!
-    early = 7.days.ago.to_date
-    Issue.generate!(:project => project, :start_date => nil)
-
-    assert_nil project.start_date
-  end
-
-  test "#start_date should be the earliest start date of it's issues" do
-    project = Project.generate!
-    project.trackers << Tracker.generate!
-    early = 7.days.ago.to_date
-    Issue.generate!(:project => project, :start_date => Date.today)
-    Issue.generate!(:project => project, :start_date => early)
-
-    assert_equal early, project.start_date
-  end
-
-  test "#due_date should be nil if there are no issues on the project" do
-    project = Project.generate!
-    assert_nil project.due_date
-  end
-
-  test "#due_date should be nil if there are no issues with due dates" do
-    project = Project.generate!
-    project.trackers << Tracker.generate!
-    Issue.generate!(:project => project, :due_date => nil)
-
-    assert_nil project.due_date
-  end
-
-  test "#due_date should be the latest due date of it's issues" do
-    project = Project.generate!
-    project.trackers << Tracker.generate!
-    future = 7.days.from_now.to_date
-    Issue.generate!(:project => project, :due_date => future)
-    Issue.generate!(:project => project, :due_date => Date.today)
-
-    assert_equal future, project.due_date
-  end
-
-  test "#due_date should be the latest due date of it's versions" do
-    project = Project.generate!
-    future = 7.days.from_now.to_date
-    project.versions << Version.generate!(:effective_date => future)
-    project.versions << Version.generate!(:effective_date => Date.today)
-
-    assert_equal future, project.due_date
-  end
-
-  test "#due_date should pick the latest date from it's issues and versions" do
-    project = Project.generate!
-    project.trackers << Tracker.generate!
-    future = 7.days.from_now.to_date
-    far_future = 14.days.from_now.to_date
-    Issue.generate!(:project => project, :due_date => far_future)
-    project.versions << Version.generate!(:effective_date => future)
-
-    assert_equal far_future, project.due_date
-  end
-
-  test "#completed_percent with no versions should be 100" do
-    project = Project.generate!
-    assert_equal 100, project.completed_percent
-  end
-
-  test "#completed_percent with versions should return 0 if the versions have no issues" do
-    project = Project.generate!
-    Version.generate!(:project => project)
-    Version.generate!(:project => project)
-
-    assert_equal 0, project.completed_percent
-  end
-
-  test "#completed_percent with versions should return 100 if the version has only closed issues" do
-    project = Project.generate!
-    project.trackers << Tracker.generate!
-    v1 = Version.generate!(:project => project)
-    Issue.generate!(:project => project, :status => IssueStatus.find_by_name('Closed'), :fixed_version => v1)
-    v2 = Version.generate!(:project => project)
-    Issue.generate!(:project => project, :status => IssueStatus.find_by_name('Closed'), :fixed_version => v2)
-
-    assert_equal 100, project.completed_percent
-  end
-
-  test "#completed_percent with versions should return the averaged completed percent of the versions (not weighted)" do
-    project = Project.generate!
-    project.trackers << Tracker.generate!
-    v1 = Version.generate!(:project => project)
-    Issue.generate!(:project => project, :status => IssueStatus.find_by_name('New'), :estimated_hours => 10, :done_ratio => 50, :fixed_version => v1)
-    v2 = Version.generate!(:project => project)
-    Issue.generate!(:project => project, :status => IssueStatus.find_by_name('New'), :estimated_hours => 10, :done_ratio => 50, :fixed_version => v2)
-
-    assert_equal 50, project.completed_percent
-  end
-
-  test "#notified_users" do
-    project = Project.generate!
-    role = Role.generate!
-
-    user_with_membership_notification = User.generate!(:mail_notification => 'selected')
-    Member.create!(:project => project, :roles => [role], :principal => user_with_membership_notification, :mail_notification => true)
-
-    all_events_user = User.generate!(:mail_notification => 'all')
-    Member.create!(:project => project, :roles => [role], :principal => all_events_user)
-
-    no_events_user = User.generate!(:mail_notification => 'none')
-    Member.create!(:project => project, :roles => [role], :principal => no_events_user)
-
-    only_my_events_user = User.generate!(:mail_notification => 'only_my_events')
-    Member.create!(:project => project, :roles => [role], :principal => only_my_events_user)
-
-    only_assigned_user = User.generate!(:mail_notification => 'only_assigned')
-    Member.create!(:project => project, :roles => [role], :principal => only_assigned_user)
-
-    only_owned_user = User.generate!(:mail_notification => 'only_owner')
-    Member.create!(:project => project, :roles => [role], :principal => only_owned_user)
-
-    assert project.notified_users.include?(user_with_membership_notification), "should include members with a mail notification"
-    assert project.notified_users.include?(all_events_user), "should include users with the 'all' notification option"
-    assert !project.notified_users.include?(no_events_user), "should not include users with the 'none' notification option"
-    assert !project.notified_users.include?(only_my_events_user), "should not include users with the 'only_my_events' notification option"
-    assert !project.notified_users.include?(only_assigned_user), "should not include users with the 'only_assigned' notification option"
-    assert !project.notified_users.include?(only_owned_user), "should not include users with the 'only_owner' notification option"
-  end
-end
--- a/.svn/pristine/c3/c359a81860a9169febc935dc31d96675ccce6f95.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,431 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingRepositoriesTest < ActionController::IntegrationTest
-  def setup
-    @path_hash  = repository_path_hash(%w[path to file.c])
-    assert_equal "path/to/file.c", @path_hash[:path]
-    assert_equal "path/to/file.c", @path_hash[:param]
-  end
-
-  def test_repositories_resources
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repositories/new" },
-        { :controller => 'repositories', :action => 'new', :project_id => 'redmine' }
-      )
-    assert_routing(
-        { :method => 'post',
-          :path => "/projects/redmine/repositories" },
-        { :controller => 'repositories', :action => 'create', :project_id => 'redmine' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/repositories/1/edit" },
-        { :controller => 'repositories', :action => 'edit', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put',
-          :path => "/repositories/1" },
-        { :controller => 'repositories', :action => 'update', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'delete',
-          :path => "/repositories/1" },
-        { :controller => 'repositories', :action => 'destroy', :id => '1' }
-      )
-    ["get", "post"].each do |method|
-      assert_routing(
-          { :method => method,
-            :path => "/repositories/1/committers" },
-          { :controller => 'repositories', :action => 'committers', :id => '1' }
-        )
-    end
-  end
-
-  def test_repositories_show
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository" },
-        { :controller => 'repositories', :action => 'show', :id => 'redmine' }
-      )
-  end
-
-  def test_repositories
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/statistics" },
-        { :controller => 'repositories', :action => 'stats', :id => 'redmine' }
-     )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/graph" },
-        { :controller => 'repositories', :action => 'graph', :id => 'redmine' }
-     )
-  end
-
-  def test_repositories_show_with_repository_id
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo" },
-        { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo' }
-      )
-  end
-
-  def test_repositories_with_repository_id
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/statistics" },
-        { :controller => 'repositories', :action => 'stats', :id => 'redmine', :repository_id => 'foo' }
-     )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/graph" },
-        { :controller => 'repositories', :action => 'graph', :id => 'redmine', :repository_id => 'foo' }
-     )
-  end
-
-  def test_repositories_revisions
-    empty_path_param = []
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions" },
-        { :controller => 'repositories', :action => 'revisions', :id => 'redmine' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions.atom" },
-        { :controller => 'repositories', :action => 'revisions', :id => 'redmine',
-          :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2457" },
-        { :controller => 'repositories', :action => 'revision', :id => 'redmine',
-          :rev => '2457' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2457/show" },
-        { :controller => 'repositories', :action => 'show', :id => 'redmine',
-          :rev => '2457' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2457/show/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'show', :id => 'redmine',
-          :path => @path_hash[:param] , :rev => '2457'}
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2457/diff" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine',
-          :rev => '2457' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2457/diff" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine',
-          :rev => '2457', :format => 'diff' },
-        {},
-        { :format => 'diff' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2/diff/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine',
-          :path => @path_hash[:param], :rev => '2' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2/diff/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine',
-          :path => @path_hash[:param], :rev => '2', :format => 'diff' },
-        {},
-        { :format => 'diff' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2/entry/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'entry', :id => 'redmine',
-          :path => @path_hash[:param], :rev => '2' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2/raw/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'raw', :id => 'redmine',
-          :path => @path_hash[:param], :rev => '2' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revisions/2/annotate/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'annotate', :id => 'redmine',
-          :path => @path_hash[:param], :rev => '2' }
-      )
-  end
-
-  def test_repositories_revisions_with_repository_id
-    empty_path_param = []
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions" },
-        { :controller => 'repositories', :action => 'revisions', :id => 'redmine', :repository_id => 'foo' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions.atom" },
-        { :controller => 'repositories', :action => 'revisions', :id => 'redmine', :repository_id => 'foo',
-          :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2457" },
-        { :controller => 'repositories', :action => 'revision', :id => 'redmine', :repository_id => 'foo',
-          :rev => '2457' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2457/show" },
-        { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo',
-          :rev => '2457' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2457/show/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param] , :rev => '2457'}
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2457/diff" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
-          :rev => '2457' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2457/diff" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
-          :rev => '2457', :format => 'diff' },
-        {},
-        { :format => 'diff' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2/diff/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param], :rev => '2' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2/diff/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param], :rev => '2', :format => 'diff' },
-        {},
-        { :format => 'diff' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2/entry/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param], :rev => '2' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2/raw/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'raw', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param], :rev => '2' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revisions/2/annotate/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'annotate', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param], :rev => '2' }
-      )
-  end
-
-  def test_repositories_non_revisions_path
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/changes" },
-        { :controller => 'repositories', :action => 'changes', :id => 'redmine' }
-      )
-    ['2457', 'master', 'slash/slash'].each do |rev|
-      assert_routing(
-           { :method => 'get',
-             :path => "/projects/redmine/repository/changes" },
-           { :controller => 'repositories', :action => 'changes', :id => 'redmine',
-             :rev => rev },
-           {},
-           { :rev => rev }
-         )
-    end
-    ['2457', 'master', 'slash/slash'].each do |rev|
-      assert_routing(
-           { :method => 'get',
-             :path => "/projects/redmine/repository/changes/#{@path_hash[:path]}" },
-           { :controller => 'repositories', :action => 'changes', :id => 'redmine',
-             :path => @path_hash[:param], :rev => rev },
-           {},
-           { :rev => rev }
-         )
-    end
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/diff/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/browse/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'browse', :id => 'redmine',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/entry/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'entry', :id => 'redmine',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/raw/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'raw', :id => 'redmine',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/annotate/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'annotate', :id => 'redmine',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/changes/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'changes', :id => 'redmine',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/revision" },
-        { :controller => 'repositories', :action => 'revision', :id => 'redmine' }
-      )
-  end
-
-  def test_repositories_non_revisions_path_with_repository_id
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/changes" },
-        { :controller => 'repositories', :action => 'changes',
-          :id => 'redmine', :repository_id => 'foo' }
-      )
-    ['2457', 'master', 'slash/slash'].each do |rev|
-      assert_routing(
-           { :method => 'get',
-             :path => "/projects/redmine/repository/foo/changes" },
-           { :controller => 'repositories', :action => 'changes',
-             :id => 'redmine',
-             :repository_id => 'foo', :rev => rev },
-           {},
-           { :rev => rev }
-         )
-    end
-    ['2457', 'master', 'slash/slash'].each do |rev|
-      assert_routing(
-           { :method => 'get',
-             :path => "/projects/redmine/repository/foo/changes/#{@path_hash[:path]}" },
-           { :controller => 'repositories', :action => 'changes', :id => 'redmine',
-             :repository_id => 'foo', :path => @path_hash[:param], :rev => rev },
-           {},
-           { :rev => rev }
-         )
-    end
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/diff/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/browse/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'browse', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/entry/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/raw/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'raw', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/annotate/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'annotate', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/changes/#{@path_hash[:path]}" },
-        { :controller => 'repositories', :action => 'changes', :id => 'redmine', :repository_id => 'foo',
-          :path => @path_hash[:param] }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/redmine/repository/foo/revision" },
-        { :controller => 'repositories', :action => 'revision', :id => 'redmine', :repository_id => 'foo'}
-      )
-  end
-
-  def test_repositories_related_issues
-    assert_routing(
-        { :method => 'post',
-          :path => "/projects/redmine/repository/revisions/123/issues" },
-        { :controller => 'repositories', :action => 'add_related_issue',
-          :id => 'redmine', :rev => '123' }
-      )
-    assert_routing(
-        { :method => 'delete',
-          :path => "/projects/redmine/repository/revisions/123/issues/25" },
-        { :controller => 'repositories', :action => 'remove_related_issue',
-          :id => 'redmine', :rev => '123', :issue_id => '25' }
-      )
-  end
-
-  def test_repositories_related_issues_with_repository_id
-    assert_routing(
-        { :method => 'post',
-          :path => "/projects/redmine/repository/foo/revisions/123/issues" },
-        { :controller => 'repositories', :action => 'add_related_issue',
-          :id => 'redmine', :repository_id => 'foo', :rev => '123' }
-      )
-    assert_routing(
-        { :method => 'delete',
-          :path => "/projects/redmine/repository/foo/revisions/123/issues/25" },
-        { :controller => 'repositories', :action => 'remove_related_issue',
-          :id => 'redmine', :repository_id => 'foo', :rev => '123', :issue_id => '25' }
-      )
-  end
-end
--- a/.svn/pristine/c3/c380a8da5e4aab76f8d0af1d1700421b9d214474.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class CustomFieldUserFormatTest < ActiveSupport::TestCase
-  fixtures :custom_fields, :projects, :members, :users, :member_roles, :trackers, :issues
-
-  def setup
-    @field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user')
-  end
-
-  def test_possible_values_with_no_arguments
-    assert_equal [], @field.possible_values
-    assert_equal [], @field.possible_values(nil)
-  end
-
-  def test_possible_values_with_project_resource
-    project = Project.find(1)
-    possible_values = @field.possible_values(project.issues.first)
-    assert possible_values.any?
-    assert_equal project.users.sort.collect(&:id).map(&:to_s), possible_values
-  end
-
-  def test_possible_values_with_nil_project_resource
-    project = Project.find(1)
-    assert_equal [], @field.possible_values(Issue.new)
-  end
-
-  def test_possible_values_options_with_no_arguments
-    assert_equal [], @field.possible_values_options
-    assert_equal [], @field.possible_values_options(nil)
-  end
-
-  def test_possible_values_options_with_project_resource
-    project = Project.find(1)
-    possible_values_options = @field.possible_values_options(project.issues.first)
-    assert possible_values_options.any?
-    assert_equal project.users.sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
-  end
-
-  def test_possible_values_options_with_array
-    projects = Project.find([1, 2])
-    possible_values_options = @field.possible_values_options(projects)
-    assert possible_values_options.any?
-    assert_equal (projects.first.users & projects.last.users).sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
-  end
-
-  def test_cast_blank_value
-    assert_equal nil, @field.cast_value(nil)
-    assert_equal nil, @field.cast_value("")
-  end
-
-  def test_cast_valid_value
-    user = @field.cast_value("2")
-    assert_kind_of User, user
-    assert_equal User.find(2), user
-  end
-
-  def test_cast_invalid_value
-    assert_equal nil, @field.cast_value("187")
-  end
-end
--- a/.svn/pristine/c3/c38db3d2cd80cc99b93358b91a6eeac67c486c5e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,264 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../base', __FILE__)
-
-class Redmine::UiTest::IssuesTest < Redmine::UiTest::Base
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :trackers, :projects_trackers, :enabled_modules, :issue_statuses, :issues,
-           :enumerations, :custom_fields, :custom_values, :custom_fields_trackers,
-           :watchers
-
-  def test_create_issue
-    log_user('jsmith', 'jsmith')
-    visit '/projects/ecookbook/issues/new'
-    within('form#issue-form') do
-      select 'Bug', :from => 'Tracker'
-      select 'Low', :from => 'Priority'
-      fill_in 'Subject', :with => 'new test issue'
-      fill_in 'Description', :with => 'new issue'
-      select '0 %', :from => 'Done'
-      fill_in 'Due date', :with => ''
-      fill_in 'Searchable field', :with => 'Value for field 2'
-      # click_button 'Create' would match both 'Create' and 'Create and continue' buttons
-      find('input[name=commit]').click
-    end
-
-    # find created issue
-    issue = Issue.find_by_subject("new test issue")
-    assert_kind_of Issue, issue
-
-    # check redirection
-    find 'div#flash_notice', :visible => true, :text => "Issue \##{issue.id} created."
-    assert_equal issue_path(:id => issue), current_path
-
-    # check issue attributes
-    assert_equal 'jsmith', issue.author.login
-    assert_equal 1, issue.project.id
-    assert_equal IssueStatus.find_by_name('New'), issue.status 
-    assert_equal Tracker.find_by_name('Bug'), issue.tracker
-    assert_equal IssuePriority.find_by_name('Low'), issue.priority
-    assert_equal 'Value for field 2', issue.custom_field_value(CustomField.find_by_name('Searchable field'))
-  end
-
-  def test_create_issue_with_form_update
-    field1 = IssueCustomField.create!(
-      :field_format => 'string',
-      :name => 'Field1',
-      :is_for_all => true,
-      :trackers => Tracker.find_all_by_id([1, 2])
-    )
-    field2 = IssueCustomField.create!(
-      :field_format => 'string',
-      :name => 'Field2',
-      :is_for_all => true,
-      :trackers => Tracker.find_all_by_id(2)
-    )
-
-    Role.non_member.add_permission! :add_issues
-    Role.non_member.remove_permission! :edit_issues, :add_issue_notes
-
-    log_user('someone', 'foo')
-    visit '/projects/ecookbook/issues/new'
-    assert page.has_no_content?(field2.name)
-    assert page.has_content?(field1.name)
-
-    fill_in 'Subject', :with => 'New test issue'
-    fill_in 'Description', :with => 'New test issue description'
-    fill_in field1.name, :with => 'CF1 value'
-    select 'Low', :from => 'Priority'
-
-    # field2 should show up when changing tracker
-    select 'Feature request', :from => 'Tracker'
-    assert page.has_content?(field2.name)
-    assert page.has_content?(field1.name)
-
-    fill_in field2.name, :with => 'CF2 value'
-    assert_difference 'Issue.count' do
-      page.first(:button, 'Create').click
-    end
-
-    issue = Issue.order('id desc').first
-    assert_equal 'New test issue', issue.subject
-    assert_equal 'New test issue description', issue.description
-    assert_equal 'Low', issue.priority.name
-    assert_equal 'CF1 value', issue.custom_field_value(field1)
-    assert_equal 'CF2 value', issue.custom_field_value(field2)
-  end
-
-  def test_create_issue_with_watchers
-    user = User.generate!(:firstname => 'Some', :lastname => 'Watcher')
-    assert_equal 'Some Watcher', user.name
-    log_user('jsmith', 'jsmith')
-    visit '/projects/ecookbook/issues/new'
-    fill_in 'Subject', :with => 'Issue with watchers'
-    # Add a project member as watcher
-    check 'Dave Lopper'
-    # Search for another user
-    assert page.has_no_css?('form#new-watcher-form')
-    assert page.has_no_content?('Some Watcher')
-    click_link 'Search for watchers to add'
-    within('form#new-watcher-form') do
-      assert page.has_content?('Some One')
-      fill_in 'user_search', :with => 'watch'
-      assert page.has_no_content?('Some One')
-      check 'Some Watcher'
-      click_button 'Add'
-    end
-    assert page.has_css?('form#issue-form')
-    assert page.has_css?('p#watchers_form')
-    using_wait_time(30) do
-      within('span#watchers_inputs') do
-        within("label#issue_watcher_user_ids_#{user.id}") do
-          assert has_content?('Some Watcher'), "No watcher content"
-        end
-      end
-    end
-    assert_difference 'Issue.count' do
-      find('input[name=commit]').click
-    end
-
-    issue = Issue.order('id desc').first
-    assert_equal ['Dave Lopper', 'Some Watcher'], issue.watcher_users.map(&:name).sort
-  end
-
-  def test_create_issue_start_due_date
-    with_settings :default_issue_start_date_to_creation_date => 0 do
-      log_user('jsmith', 'jsmith')
-      visit '/projects/ecookbook/issues/new'
-      assert_equal "", page.find('input#issue_start_date').value
-      assert_equal "", page.find('input#issue_due_date').value
-      page.first('p#start_date_area img').click
-      page.first("td.ui-datepicker-days-cell-over a").click
-      assert_equal Date.today.to_s, page.find('input#issue_start_date').value
-      page.first('p#due_date_area img').click
-      page.first("td.ui-datepicker-days-cell-over a").click
-      assert_equal Date.today.to_s, page.find('input#issue_due_date').value
-    end
-  end
-
-  def test_create_issue_start_due_date_default
-    log_user('jsmith', 'jsmith')
-    visit '/projects/ecookbook/issues/new'
-    fill_in 'Start date', :with => '2012-04-01'
-    fill_in 'Due date', :with => ''
-    page.first('p#due_date_area img').click
-    page.first("td.ui-datepicker-days-cell-over a").click
-    assert_equal '2012-04-01', page.find('input#issue_due_date').value
-
-    fill_in 'Start date', :with => ''
-    fill_in 'Due date', :with => '2012-04-01'
-    page.first('p#start_date_area img').click
-    page.first("td.ui-datepicker-days-cell-over a").click
-    assert_equal '2012-04-01', page.find('input#issue_start_date').value
-  end
-
-  def test_preview_issue_description
-    log_user('jsmith', 'jsmith')
-    visit '/projects/ecookbook/issues/new'
-    within('form#issue-form') do
-      fill_in 'Subject', :with => 'new issue subject'
-      fill_in 'Description', :with => 'new issue description'
-      click_link 'Preview'
-    end
-    find 'div#preview fieldset', :visible => true, :text => 'new issue description'
-    assert_difference 'Issue.count' do
-      find('input[name=commit]').click
-    end
-
-    issue = Issue.order('id desc').first
-    assert_equal 'new issue description', issue.description
-  end
-
-  def test_update_issue_with_form_update
-    field = IssueCustomField.create!(
-      :field_format => 'string',
-      :name => 'Form update CF',
-      :is_for_all => true,
-      :trackers => Tracker.find_all_by_name('Feature request')
-    )
-
-    Role.non_member.add_permission! :edit_issues
-    Role.non_member.remove_permission! :add_issues, :add_issue_notes
-
-    log_user('someone', 'foo')
-    visit '/issues/1'
-    assert page.has_no_content?('Form update CF')
-
-    page.first(:link, 'Update').click
-    # the custom field should show up when changing tracker
-    select 'Feature request', :from => 'Tracker'
-    assert page.has_content?('Form update CF')
-
-    fill_in 'Form update', :with => 'CF value'
-    assert_no_difference 'Issue.count' do
-      page.first(:button, 'Submit').click
-    end
-
-    issue = Issue.find(1)
-    assert_equal 'CF value', issue.custom_field_value(field)
-  end
-
-  def test_remove_issue_watcher_from_sidebar
-    user = User.find(3)
-    Watcher.create!(:watchable => Issue.find(1), :user => user)
-
-    log_user('jsmith', 'jsmith')
-    visit '/issues/1'
-    assert page.first('#sidebar').has_content?('Watchers (1)')
-    assert page.first('#sidebar').has_content?(user.name)
-    assert_difference 'Watcher.count', -1 do
-      page.first('ul.watchers .user-3 a.delete').click
-      assert page.first('#sidebar').has_content?('Watchers (0)')
-    end
-    assert page.first('#sidebar').has_no_content?(user.name)
-  end
-
-  def test_watch_issue_via_context_menu
-    log_user('jsmith', 'jsmith')
-    visit '/issues'
-    assert page.has_css?('tr#issue-1')
-    find('tr#issue-1 td.updated_on').click
-    page.execute_script "$('tr#issue-1 td.updated_on').trigger('contextmenu');"
-    assert_difference 'Watcher.count' do
-      within('#context-menu') do
-        click_link 'Watch'
-      end
-      assert page.has_css?('tr#issue-1')
-    end
-    assert Issue.find(1).watched_by?(User.find_by_login('jsmith'))
-  end
-
-  def test_bulk_watch_issues_via_context_menu
-    log_user('jsmith', 'jsmith')
-    visit '/issues'
-    assert page.has_css?('tr#issue-1')
-    assert page.has_css?('tr#issue-4')
-    find('tr#issue-1 input[type=checkbox]').click
-    find('tr#issue-4 input[type=checkbox]').click
-    page.execute_script "$('tr#issue-1 td.updated_on').trigger('contextmenu');"
-    assert_difference 'Watcher.count', 2 do
-      within('#context-menu') do
-        click_link 'Watch'
-      end
-      assert page.has_css?('tr#issue-1')
-      assert page.has_css?('tr#issue-4')
-    end
-    assert Issue.find(1).watched_by?(User.find_by_login('jsmith'))
-    assert Issue.find(4).watched_by?(User.find_by_login('jsmith'))
-  end
-end
--- a/.svn/pristine/c4/c4b9bd5f0c63e69e0dff5d428931d5aa53681958.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,317 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class QueriesControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :queries, :enabled_modules
-
-  def setup
-    User.current = nil
-  end
-
-  def test_index
-    get :index
-    # HTML response not implemented
-    assert_response 406
-  end
-
-  def test_new_project_query
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-    assert_select 'input[name=?][value=0][checked=checked]', 'query[visibility]'
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'query_is_for_all',
-                                                 :checked => nil,
-                                                 :disabled => nil }
-    assert_select 'select[name=?]', 'c[]' do
-      assert_select 'option[value=tracker]'
-      assert_select 'option[value=subject]'
-    end
-  end
-
-  def test_new_global_query
-    @request.session[:user_id] = 2
-    get :new
-    assert_response :success
-    assert_template 'new'
-    assert_select 'input[name=?]', 'query[visibility]', 0
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'query_is_for_all',
-                                                 :checked => 'checked',
-                                                 :disabled => nil }
-  end
-
-  def test_new_on_invalid_project
-    @request.session[:user_id] = 2
-    get :new, :project_id => 'invalid'
-    assert_response 404
-  end
-
-  def test_create_project_public_query
-    @request.session[:user_id] = 2
-    post :create,
-         :project_id => 'ecookbook',
-         :default_columns => '1',
-         :f => ["status_id", "assigned_to_id"],
-         :op => {"assigned_to_id" => "=", "status_id" => "o"},
-         :v => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
-         :query => {"name" => "test_new_project_public_query", "visibility" => "2"}
-
-    q = Query.find_by_name('test_new_project_public_query')
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
-    assert q.is_public?
-    assert q.has_default_columns?
-    assert q.valid?
-  end
-
-  def test_create_project_private_query
-    @request.session[:user_id] = 3
-    post :create,
-         :project_id => 'ecookbook',
-         :default_columns => '1',
-         :fields => ["status_id", "assigned_to_id"],
-         :operators => {"assigned_to_id" => "=", "status_id" => "o"},
-         :values => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
-         :query => {"name" => "test_new_project_private_query", "visibility" => "2"}
-
-    q = Query.find_by_name('test_new_project_private_query')
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
-    assert !q.is_public?
-    assert q.has_default_columns?
-    assert q.valid?
-  end
-
-  def test_create_global_private_query_with_custom_columns
-    @request.session[:user_id] = 3
-    post :create,
-         :fields => ["status_id", "assigned_to_id"],
-         :operators => {"assigned_to_id" => "=", "status_id" => "o"},
-         :values => { "assigned_to_id" => ["me"], "status_id" => ["1"]},
-         :query => {"name" => "test_new_global_private_query", "visibility" => "2"},
-         :c => ["", "tracker", "subject", "priority", "category"]
-
-    q = Query.find_by_name('test_new_global_private_query')
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => nil, :query_id => q
-    assert !q.is_public?
-    assert !q.has_default_columns?
-    assert_equal [:id, :tracker, :subject, :priority, :category], q.columns.collect {|c| c.name}
-    assert q.valid?
-  end
-
-  def test_create_global_query_with_custom_filters
-    @request.session[:user_id] = 3
-    post :create,
-         :fields => ["assigned_to_id"],
-         :operators => {"assigned_to_id" => "="},
-         :values => { "assigned_to_id" => ["me"]},
-         :query => {"name" => "test_new_global_query"}
-
-    q = Query.find_by_name('test_new_global_query')
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => nil, :query_id => q
-    assert !q.has_filter?(:status_id)
-    assert_equal ['assigned_to_id'], q.filters.keys
-    assert q.valid?
-  end
-
-  def test_create_with_sort
-    @request.session[:user_id] = 1
-    post :create,
-         :default_columns => '1',
-         :operators => {"status_id" => "o"},
-         :values => {"status_id" => ["1"]},
-         :query => {:name => "test_new_with_sort",
-                    :visibility => "2",
-                    :sort_criteria => {"0" => ["due_date", "desc"], "1" => ["tracker", ""]}}
-
-    query = Query.find_by_name("test_new_with_sort")
-    assert_not_nil query
-    assert_equal [['due_date', 'desc'], ['tracker', 'asc']], query.sort_criteria
-  end
-
-  def test_create_with_failure
-    @request.session[:user_id] = 2
-    assert_no_difference '::Query.count' do
-      post :create, :project_id => 'ecookbook', :query => {:name => ''}
-    end
-    assert_response :success
-    assert_template 'new'
-    assert_select 'input[name=?]', 'query[name]'
-  end
-
-  def test_create_global_query_from_gantt
-    @request.session[:user_id] = 1
-    assert_difference 'IssueQuery.count' do
-      post :create,
-           :gantt => 1,
-           :operators => {"status_id" => "o"},
-           :values => {"status_id" => ["1"]},
-           :query => {:name => "test_create_from_gantt",
-                      :draw_relations => '1',
-                      :draw_progress_line => '1'}
-      assert_response 302
-    end
-    query = IssueQuery.order('id DESC').first
-    assert_redirected_to "/issues/gantt?query_id=#{query.id}"
-    assert_equal true, query.draw_relations
-    assert_equal true, query.draw_progress_line
-  end
-
-  def test_create_project_query_from_gantt
-    @request.session[:user_id] = 1
-    assert_difference 'IssueQuery.count' do
-      post :create,
-           :project_id => 'ecookbook',
-           :gantt => 1,
-           :operators => {"status_id" => "o"},
-           :values => {"status_id" => ["1"]},
-           :query => {:name => "test_create_from_gantt",
-                      :draw_relations => '0',
-                      :draw_progress_line => '0'}
-      assert_response 302
-    end
-    query = IssueQuery.order('id DESC').first
-    assert_redirected_to "/projects/ecookbook/issues/gantt?query_id=#{query.id}"
-    assert_equal false, query.draw_relations
-    assert_equal false, query.draw_progress_line
-  end
-
-  def test_edit_global_public_query
-    @request.session[:user_id] = 1
-    get :edit, :id => 4
-    assert_response :success
-    assert_template 'edit'
-    assert_select 'input[name=?][value=2][checked=checked]', 'query[visibility]'
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'query_is_for_all',
-                                                 :checked => 'checked',
-                                                 :disabled => 'disabled' }
-  end
-
-  def test_edit_global_private_query
-    @request.session[:user_id] = 3
-    get :edit, :id => 3
-    assert_response :success
-    assert_template 'edit'
-    assert_select 'input[name=?]', 'query[visibility]', 0
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'query_is_for_all',
-                                                 :checked => 'checked',
-                                                 :disabled => 'disabled' }
-  end
-
-  def test_edit_project_private_query
-    @request.session[:user_id] = 3
-    get :edit, :id => 2
-    assert_response :success
-    assert_template 'edit'
-    assert_select 'input[name=?]', 'query[visibility]', 0
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'query_is_for_all',
-                                                 :checked => nil,
-                                                 :disabled => nil }
-  end
-
-  def test_edit_project_public_query
-    @request.session[:user_id] = 2
-    get :edit, :id => 1
-    assert_response :success
-    assert_template 'edit'
-    assert_select 'input[name=?][value=2][checked=checked]', 'query[visibility]'
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'query_is_for_all',
-                                                 :checked => nil,
-                                                 :disabled => 'disabled' }
-  end
-
-  def test_edit_sort_criteria
-    @request.session[:user_id] = 1
-    get :edit, :id => 5
-    assert_response :success
-    assert_template 'edit'
-    assert_tag :tag => 'select', :attributes => { :name => 'query[sort_criteria][0][]' },
-                                 :child => { :tag => 'option', :attributes => { :value => 'priority',
-                                                                                :selected => 'selected' } }
-    assert_tag :tag => 'select', :attributes => { :name => 'query[sort_criteria][0][]' },
-                                 :child => { :tag => 'option', :attributes => { :value => 'desc',
-                                                                                :selected => 'selected' } }
-  end
-
-  def test_edit_invalid_query
-    @request.session[:user_id] = 2
-    get :edit, :id => 99
-    assert_response 404
-  end
-
-  def test_udpate_global_private_query
-    @request.session[:user_id] = 3
-    put :update,
-         :id => 3,
-         :default_columns => '1',
-         :fields => ["status_id", "assigned_to_id"],
-         :operators => {"assigned_to_id" => "=", "status_id" => "o"},
-         :values => { "assigned_to_id" => ["me"], "status_id" => ["1"]},
-         :query => {"name" => "test_edit_global_private_query", "visibility" => "2"}
-
-    assert_redirected_to :controller => 'issues', :action => 'index', :query_id => 3
-    q = Query.find_by_name('test_edit_global_private_query')
-    assert !q.is_public?
-    assert q.has_default_columns?
-    assert q.valid?
-  end
-
-  def test_update_global_public_query
-    @request.session[:user_id] = 1
-    put :update,
-         :id => 4,
-         :default_columns => '1',
-         :fields => ["status_id", "assigned_to_id"],
-         :operators => {"assigned_to_id" => "=", "status_id" => "o"},
-         :values => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
-         :query => {"name" => "test_edit_global_public_query", "visibility" => "2"}
-
-    assert_redirected_to :controller => 'issues', :action => 'index', :query_id => 4
-    q = Query.find_by_name('test_edit_global_public_query')
-    assert q.is_public?
-    assert q.has_default_columns?
-    assert q.valid?
-  end
-
-  def test_update_with_failure
-    @request.session[:user_id] = 1
-    put :update, :id => 4, :query => {:name => ''}
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_destroy
-    @request.session[:user_id] = 2
-    delete :destroy, :id => 1
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :set_filter => 1, :query_id => nil
-    assert_nil Query.find_by_id(1)
-  end
-
-  def test_backslash_should_be_escaped_in_filters
-    @request.session[:user_id] = 2
-    get :new, :subject => 'foo/bar'
-    assert_response :success
-    assert_template 'new'
-    assert_include 'addFilter("subject", "=", ["foo\/bar"]);', response.body
-  end
-end
--- a/.svn/pristine/c5/c52e05a6bbf465f32cbcf511ef2e13fc1ee99956.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module AccountHelper
-end
--- a/.svn/pristine/c5/c579e1089533be72e96be9f837601901aa22b4de.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,263 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-require 'issues_controller'
-
-class IssuesControllerTransactionTest < ActionController::TestCase
-  tests IssuesController
-  fixtures :projects,
-           :users,
-           :roles,
-           :members,
-           :member_roles,
-           :issues,
-           :issue_statuses,
-           :versions,
-           :trackers,
-           :projects_trackers,
-           :issue_categories,
-           :enabled_modules,
-           :enumerations,
-           :attachments,
-           :workflows,
-           :custom_fields,
-           :custom_values,
-           :custom_fields_projects,
-           :custom_fields_trackers,
-           :time_entries,
-           :journals,
-           :journal_details,
-           :queries
-
-  self.use_transactional_fixtures = false
-
-  def setup
-    User.current = nil
-  end
-
-  def test_update_stale_issue_should_not_update_the_issue
-    issue = Issue.find(2)
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Journal.count' do
-      assert_no_difference 'TimeEntry.count' do
-        put :update,
-              :id => issue.id,
-              :issue => {
-                :fixed_version_id => 4,
-                :notes => 'My notes',
-                :lock_version => (issue.lock_version - 1)
-              },
-              :time_entry => { :hours => '2.5', :comments => '', :activity_id => TimeEntryActivity.first.id }
-      end
-    end
-
-    assert_response :success
-    assert_template 'edit'
-
-    assert_select 'div.conflict'
-    assert_select 'input[name=?][value=?]', 'conflict_resolution', 'overwrite'
-    assert_select 'input[name=?][value=?]', 'conflict_resolution', 'add_notes'
-    assert_select 'label' do
-      assert_select 'input[name=?][value=?]', 'conflict_resolution', 'cancel'
-      assert_select 'a[href=/issues/2]'
-    end
-  end
-
-  def test_update_stale_issue_should_save_attachments
-    set_tmp_attachments_directory
-    issue = Issue.find(2)
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Journal.count' do
-      assert_no_difference 'TimeEntry.count' do
-        assert_difference 'Attachment.count' do
-          put :update,
-                :id => issue.id,
-                :issue => {
-                  :fixed_version_id => 4,
-                  :notes => 'My notes',
-                  :lock_version => (issue.lock_version - 1)
-                },
-                :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}},
-                :time_entry => { :hours => '2.5', :comments => '', :activity_id => TimeEntryActivity.first.id }
-        end
-      end
-    end
-
-    assert_response :success
-    assert_template 'edit'
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_tag 'input', :attributes => {:name => 'attachments[p0][token]', :value => attachment.token}
-    assert_tag 'input', :attributes => {:name => 'attachments[p0][filename]', :value => 'testfile.txt'}
-  end
-
-  def test_update_stale_issue_without_notes_should_not_show_add_notes_option
-    issue = Issue.find(2)
-    @request.session[:user_id] = 2
-
-    put :update, :id => issue.id,
-          :issue => {
-            :fixed_version_id => 4,
-            :notes => '',
-            :lock_version => (issue.lock_version - 1)
-          }
-
-    assert_tag 'div', :attributes => {:class => 'conflict'}
-    assert_tag 'input', :attributes => {:name => 'conflict_resolution', :value => 'overwrite'}
-    assert_no_tag 'input', :attributes => {:name => 'conflict_resolution', :value => 'add_notes'}
-    assert_tag 'input', :attributes => {:name => 'conflict_resolution', :value => 'cancel'}
-  end
-
-  def test_update_stale_issue_should_show_conflicting_journals
-    @request.session[:user_id] = 2
-
-    put :update, :id => 1,
-          :issue => {
-            :fixed_version_id => 4,
-            :notes => '',
-            :lock_version => 2
-          },
-          :last_journal_id => 1
-
-    assert_not_nil assigns(:conflict_journals)
-    assert_equal 1, assigns(:conflict_journals).size
-    assert_equal 2, assigns(:conflict_journals).first.id
-    assert_tag 'div', :attributes => {:class => 'conflict'},
-      :descendant => {:content => /Some notes with Redmine links/}
-  end
-
-  def test_update_stale_issue_without_previous_journal_should_show_all_journals
-    @request.session[:user_id] = 2
-
-    put :update, :id => 1,
-          :issue => {
-            :fixed_version_id => 4,
-            :notes => '',
-            :lock_version => 2
-          },
-          :last_journal_id => ''
-
-    assert_not_nil assigns(:conflict_journals)
-    assert_equal 2, assigns(:conflict_journals).size
-    assert_tag 'div', :attributes => {:class => 'conflict'},
-      :descendant => {:content => /Some notes with Redmine links/}
-    assert_tag 'div', :attributes => {:class => 'conflict'},
-      :descendant => {:content => /Journal notes/}
-  end
-
-  def test_update_stale_issue_should_show_private_journals_with_permission_only
-    journal = Journal.create!(:journalized => Issue.find(1), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
-
-    @request.session[:user_id] = 2
-    put :update, :id => 1, :issue => {:fixed_version_id => 4, :lock_version => 2}, :last_journal_id => ''
-    assert_include journal, assigns(:conflict_journals)
-
-    Role.find(1).remove_permission! :view_private_notes
-    put :update, :id => 1, :issue => {:fixed_version_id => 4, :lock_version => 2}, :last_journal_id => ''
-    assert_not_include journal, assigns(:conflict_journals)
-  end
-
-  def test_update_stale_issue_with_overwrite_conflict_resolution_should_update
-    @request.session[:user_id] = 2
-
-    assert_difference 'Journal.count' do
-      put :update, :id => 1,
-            :issue => {
-              :fixed_version_id => 4,
-              :notes => 'overwrite_conflict_resolution',
-              :lock_version => 2
-            },
-            :conflict_resolution => 'overwrite'
-    end
-
-    assert_response 302
-    issue = Issue.find(1)
-    assert_equal 4, issue.fixed_version_id
-    journal = Journal.first(:order => 'id DESC')
-    assert_equal 'overwrite_conflict_resolution', journal.notes
-    assert journal.details.any?
-  end
-
-  def test_update_stale_issue_with_add_notes_conflict_resolution_should_update
-    @request.session[:user_id] = 2
-
-    assert_difference 'Journal.count' do
-      put :update, :id => 1,
-            :issue => {
-              :fixed_version_id => 4,
-              :notes => 'add_notes_conflict_resolution',
-              :lock_version => 2
-            },
-            :conflict_resolution => 'add_notes'
-    end
-
-    assert_response 302
-    issue = Issue.find(1)
-    assert_nil issue.fixed_version_id
-    journal = Journal.first(:order => 'id DESC')
-    assert_equal 'add_notes_conflict_resolution', journal.notes
-    assert journal.details.empty?
-  end
-
-  def test_update_stale_issue_with_cancel_conflict_resolution_should_redirect_without_updating
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Journal.count' do
-      put :update, :id => 1,
-            :issue => {
-              :fixed_version_id => 4,
-              :notes => 'add_notes_conflict_resolution',
-              :lock_version => 2
-            },
-            :conflict_resolution => 'cancel'
-    end
-
-    assert_redirected_to '/issues/1'
-    issue = Issue.find(1)
-    assert_nil issue.fixed_version_id
-  end
-
-  def test_put_update_with_spent_time_and_failure_should_not_add_spent_time
-    @request.session[:user_id] = 2
-
-    assert_no_difference('TimeEntry.count') do
-      put :update,
-           :id => 1,
-           :issue => { :subject => '' },
-           :time_entry => { :hours => '2.5', :comments => 'should not be added', :activity_id => TimeEntryActivity.first.id }
-      assert_response :success
-    end
-
-    assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2.5'
-    assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'should not be added'
-    assert_select 'select[name=?]', 'time_entry[activity_id]' do
-      assert_select 'option[value=?][selected=selected]', TimeEntryActivity.first.id
-    end
-  end
-
-  def test_index_should_rescue_invalid_sql_query
-    IssueQuery.any_instance.stubs(:statement).returns("INVALID STATEMENT")
-
-    get :index
-    assert_response 500
-    assert_tag 'p', :content => /An error occurred/
-    assert_nil session[:query]
-    assert_nil session[:issues_index_sort]
-  end
-end
--- a/.svn/pristine/c5/c58d60a26982a819fdf9b2a65688b42aae5216fc.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingReportsTest < ActionController::IntegrationTest
-  def test_reports
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/issues/report" },
-        { :controller => 'reports', :action => 'issue_report', :id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/issues/report/assigned_to" },
-        { :controller => 'reports', :action => 'issue_report_details',
-          :id => '567', :detail => 'assigned_to' }
-      )
-  end
-end
--- a/.svn/pristine/c6/c6b59a98475e92f48670b041ca8dfc5d4a6c1a5b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-
-begin
-  require 'mocha/setup'
-
-  class SubversionAdapterTest < ActiveSupport::TestCase
-
-    if repository_configured?('subversion')
-      def setup
-        @adapter = Redmine::Scm::Adapters::SubversionAdapter.new(self.class.subversion_repository_url)
-      end
-
-      def test_client_version
-        v = Redmine::Scm::Adapters::SubversionAdapter.client_version
-        assert v.is_a?(Array)
-      end
-
-      def test_scm_version
-        to_test = { "svn, version 1.6.13 (r1002816)\n"  => [1,6,13],
-                    "svn, versione 1.6.13 (r1002816)\n" => [1,6,13],
-                    "1.6.1\n1.7\n1.8"                   => [1,6,1],
-                    "1.6.2\r\n1.8.1\r\n1.9.1"           => [1,6,2]}
-        to_test.each do |s, v|
-          test_scm_version_for(s, v)
-        end
-      end
-
-      def test_info_not_nil
-        assert_not_nil @adapter.info
-      end
-
-      def test_info_nil
-        adpt = Redmine::Scm::Adapters::SubversionAdapter.new(
-                  "file:///invalid/invalid/"
-                  )
-        assert_nil adpt.info
-      end
-
-      private
-
-      def test_scm_version_for(scm_version, version)
-        @adapter.class.expects(:scm_version_from_command_line).returns(scm_version)
-        assert_equal version, @adapter.class.svn_binary_version
-      end
-    else
-      puts "Subversion test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
-    end
-  end
-rescue LoadError
-  class SubversionMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
-  end
-end
--- a/.svn/pristine/c6/c6bb92835cd944a70efc7f1fadbb496a3624fce7.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ApplicationTest < ActionController::IntegrationTest
-  include Redmine::I18n
-
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def test_set_localization
-    Setting.default_language = 'en'
-
-    # a french user
-    get 'projects', { }, 'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
-    assert_response :success
-    assert_tag :tag => 'h2', :content => 'Projets'
-    assert_equal :fr, current_language
-    assert_select "html[lang=?]", "fr"
-
-    # then an italien user
-    get 'projects', { }, 'HTTP_ACCEPT_LANGUAGE' => 'it;q=0.8,en-us;q=0.5,en;q=0.3'
-    assert_response :success
-    assert_tag :tag => 'h2', :content => 'Progetti'
-    assert_equal :it, current_language
-    assert_select "html[lang=?]", "it"
-
-    # not a supported language: default language should be used
-    get 'projects', { }, 'HTTP_ACCEPT_LANGUAGE' => 'zz'
-    assert_response :success
-    assert_tag :tag => 'h2', :content => 'Projects'
-    assert_select "html[lang=?]", "en"
-  end
-
-  def test_token_based_access_should_not_start_session
-    # issue of a private project
-    get 'issues/4.atom'
-    assert_response 302
-
-    rss_key = User.find(2).rss_key
-    get "issues/4.atom?key=#{rss_key}"
-    assert_response 200
-    assert_nil session[:user_id]
-  end
-
-  def test_missing_template_should_respond_with_404
-    get '/login.png'
-    assert_response 404
-  end
-
-  def test_invalid_token_should_call_custom_handler
-    ActionController::Base.allow_forgery_protection = true
-    post '/issues'
-    assert_response 422
-    assert_include "Invalid form authenticity token.", response.body
-  ensure
-    ActionController::Base.allow_forgery_protection = false
-  end
-end
--- a/.svn/pristine/c7/c71c2943a1e92bfbcb19b7e4592c3d8e1f7f80fd.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class Redmine::MenuManager::MapperTest < ActiveSupport::TestCase
-  test "Mapper#initialize should define a root MenuNode if menu is not present in items" do
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    node = menu_mapper.menu_items
-    assert_not_nil node
-    assert_equal :root, node.name
-  end
-
-  test "Mapper#initialize should use existing MenuNode if present" do
-    node = "foo" # just an arbitrary reference
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {:test_menu => node})
-    assert_equal node, menu_mapper.menu_items
-  end
-
-  def test_push_onto_root
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
-
-    menu_mapper.exists?(:test_overview)
-  end
-
-  def test_push_onto_parent
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_child, { :controller => 'projects', :action => 'show'}, {:parent => :test_overview}
-
-    assert menu_mapper.exists?(:test_child)
-    assert_equal :test_child, menu_mapper.find(:test_child).name
-  end
-
-  def test_push_onto_grandparent
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_child, { :controller => 'projects', :action => 'show'}, {:parent => :test_overview}
-    menu_mapper.push :test_grandchild, { :controller => 'projects', :action => 'show'}, {:parent => :test_child}
-
-    assert menu_mapper.exists?(:test_grandchild)
-    grandchild = menu_mapper.find(:test_grandchild)
-    assert_equal :test_grandchild, grandchild.name
-    assert_equal :test_child, grandchild.parent.name
-  end
-
-  def test_push_first
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_second, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_third, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_fourth, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_fifth, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_first, { :controller => 'projects', :action => 'show'}, {:first => true}
-
-    root = menu_mapper.find(:root)
-    assert_equal 5, root.children.size
-    {0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
-      assert_not_nil root.children[position]
-      assert_equal name, root.children[position].name
-    end
-
-  end
-
-  def test_push_before
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_first, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_second, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_fourth, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_fifth, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_third, { :controller => 'projects', :action => 'show'}, {:before => :test_fourth}
-
-    root = menu_mapper.find(:root)
-    assert_equal 5, root.children.size
-    {0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
-      assert_not_nil root.children[position]
-      assert_equal name, root.children[position].name
-    end
-
-  end
-
-  def test_push_after
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_first, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_second, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_third, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_fifth, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_fourth, { :controller => 'projects', :action => 'show'}, {:after => :test_third}
-
-    root = menu_mapper.find(:root)
-    assert_equal 5, root.children.size
-    {0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
-      assert_not_nil root.children[position]
-      assert_equal name, root.children[position].name
-    end
-
-  end
-
-  def test_push_last
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_first, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_second, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_third, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_fifth, { :controller => 'projects', :action => 'show'}, {:last => true}
-    menu_mapper.push :test_fourth, { :controller => 'projects', :action => 'show'}, {}
-
-    root = menu_mapper.find(:root)
-    assert_equal 5, root.children.size
-    {0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
-      assert_not_nil root.children[position]
-      assert_equal name, root.children[position].name
-    end
-
-  end
-
-  def test_exists_for_child_node
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
-    menu_mapper.push :test_child, { :controller => 'projects', :action => 'show'}, {:parent => :test_overview }
-
-    assert menu_mapper.exists?(:test_child)
-  end
-
-  def test_exists_for_invalid_node
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
-
-    assert !menu_mapper.exists?(:nothing)
-  end
-
-  def test_find
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
-
-    item = menu_mapper.find(:test_overview)
-    assert_equal :test_overview, item.name
-    assert_equal({:controller => 'projects', :action => 'show'}, item.url)
-  end
-
-  def test_find_missing
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
-
-    item = menu_mapper.find(:nothing)
-    assert_equal nil, item
-  end
-
-  def test_delete
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
-    assert_not_nil menu_mapper.delete(:test_overview)
-
-    assert_nil menu_mapper.find(:test_overview)
-  end
-
-  def test_delete_missing
-    menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
-    assert_nil menu_mapper.delete(:test_missing)
-  end
-
-  test 'deleting all items' do
-    # Exposed by deleting :last items
-    Redmine::MenuManager.map :test_menu do |menu|
-      menu.push :not_last, Redmine::Info.help_url
-      menu.push :administration, { :controller => 'projects', :action => 'show'}, {:last => true}
-      menu.push :help, Redmine::Info.help_url, :last => true
-    end
-
-    assert_nothing_raised do
-      Redmine::MenuManager.map :test_menu do |menu|
-        menu.delete(:administration)
-        menu.delete(:help)
-        menu.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
-     end
-    end
-  end
-end
--- a/.svn/pristine/c7/c776d4773c045c08108bca39e768c557cd3d3f3c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module RoutesHelper
-
-  # Returns the path to project issues or to the cross-project
-  # issue list if project is nil
-  def _project_issues_path(project, *args)
-    if project
-      project_issues_path(project, *args)
-    else
-      issues_path(*args)
-    end
-  end
-
-  def _project_calendar_path(project, *args)
-    project ? project_calendar_path(project, *args) : issues_calendar_path(*args)
-  end
-
-  def _project_gantt_path(project, *args)
-    project ? project_gantt_path(project, *args) : issues_gantt_path(*args)
-  end
-end
--- a/.svn/pristine/c7/c7cf137c2588796a3073e5736e9e052805b1bb66.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Views
-    class OtherFormatsBuilder
-      def initialize(view)
-        @view = view
-      end
-
-      def link_to(name, options={})
-        url = { :format => name.to_s.downcase }.merge(options.delete(:url) || {}).except('page')
-        caption = options.delete(:caption) || name
-        html_options = { :class => name.to_s.downcase, :rel => 'nofollow' }.merge(options)
-        @view.content_tag('span', @view.link_to(caption, url, html_options))
-      end
-    end
-  end
-end
--- a/.svn/pristine/c8/c8227a12426582a67a866b9030d95a66b9f407a6.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-begin
-  require 'mocha/setup'
-rescue
-  # Won't run some tests
-end
-
-class AccountTest < ActionController::IntegrationTest
-  fixtures :users, :roles
-
-  # Replace this with your real tests.
-  def test_login
-    get "my/page"
-    assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fmy%2Fpage"
-    log_user('jsmith', 'jsmith')
-
-    get "my/account"
-    assert_response :success
-    assert_template "my/account"
-  end
-
-  def test_autologin
-    user = User.find(1)
-    Setting.autologin = "7"
-    Token.delete_all
-
-    # User logs in with 'autologin' checked
-    post '/login', :username => user.login, :password => 'admin', :autologin => 1
-    assert_redirected_to '/my/page'
-    token = Token.first
-    assert_not_nil token
-    assert_equal user, token.user
-    assert_equal 'autologin', token.action
-    assert_equal user.id, session[:user_id]
-    assert_equal token.value, cookies['autologin']
-
-    # Session is cleared
-    reset!
-    User.current = nil
-    # Clears user's last login timestamp
-    user.update_attribute :last_login_on, nil
-    assert_nil user.reload.last_login_on
-
-    # User comes back with user's autologin cookie
-    cookies[:autologin] = token.value
-    get '/my/page'
-    assert_response :success
-    assert_template 'my/page'
-    assert_equal user.id, session[:user_id]
-    assert_not_nil user.reload.last_login_on
-  end
-
-  def test_autologin_should_use_autologin_cookie_name
-    Token.delete_all
-    Redmine::Configuration.stubs(:[]).with('autologin_cookie_name').returns('custom_autologin')
-    Redmine::Configuration.stubs(:[]).with('autologin_cookie_path').returns('/')
-    Redmine::Configuration.stubs(:[]).with('autologin_cookie_secure').returns(false)
-
-    with_settings :autologin => '7' do
-      assert_difference 'Token.count' do
-        post '/login', :username => 'admin', :password => 'admin', :autologin => 1
-      end
-      assert_response 302
-      assert cookies['custom_autologin'].present?
-      token = cookies['custom_autologin']
-
-      # Session is cleared
-      reset!
-      cookies['custom_autologin'] = token
-      get '/my/page'
-      assert_response :success
-
-      assert_difference 'Token.count', -1 do
-        post '/logout'
-      end
-      assert cookies['custom_autologin'].blank?
-    end
-  end
-
-  def test_lost_password
-    Token.delete_all
-
-    get "account/lost_password"
-    assert_response :success
-    assert_template "account/lost_password"
-    assert_select 'input[name=mail]'
-
-    post "account/lost_password", :mail => 'jSmith@somenet.foo'
-    assert_redirected_to "/login"
-
-    token = Token.first
-    assert_equal 'recovery', token.action
-    assert_equal 'jsmith@somenet.foo', token.user.mail
-    assert !token.expired?
-
-    get "account/lost_password", :token => token.value
-    assert_response :success
-    assert_template "account/password_recovery"
-    assert_select 'input[type=hidden][name=token][value=?]', token.value
-    assert_select 'input[name=new_password]'
-    assert_select 'input[name=new_password_confirmation]'
-
-    post "account/lost_password",
-         :token => token.value, :new_password => 'newpass123',
-         :new_password_confirmation => 'newpass123'
-    assert_redirected_to "/login"
-    assert_equal 'Password was successfully updated.', flash[:notice]
-
-    log_user('jsmith', 'newpass123')
-    assert_equal 0, Token.count
-  end
-
-  def test_user_with_must_change_passwd_should_be_forced_to_change_its_password
-    User.find_by_login('jsmith').update_attribute :must_change_passwd, true
-
-    post '/login', :username => 'jsmith', :password => 'jsmith'
-    assert_redirected_to '/my/page'
-    follow_redirect!
-    assert_redirected_to '/my/password'
-
-    get '/issues'
-    assert_redirected_to '/my/password'
-  end
-
-  def test_user_with_must_change_passwd_should_be_able_to_change_its_password
-    User.find_by_login('jsmith').update_attribute :must_change_passwd, true
-
-    post '/login', :username => 'jsmith', :password => 'jsmith'
-    assert_redirected_to '/my/page'
-    follow_redirect!
-    assert_redirected_to '/my/password'
-    follow_redirect!
-    assert_response :success
-    post '/my/password', :password => 'jsmith', :new_password => 'newpassword', :new_password_confirmation => 'newpassword'
-    assert_redirected_to '/my/account'
-    follow_redirect!
-    assert_response :success
-
-    assert_equal false, User.find_by_login('jsmith').must_change_passwd?
-  end
-
-  def test_register_with_automatic_activation
-    Setting.self_registration = '3'
-
-    get 'account/register'
-    assert_response :success
-    assert_template 'account/register'
-
-    post 'account/register',
-         :user => {:login => "newuser", :language => "en",
-                   :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
-                   :password => "newpass123", :password_confirmation => "newpass123"}
-    assert_redirected_to '/my/account'
-    follow_redirect!
-    assert_response :success
-    assert_template 'my/account'
-
-    user = User.find_by_login('newuser')
-    assert_not_nil user
-    assert user.active?
-    assert_not_nil user.last_login_on
-  end
-
-  def test_register_with_manual_activation
-    Setting.self_registration = '2'
-
-    post 'account/register',
-         :user => {:login => "newuser", :language => "en",
-                   :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
-                   :password => "newpass123", :password_confirmation => "newpass123"}
-    assert_redirected_to '/login'
-    assert !User.find_by_login('newuser').active?
-  end
-
-  def test_register_with_email_activation
-    Setting.self_registration = '1'
-    Token.delete_all
-
-    post 'account/register',
-         :user => {:login => "newuser", :language => "en",
-                   :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
-                   :password => "newpass123", :password_confirmation => "newpass123"}
-    assert_redirected_to '/login'
-    assert !User.find_by_login('newuser').active?
-
-    token = Token.first
-    assert_equal 'register', token.action
-    assert_equal 'newuser@foo.bar', token.user.mail
-    assert !token.expired?
-
-    get 'account/activate', :token => token.value
-    assert_redirected_to '/login'
-    log_user('newuser', 'newpass123')
-  end
-
-  def test_onthefly_registration
-    # disable registration
-    Setting.self_registration = '0'
-    AuthSource.expects(:authenticate).returns(
-      {:login => 'foo', :firstname => 'Foo', :lastname => 'Smith',
-       :mail => 'foo@bar.com', :auth_source_id => 66})
-
-    post '/login', :username => 'foo', :password => 'bar'
-    assert_redirected_to '/my/page'
-
-    user = User.find_by_login('foo')
-    assert user.is_a?(User)
-    assert_equal 66, user.auth_source_id
-    assert user.hashed_password.blank?
-  end
-
-  def test_onthefly_registration_with_invalid_attributes
-    # disable registration
-    Setting.self_registration = '0'
-    AuthSource.expects(:authenticate).returns(
-      {:login => 'foo', :lastname => 'Smith', :auth_source_id => 66})
-
-    post '/login', :username => 'foo', :password => 'bar'
-    assert_response :success
-    assert_template 'account/register'
-    assert_tag :input, :attributes => { :name => 'user[firstname]', :value => '' }
-    assert_tag :input, :attributes => { :name => 'user[lastname]', :value => 'Smith' }
-    assert_no_tag :input, :attributes => { :name => 'user[login]' }
-    assert_no_tag :input, :attributes => { :name => 'user[password]' }
-
-    post 'account/register',
-         :user => {:firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com'}
-    assert_redirected_to '/my/account'
-
-    user = User.find_by_login('foo')
-    assert user.is_a?(User)
-    assert_equal 66, user.auth_source_id
-    assert user.hashed_password.blank?
-  end
-
-  def test_registered_user_should_be_able_to_get_a_new_activation_email
-    Token.delete_all
-
-    with_settings :self_registration => '1', :default_language => 'en' do
-      # register a new account
-      assert_difference 'User.count' do
-        assert_difference 'Token.count' do
-          post 'account/register',
-             :user => {:login => "newuser", :language => "en",
-                       :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
-                       :password => "newpass123", :password_confirmation => "newpass123"}
-        end
-      end
-      user = User.order('id desc').first
-      assert_equal User::STATUS_REGISTERED, user.status
-      reset!
-
-      # try to use "lost password"
-      assert_no_difference 'ActionMailer::Base.deliveries.size' do
-        post '/account/lost_password', :mail => 'newuser@foo.bar'
-      end
-      assert_redirected_to '/account/lost_password'
-      follow_redirect!
-      assert_response :success
-      assert_select 'div.flash', :text => /new activation email/
-      assert_select 'div.flash a[href=/account/activation_email]'
-
-      # request a new action activation email
-      assert_difference 'ActionMailer::Base.deliveries.size' do
-        get '/account/activation_email'
-      end
-      assert_redirected_to '/login'
-      token = Token.order('id desc').first
-      activation_path = "/account/activate?token=#{token.value}"
-      assert_include activation_path, mail_body(ActionMailer::Base.deliveries.last)
-
-      # activate the account
-      get activation_path
-      assert_redirected_to '/login'
-
-      post '/login', :username => 'newuser', :password => 'newpass123'
-      assert_redirected_to '/my/page'
-    end
-  end
-end
--- a/.svn/pristine/c8/c8c8b891b8b1a98cd7dec3eea46d3351c5d63dc0.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/darcs_adapter'
-
-class Repository::Darcs < Repository
-  validates_presence_of :url, :log_encoding
-
-  def self.human_attribute_name(attribute_key_name, *args)
-    attr_name = attribute_key_name.to_s
-    if attr_name == "url"
-      attr_name = "path_to_repository"
-    end
-    super(attr_name, *args)
-  end
-
-  def self.scm_adapter_class
-    Redmine::Scm::Adapters::DarcsAdapter
-  end
-
-  def self.scm_name
-    'Darcs'
-  end
-
-  def supports_directory_revisions?
-    true
-  end
-
-  def entry(path=nil, identifier=nil)
-    patch = identifier.nil? ? nil : changesets.find_by_revision(identifier)
-    scm.entry(path, patch.nil? ? nil : patch.scmid)
-  end
-
-  def entries(path=nil, identifier=nil)
-    patch = nil
-    if ! identifier.nil?
-      patch = changesets.find_by_revision(identifier)
-      return nil if patch.nil?
-    end
-    entries = scm.entries(path, patch.nil? ? nil : patch.scmid)
-    if entries
-      entries.each do |entry|
-        # Search the DB for the entry's last change
-        if entry.lastrev && !entry.lastrev.scmid.blank?
-          changeset = changesets.find_by_scmid(entry.lastrev.scmid)
-        end
-        if changeset
-          entry.lastrev.identifier = changeset.revision
-          entry.lastrev.name       = changeset.revision
-          entry.lastrev.time       = changeset.committed_on
-          entry.lastrev.author     = changeset.committer
-        end
-      end
-    end
-    load_entries_changesets(entries)
-    entries
-  end
-
-  def cat(path, identifier=nil)
-    patch = identifier.nil? ? nil : changesets.find_by_revision(identifier.to_s)
-    scm.cat(path, patch.nil? ? nil : patch.scmid)
-  end
-
-  def diff(path, rev, rev_to)
-    patch_from = changesets.find_by_revision(rev)
-    return nil if patch_from.nil?
-    patch_to = changesets.find_by_revision(rev_to) if rev_to
-    if path.blank?
-      path = patch_from.filechanges.collect{|change| change.path}.join(' ')
-    end
-    patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil) : nil
-  end
-
-  def fetch_changesets
-    scm_info = scm.info
-    if scm_info
-      db_last_id = latest_changeset ? latest_changeset.scmid : nil
-      next_rev   = latest_changeset ? latest_changeset.revision.to_i + 1 : 1
-      # latest revision in the repository
-      scm_revision = scm_info.lastrev.scmid
-      unless changesets.find_by_scmid(scm_revision)
-        revisions = scm.revisions('', db_last_id, nil, :with_path => true)
-        transaction do
-          revisions.reverse_each do |revision|
-            changeset = Changeset.create(:repository   => self,
-                                         :revision     => next_rev,
-                                         :scmid        => revision.scmid,
-                                         :committer    => revision.author,
-                                         :committed_on => revision.time,
-                                         :comments     => revision.message)
-            revision.paths.each do |change|
-              changeset.create_change(change)
-            end
-            next_rev += 1
-          end if revisions
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/c8/c8eb9218e8a7b1005bc9738485c7283ea65cf881.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingCustomFieldsTest < ActionController::IntegrationTest
-  def test_custom_fields
-    assert_routing(
-        { :method => 'get', :path => "/custom_fields" },
-        { :controller => 'custom_fields', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/custom_fields/new" },
-        { :controller => 'custom_fields', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/custom_fields" },
-        { :controller => 'custom_fields', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/custom_fields/2/edit" },
-        { :controller => 'custom_fields', :action => 'edit', :id => '2' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/custom_fields/2" },
-        { :controller => 'custom_fields', :action => 'update', :id => '2' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/custom_fields/2" },
-        { :controller => 'custom_fields', :action => 'destroy', :id => '2' }
-      )
-  end
-
-  def test_custom_fields_api
-    assert_routing(
-        { :method => 'get', :path => "/custom_fields.xml" },
-        { :controller => 'custom_fields', :action => 'index', :format => 'xml' }
-      )
-  end
-end
--- a/.svn/pristine/c9/c94378ba0f927a1812044bbae32975e1c8d9db8b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssueRelation < ActiveRecord::Base
-  # Class used to represent the relations of an issue
-  class Relations < Array
-    include Redmine::I18n
-
-    def initialize(issue, *args)
-      @issue = issue
-      super(*args)
-    end
-
-    def to_s(*args)
-      map {|relation| "#{l(relation.label_for(@issue))} ##{relation.other_issue(@issue).id}"}.join(', ')
-    end
-  end
-
-  belongs_to :issue_from, :class_name => 'Issue', :foreign_key => 'issue_from_id'
-  belongs_to :issue_to, :class_name => 'Issue', :foreign_key => 'issue_to_id'
-
-  TYPE_RELATES      = "relates"
-  TYPE_DUPLICATES   = "duplicates"
-  TYPE_DUPLICATED   = "duplicated"
-  TYPE_BLOCKS       = "blocks"
-  TYPE_BLOCKED      = "blocked"
-  TYPE_PRECEDES     = "precedes"
-  TYPE_FOLLOWS      = "follows"
-  TYPE_COPIED_TO    = "copied_to"
-  TYPE_COPIED_FROM  = "copied_from"
-
-  TYPES = {
-    TYPE_RELATES =>     { :name => :label_relates_to, :sym_name => :label_relates_to,
-                          :order => 1, :sym => TYPE_RELATES },
-    TYPE_DUPLICATES =>  { :name => :label_duplicates, :sym_name => :label_duplicated_by,
-                          :order => 2, :sym => TYPE_DUPLICATED },
-    TYPE_DUPLICATED =>  { :name => :label_duplicated_by, :sym_name => :label_duplicates,
-                          :order => 3, :sym => TYPE_DUPLICATES, :reverse => TYPE_DUPLICATES },
-    TYPE_BLOCKS =>      { :name => :label_blocks, :sym_name => :label_blocked_by,
-                          :order => 4, :sym => TYPE_BLOCKED },
-    TYPE_BLOCKED =>     { :name => :label_blocked_by, :sym_name => :label_blocks,
-                          :order => 5, :sym => TYPE_BLOCKS, :reverse => TYPE_BLOCKS },
-    TYPE_PRECEDES =>    { :name => :label_precedes, :sym_name => :label_follows,
-                          :order => 6, :sym => TYPE_FOLLOWS },
-    TYPE_FOLLOWS =>     { :name => :label_follows, :sym_name => :label_precedes,
-                          :order => 7, :sym => TYPE_PRECEDES, :reverse => TYPE_PRECEDES },
-    TYPE_COPIED_TO =>   { :name => :label_copied_to, :sym_name => :label_copied_from,
-                          :order => 8, :sym => TYPE_COPIED_FROM },
-    TYPE_COPIED_FROM => { :name => :label_copied_from, :sym_name => :label_copied_to,
-                          :order => 9, :sym => TYPE_COPIED_TO, :reverse => TYPE_COPIED_TO }
-  }.freeze
-
-  validates_presence_of :issue_from, :issue_to, :relation_type
-  validates_inclusion_of :relation_type, :in => TYPES.keys
-  validates_numericality_of :delay, :allow_nil => true
-  validates_uniqueness_of :issue_to_id, :scope => :issue_from_id
-  validate :validate_issue_relation
-
-  attr_protected :issue_from_id, :issue_to_id
-  before_save :handle_issue_order
-  after_create  :create_journal_after_create
-  after_destroy :create_journal_after_delete
-
-  def visible?(user=User.current)
-    (issue_from.nil? || issue_from.visible?(user)) && (issue_to.nil? || issue_to.visible?(user))
-  end
-
-  def deletable?(user=User.current)
-    visible?(user) &&
-      ((issue_from.nil? || user.allowed_to?(:manage_issue_relations, issue_from.project)) ||
-        (issue_to.nil? || user.allowed_to?(:manage_issue_relations, issue_to.project)))
-  end
-
-  def initialize(attributes=nil, *args)
-    super
-    if new_record?
-      if relation_type.blank?
-        self.relation_type = IssueRelation::TYPE_RELATES
-      end
-    end
-  end
-
-  def validate_issue_relation
-    if issue_from && issue_to
-      errors.add :issue_to_id, :invalid if issue_from_id == issue_to_id
-      unless issue_from.project_id == issue_to.project_id ||
-                Setting.cross_project_issue_relations?
-        errors.add :issue_to_id, :not_same_project
-      end
-      # detect circular dependencies depending wether the relation should be reversed
-      if TYPES.has_key?(relation_type) && TYPES[relation_type][:reverse]
-        errors.add :base, :circular_dependency if issue_from.all_dependent_issues.include? issue_to
-      else
-        errors.add :base, :circular_dependency if issue_to.all_dependent_issues.include? issue_from
-      end
-      if issue_from.is_descendant_of?(issue_to) || issue_from.is_ancestor_of?(issue_to)
-        errors.add :base, :cant_link_an_issue_with_a_descendant
-      end
-    end
-  end
-
-  def other_issue(issue)
-    (self.issue_from_id == issue.id) ? issue_to : issue_from
-  end
-
-  # Returns the relation type for +issue+
-  def relation_type_for(issue)
-    if TYPES[relation_type]
-      if self.issue_from_id == issue.id
-        relation_type
-      else
-        TYPES[relation_type][:sym]
-      end
-    end
-  end
-
-  def label_for(issue)
-    TYPES[relation_type] ?
-        TYPES[relation_type][(self.issue_from_id == issue.id) ? :name : :sym_name] :
-        :unknow
-  end
-
-  def css_classes_for(issue)
-    "rel-#{relation_type_for(issue)}"
-  end
-
-  def handle_issue_order
-    reverse_if_needed
-
-    if TYPE_PRECEDES == relation_type
-      self.delay ||= 0
-    else
-      self.delay = nil
-    end
-    set_issue_to_dates
-  end
-
-  def set_issue_to_dates
-    soonest_start = self.successor_soonest_start
-    if soonest_start && issue_to
-      issue_to.reschedule_on!(soonest_start)
-    end
-  end
-
-  def successor_soonest_start
-    if (TYPE_PRECEDES == self.relation_type) && delay && issue_from &&
-           (issue_from.start_date || issue_from.due_date)
-      (issue_from.due_date || issue_from.start_date) + 1 + delay
-    end
-  end
-
-  def <=>(relation)
-    r = TYPES[self.relation_type][:order] <=> TYPES[relation.relation_type][:order]
-    r == 0 ? id <=> relation.id : r
-  end
-
-  private
-
-  # Reverses the relation if needed so that it gets stored in the proper way
-  # Should not be reversed before validation so that it can be displayed back
-  # as entered on new relation form
-  def reverse_if_needed
-    if TYPES.has_key?(relation_type) && TYPES[relation_type][:reverse]
-      issue_tmp = issue_to
-      self.issue_to = issue_from
-      self.issue_from = issue_tmp
-      self.relation_type = TYPES[relation_type][:reverse]
-    end
-  end
-
-  def create_journal_after_create
-    journal = issue_from.init_journal(User.current)
-    journal.details << JournalDetail.new(:property => 'relation',
-                                         :prop_key => label_for(issue_from).to_s,
-                                         :value    => issue_to.id)
-    journal.save
-    journal = issue_to.init_journal(User.current)
-    journal.details << JournalDetail.new(:property => 'relation',
-                                         :prop_key => label_for(issue_to).to_s,
-                                         :value    => issue_from.id)
-    journal.save
-  end
-
-  def create_journal_after_delete
-    journal = issue_from.init_journal(User.current)
-    journal.details << JournalDetail.new(:property  => 'relation',
-                                         :prop_key  => label_for(issue_from).to_s,
-                                         :old_value => issue_to.id)
-    journal.save
-    journal = issue_to.init_journal(User.current)
-    journal.details << JournalDetail.new(:property  => 'relation',
-                                         :prop_key  => label_for(issue_to).to_s,
-                                         :old_value => issue_from.id)
-    journal.save
-  end
-end
--- a/.svn/pristine/c9/c95a845f51d0458457322e070bfabbc6737ef1a1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class PatchesTest < ActiveSupport::TestCase
-  include Redmine::I18n
-
-  def setup
-    Setting.default_language = 'en'
-  end
-
-  test "ActiveRecord::Base.human_attribute_name should transform name to field_name" do
-    assert_equal l('field_last_login_on'), ActiveRecord::Base.human_attribute_name('last_login_on')
-  end
-
-  test "ActiveRecord::Base.human_attribute_name should cut extra _id suffix for better validation" do
-    assert_equal l('field_last_login_on'), ActiveRecord::Base.human_attribute_name('last_login_on_id')
-  end
-
-  test "ActiveRecord::Base.human_attribute_name should default to humanized value if no translation has been found (useful for custom fields)" do
-    assert_equal 'Patch name', ActiveRecord::Base.human_attribute_name('Patch name')
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/c9/c9a4606fd56695d0574a554ddcfcebb976dd9120.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,190 @@
+/* Redmine - project management software
+   Copyright (C) 2006-2014  Jean-Philippe Lang */
+
+function addFile(inputEl, file, eagerUpload) {
+
+  if ($('#attachments_fields').children().length < 10) {
+
+    var attachmentId = addFile.nextAttachmentId++;
+
+    var fileSpan = $('<span>', { id: 'attachments_' + attachmentId });
+
+    fileSpan.append(
+        $('<input>', { type: 'text', 'class': 'filename readonly', name: 'attachments[' + attachmentId + '][filename]', readonly: 'readonly'} ).val(file.name),
+        $('<input>', { type: 'text', 'class': 'description', name: 'attachments[' + attachmentId + '][description]', maxlength: 255, placeholder: $(inputEl).data('description-placeholder') } ).toggle(!eagerUpload),
+        $('<a>&nbsp</a>').attr({ href: "#", 'class': 'remove-upload' }).click(removeFile).toggle(!eagerUpload)
+    ).appendTo('#attachments_fields');
+
+    if(eagerUpload) {
+      ajaxUpload(file, attachmentId, fileSpan, inputEl);
+    }
+
+    return attachmentId;
+  }
+  return null;
+}
+
+addFile.nextAttachmentId = 1;
+
+function ajaxUpload(file, attachmentId, fileSpan, inputEl) {
+
+  function onLoadstart(e) {
+    fileSpan.removeClass('ajax-waiting');
+    fileSpan.addClass('ajax-loading');
+    $('input:submit', $(this).parents('form')).attr('disabled', 'disabled');
+  }
+
+  function onProgress(e) {
+    if(e.lengthComputable) {
+      this.progressbar( 'value', e.loaded * 100 / e.total );
+    }
+  }
+
+  function actualUpload(file, attachmentId, fileSpan, inputEl) {
+
+    ajaxUpload.uploading++;
+
+    uploadBlob(file, $(inputEl).data('upload-path'), attachmentId, {
+        loadstartEventHandler: onLoadstart.bind(progressSpan),
+        progressEventHandler: onProgress.bind(progressSpan)
+      })
+      .done(function(result) {
+        progressSpan.progressbar( 'value', 100 ).remove();
+        fileSpan.find('input.description, a').css('display', 'inline-block');
+      })
+      .fail(function(result) {
+        progressSpan.text(result.statusText);
+      }).always(function() {
+        ajaxUpload.uploading--;
+        fileSpan.removeClass('ajax-loading');
+        var form = fileSpan.parents('form');
+        if (form.queue('upload').length == 0 && ajaxUpload.uploading == 0) {
+          $('input:submit', form).removeAttr('disabled');
+        }
+        form.dequeue('upload');
+      });
+  }
+
+  var progressSpan = $('<div>').insertAfter(fileSpan.find('input.filename'));
+  progressSpan.progressbar();
+  fileSpan.addClass('ajax-waiting');
+
+  var maxSyncUpload = $(inputEl).data('max-concurrent-uploads');
+
+  if(maxSyncUpload == null || maxSyncUpload <= 0 || ajaxUpload.uploading < maxSyncUpload)
+    actualUpload(file, attachmentId, fileSpan, inputEl);
+  else
+    $(inputEl).parents('form').queue('upload', actualUpload.bind(this, file, attachmentId, fileSpan, inputEl));
+}
+
+ajaxUpload.uploading = 0;
+
+function removeFile() {
+  $(this).parent('span').remove();
+  return false;
+}
+
+function uploadBlob(blob, uploadUrl, attachmentId, options) {
+
+  var actualOptions = $.extend({
+    loadstartEventHandler: $.noop,
+    progressEventHandler: $.noop
+  }, options);
+
+  uploadUrl = uploadUrl + '?attachment_id=' + attachmentId;
+  if (blob instanceof window.File) {
+    uploadUrl += '&filename=' + encodeURIComponent(blob.name);
+  }
+
+  return $.ajax(uploadUrl, {
+    type: 'POST',
+    contentType: 'application/octet-stream',
+    beforeSend: function(jqXhr, settings) {
+      jqXhr.setRequestHeader('Accept', 'application/js');
+      // attach proper File object 
+      settings.data = blob;
+    },
+    xhr: function() {
+      var xhr = $.ajaxSettings.xhr();
+      xhr.upload.onloadstart = actualOptions.loadstartEventHandler;
+      xhr.upload.onprogress = actualOptions.progressEventHandler;
+      return xhr;
+    },
+    data: blob,
+    cache: false,
+    processData: false
+  });
+}
+
+function addInputFiles(inputEl) {
+  var clearedFileInput = $(inputEl).clone().val('');
+
+  if (inputEl.files) {
+    // upload files using ajax
+    uploadAndAttachFiles(inputEl.files, inputEl);
+    $(inputEl).remove();
+  } else {
+    // browser not supporting the file API, upload on form submission
+    var attachmentId;
+    var aFilename = inputEl.value.split(/\/|\\/);
+    attachmentId = addFile(inputEl, { name: aFilename[ aFilename.length - 1 ] }, false);
+    if (attachmentId) {
+      $(inputEl).attr({ name: 'attachments[' + attachmentId + '][file]', style: 'display:none;' }).appendTo('#attachments_' + attachmentId);
+    }
+  }
+
+  clearedFileInput.insertAfter('#attachments_fields').on('change', function(){addInputFiles(this);});
+}
+
+function uploadAndAttachFiles(files, inputEl) {
+
+  var maxFileSize = $(inputEl).data('max-file-size');
+  var maxFileSizeExceeded = $(inputEl).data('max-file-size-message');
+
+  var sizeExceeded = false;
+  $.each(files, function() {
+    if (this.size && maxFileSize != null && this.size > parseInt(maxFileSize)) {sizeExceeded=true;}
+  });
+  if (sizeExceeded) {
+    window.alert(maxFileSizeExceeded);
+  } else {
+    $.each(files, function() {addFile(inputEl, this, true);});
+  }
+}
+
+function handleFileDropEvent(e) {
+
+  $(this).removeClass('fileover');
+  blockEventPropagation(e);
+
+  if ($.inArray('Files', e.dataTransfer.types) > -1) {
+    uploadAndAttachFiles(e.dataTransfer.files, $('input:file.file_selector'));
+  }
+}
+
+function dragOverHandler(e) {
+  $(this).addClass('fileover');
+  blockEventPropagation(e);
+}
+
+function dragOutHandler(e) {
+  $(this).removeClass('fileover');
+  blockEventPropagation(e);
+}
+
+function setupFileDrop() {
+  if (window.File && window.FileList && window.ProgressEvent && window.FormData) {
+
+    $.event.fixHooks.drop = { props: [ 'dataTransfer' ] };
+
+    $('form div.box').has('input:file').each(function() {
+      $(this).on({
+          dragover: dragOverHandler,
+          dragleave: dragOutHandler,
+          drop: handleFileDropEvent
+      });
+    });
+  }
+}
+
+$(document).ready(setupFileDrop);
--- a/.svn/pristine/c9/c9e7983f17ebbef596f0d988a11845f2f8e0840f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module CustomFieldsHelper
-
-  CUSTOM_FIELDS_TABS = [
-    {:name => 'IssueCustomField', :partial => 'custom_fields/index',
-     :label => :label_issue_plural},
-    {:name => 'TimeEntryCustomField', :partial => 'custom_fields/index',
-     :label => :label_spent_time},
-    {:name => 'ProjectCustomField', :partial => 'custom_fields/index',
-     :label => :label_project_plural},
-    {:name => 'VersionCustomField', :partial => 'custom_fields/index',
-     :label => :label_version_plural},
-    {:name => 'UserCustomField', :partial => 'custom_fields/index',
-     :label => :label_user_plural},
-    {:name => 'GroupCustomField', :partial => 'custom_fields/index',
-     :label => :label_group_plural},
-    {:name => 'TimeEntryActivityCustomField', :partial => 'custom_fields/index',
-     :label => TimeEntryActivity::OptionName},
-    {:name => 'IssuePriorityCustomField', :partial => 'custom_fields/index',
-     :label => IssuePriority::OptionName},
-    {:name => 'DocumentCategoryCustomField', :partial => 'custom_fields/index',
-     :label => DocumentCategory::OptionName}
-  ]
-
-  def custom_fields_tabs
-    CUSTOM_FIELDS_TABS
-  end
-
-  # Return custom field html tag corresponding to its format
-  def custom_field_tag(name, custom_value)
-    custom_field = custom_value.custom_field
-    field_name = "#{name}[custom_field_values][#{custom_field.id}]"
-    field_name << "[]" if custom_field.multiple?
-    field_id = "#{name}_custom_field_values_#{custom_field.id}"
-
-    tag_options = {:id => field_id, :class => "#{custom_field.field_format}_cf"}
-
-    field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format)
-    case field_format.try(:edit_as)
-    when "date"
-      text_field_tag(field_name, custom_value.value, tag_options.merge(:size => 10)) +
-      calendar_for(field_id)
-    when "text"
-      text_area_tag(field_name, custom_value.value, tag_options.merge(:rows => 3))
-    when "bool"
-      hidden_field_tag(field_name, '0') + check_box_tag(field_name, '1', custom_value.true?, tag_options)
-    when "list"
-      blank_option = ''.html_safe
-      unless custom_field.multiple?
-        if custom_field.is_required?
-          unless custom_field.default_value.present?
-            blank_option = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---", :value => '')
-          end
-        else
-          blank_option = content_tag('option')
-        end
-      end
-      s = select_tag(field_name, blank_option + options_for_select(custom_field.possible_values_options(custom_value.customized), custom_value.value),
-        tag_options.merge(:multiple => custom_field.multiple?))
-      if custom_field.multiple?
-        s << hidden_field_tag(field_name, '')
-      end
-      s
-    else
-      text_field_tag(field_name, custom_value.value, tag_options)
-    end
-  end
-
-  # Return custom field label tag
-  def custom_field_label_tag(name, custom_value, options={})
-    required = options[:required] || custom_value.custom_field.is_required?
-
-    content_tag "label", h(custom_value.custom_field.name) +
-      (required ? " <span class=\"required\">*</span>".html_safe : ""),
-      :for => "#{name}_custom_field_values_#{custom_value.custom_field.id}"
-  end
-
-  # Return custom field tag with its label tag
-  def custom_field_tag_with_label(name, custom_value, options={})
-    custom_field_label_tag(name, custom_value, options) + custom_field_tag(name, custom_value)
-  end
-
-  def custom_field_tag_for_bulk_edit(name, custom_field, projects=nil, value='')
-    field_name = "#{name}[custom_field_values][#{custom_field.id}]"
-    field_name << "[]" if custom_field.multiple?
-    field_id = "#{name}_custom_field_values_#{custom_field.id}"
-
-    tag_options = {:id => field_id, :class => "#{custom_field.field_format}_cf"}
-
-    unset_tag = ''
-    unless custom_field.is_required?
-      unset_tag = content_tag('label',
-        check_box_tag(field_name, '__none__', (value == '__none__'), :id => nil, :data => {:disables => "##{field_id}"}) + l(:button_clear),
-        :class => 'inline'
-      )
-    end
-
-    field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format)
-    case field_format.try(:edit_as)
-      when "date"
-        text_field_tag(field_name, value, tag_options.merge(:size => 10)) +
-        calendar_for(field_id) +
-        unset_tag
-      when "text"
-        text_area_tag(field_name, value, tag_options.merge(:rows => 3)) +
-        '<br />'.html_safe +
-        unset_tag
-      when "bool"
-        select_tag(field_name, options_for_select([[l(:label_no_change_option), ''],
-                                                   [l(:general_text_yes), '1'],
-                                                   [l(:general_text_no), '0']], value), tag_options)
-      when "list"
-        options = []
-        options << [l(:label_no_change_option), ''] unless custom_field.multiple?
-        options << [l(:label_none), '__none__'] unless custom_field.is_required?
-        options += custom_field.possible_values_options(projects)
-        select_tag(field_name, options_for_select(options, value), tag_options.merge(:multiple => custom_field.multiple?))
-      else
-        text_field_tag(field_name, value, tag_options) +
-        unset_tag
-    end
-  end
-
-  # Return a string used to display a custom value
-  def show_value(custom_value)
-    return "" unless custom_value
-    format_value(custom_value.value, custom_value.custom_field.field_format)
-  end
-
-  # Return a string used to display a custom value
-  def format_value(value, field_format)
-    if value.is_a?(Array)
-      value.collect {|v| format_value(v, field_format)}.compact.sort.join(', ')
-    else
-      Redmine::CustomFieldFormat.format_value(value, field_format)
-    end
-  end
-
-  # Return an array of custom field formats which can be used in select_tag
-  def custom_field_formats_for_select(custom_field)
-    Redmine::CustomFieldFormat.as_select(custom_field.class.customized_class.name)
-  end
-
-  # Renders the custom_values in api views
-  def render_api_custom_values(custom_values, api)
-    api.array :custom_fields do
-      custom_values.each do |custom_value|
-        attrs = {:id => custom_value.custom_field_id, :name => custom_value.custom_field.name}
-        attrs.merge!(:multiple => true) if custom_value.custom_field.multiple?
-        api.custom_field attrs do
-          if custom_value.value.is_a?(Array)
-            api.array :value do
-              custom_value.value.each do |value|
-                api.value value unless value.blank?
-              end
-            end
-          else
-            api.value custom_value.value
-          end
-        end
-      end
-    end unless custom_values.empty?
-  end
-end
--- a/.svn/pristine/ca/ca2690f201462335a7ca37a385b267b1298dce63.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Enumeration < ActiveRecord::Base
-  include Redmine::SubclassFactory
-
-  default_scope :order => "#{Enumeration.table_name}.position ASC"
-
-  belongs_to :project
-
-  acts_as_list :scope => 'type = \'#{type}\''
-  acts_as_customizable
-  acts_as_tree :order => "#{Enumeration.table_name}.position ASC"
-
-  before_destroy :check_integrity
-  before_save    :check_default
-
-  attr_protected :type
-
-  validates_presence_of :name
-  validates_uniqueness_of :name, :scope => [:type, :project_id]
-  validates_length_of :name, :maximum => 30
-
-  scope :shared, lambda { where(:project_id => nil) }
-  scope :sorted, lambda { order("#{table_name}.position ASC") }
-  scope :active, lambda { where(:active => true) }
-  scope :system, lambda { where(:project_id => nil) }
-  scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
-
-  def self.default
-    # Creates a fake default scope so Enumeration.default will check
-    # it's type.  STI subclasses will automatically add their own
-    # types to the finder.
-    if self.descends_from_active_record?
-      where(:is_default => true, :type => 'Enumeration').first
-    else
-      # STI classes are
-      where(:is_default => true).first
-    end
-  end
-
-  # Overloaded on concrete classes
-  def option_name
-    nil
-  end
-
-  def check_default
-    if is_default? && is_default_changed?
-      Enumeration.update_all({:is_default => false}, {:type => type})
-    end
-  end
-
-  # Overloaded on concrete classes
-  def objects_count
-    0
-  end
-
-  def in_use?
-    self.objects_count != 0
-  end
-
-  # Is this enumeration overiding a system level enumeration?
-  def is_override?
-    !self.parent.nil?
-  end
-
-  alias :destroy_without_reassign :destroy
-
-  # Destroy the enumeration
-  # If a enumeration is specified, objects are reassigned
-  def destroy(reassign_to = nil)
-    if reassign_to && reassign_to.is_a?(Enumeration)
-      self.transfer_relations(reassign_to)
-    end
-    destroy_without_reassign
-  end
-
-  def <=>(enumeration)
-    position <=> enumeration.position
-  end
-
-  def to_s; name end
-
-  # Returns the Subclasses of Enumeration.  Each Subclass needs to be
-  # required in development mode.
-  #
-  # Note: subclasses is protected in ActiveRecord
-  def self.get_subclasses
-    subclasses
-  end
-
-  # Does the +new+ Hash override the previous Enumeration?
-  def self.overridding_change?(new, previous)
-    if (same_active_state?(new['active'], previous.active)) && same_custom_values?(new,previous)
-      return false
-    else
-      return true
-    end
-  end
-
-  # Does the +new+ Hash have the same custom values as the previous Enumeration?
-  def self.same_custom_values?(new, previous)
-    previous.custom_field_values.each do |custom_value|
-      if custom_value.value != new["custom_field_values"][custom_value.custom_field_id.to_s]
-        return false
-      end
-    end
-
-    return true
-  end
-
-  # Are the new and previous fields equal?
-  def self.same_active_state?(new, previous)
-    new = (new == "1" ? true : false)
-    return new == previous
-  end
-
-private
-  def check_integrity
-    raise "Can't delete enumeration" if self.in_use?
-  end
-
-end
-
-# Force load the subclasses in development mode
-require_dependency 'time_entry_activity'
-require_dependency 'document_category'
-require_dependency 'issue_priority'
--- a/.svn/pristine/ca/ca5fec371cca9a83b040c882b835088a92221cb9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,846 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
-  fixtures :projects,
-    :users,
-    :roles,
-    :members,
-    :member_roles,
-    :issues,
-    :issue_statuses,
-    :issue_relations,
-    :versions,
-    :trackers,
-    :projects_trackers,
-    :issue_categories,
-    :enabled_modules,
-    :enumerations,
-    :attachments,
-    :workflows,
-    :custom_fields,
-    :custom_values,
-    :custom_fields_projects,
-    :custom_fields_trackers,
-    :time_entries,
-    :journals,
-    :journal_details,
-    :queries,
-    :attachments
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  context "/issues" do
-    # Use a private project to make sure auth is really working and not just
-    # only showing public issues.
-    should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
-
-    should "contain metadata" do
-      get '/issues.xml'
-
-      assert_tag :tag => 'issues',
-        :attributes => {
-          :type => 'array',
-          :total_count => assigns(:issue_count),
-          :limit => 25,
-          :offset => 0
-        }
-    end
-
-    context "with offset and limit" do
-      should "use the params" do
-        get '/issues.xml?offset=2&limit=3'
-
-        assert_equal 3, assigns(:limit)
-        assert_equal 2, assigns(:offset)
-        assert_tag :tag => 'issues', :children => {:count => 3, :only => {:tag => 'issue'}}
-      end
-    end
-
-    context "with nometa param" do
-      should "not contain metadata" do
-        get '/issues.xml?nometa=1'
-
-        assert_tag :tag => 'issues',
-          :attributes => {
-            :type => 'array',
-            :total_count => nil,
-            :limit => nil,
-            :offset => nil
-          }
-      end
-    end
-
-    context "with nometa header" do
-      should "not contain metadata" do
-        get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
-
-        assert_tag :tag => 'issues',
-          :attributes => {
-            :type => 'array',
-            :total_count => nil,
-            :limit => nil,
-            :offset => nil
-          }
-      end
-    end
-
-    context "with relations" do
-      should "display relations" do
-        get '/issues.xml?include=relations'
-
-        assert_response :success
-        assert_equal 'application/xml', @response.content_type
-        assert_tag 'relations',
-          :parent => {:tag => 'issue', :child => {:tag => 'id', :content => '3'}},
-          :children => {:count => 1},
-          :child => {
-            :tag => 'relation',
-            :attributes => {:id => '2', :issue_id => '2', :issue_to_id => '3',
-                            :relation_type => 'relates'}
-          }
-        assert_tag 'relations',
-          :parent => {:tag => 'issue', :child => {:tag => 'id', :content => '1'}},
-          :children => {:count => 0}
-      end
-    end
-
-    context "with invalid query params" do
-      should "return errors" do
-        get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}}
-
-        assert_response :unprocessable_entity
-        assert_equal 'application/xml', @response.content_type
-        assert_tag 'errors', :child => {:tag => 'error', :content => "Start date can't be blank"}
-      end
-    end
-
-    context "with custom field filter" do
-      should "show only issues with the custom field value" do
-        get '/issues.xml',
-            {:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='},
-             :v => {:cf_1 => ['MySQL']}}
-        expected_ids = Issue.visible.
-            joins(:custom_values).
-            where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
-        assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
-           ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
-        end
-      end
-    end
-
-    context "with custom field filter (shorthand method)" do
-      should "show only issues with the custom field value" do
-        get '/issues.xml', { :cf_1 => 'MySQL' }
-
-        expected_ids = Issue.visible.
-            joins(:custom_values).
-            where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
-
-        assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
-          ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
-        end
-      end
-    end
-  end
-
-  context "/index.json" do
-    should_allow_api_authentication(:get, "/projects/private-child/issues.json")
-  end
-
-  context "/index.xml with filter" do
-    should "show only issues with the status_id" do
-      get '/issues.xml?status_id=5'
-
-      expected_ids = Issue.visible.where(:status_id => 5).map(&:id)
-
-      assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
-         ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
-      end
-    end
-  end
-
-  context "/index.json with filter" do
-    should "show only issues with the status_id" do
-      get '/issues.json?status_id=5'
-
-      json = ActiveSupport::JSON.decode(response.body)
-      status_ids_used = json['issues'].collect {|j| j['status']['id'] }
-      assert_equal 3, status_ids_used.length
-      assert status_ids_used.all? {|id| id == 5 }
-    end
-
-  end
-
-  # Issue 6 is on a private project
-  context "/issues/6.xml" do
-    should_allow_api_authentication(:get, "/issues/6.xml")
-  end
-
-  context "/issues/6.json" do
-    should_allow_api_authentication(:get, "/issues/6.json")
-  end
-
-  context "GET /issues/:id" do
-    context "with journals" do
-      context ".xml" do
-        should "display journals" do
-          get '/issues/1.xml?include=journals'
-
-          assert_tag :tag => 'issue',
-            :child => {
-              :tag => 'journals',
-              :attributes => { :type => 'array' },
-              :child => {
-                :tag => 'journal',
-                :attributes => { :id => '1'},
-                :child => {
-                  :tag => 'details',
-                  :attributes => { :type => 'array' },
-                  :child => {
-                    :tag => 'detail',
-                    :attributes => { :name => 'status_id' },
-                    :child => {
-                      :tag => 'old_value',
-                      :content => '1',
-                      :sibling => {
-                        :tag => 'new_value',
-                        :content => '2'
-                      }
-                    }
-                  }
-                }
-              }
-            }
-        end
-      end
-    end
-
-    context "with custom fields" do
-      context ".xml" do
-        should "display custom fields" do
-          get '/issues/3.xml'
-
-          assert_tag :tag => 'issue',
-            :child => {
-              :tag => 'custom_fields',
-              :attributes => { :type => 'array' },
-              :child => {
-                :tag => 'custom_field',
-                :attributes => { :id => '1'},
-                :child => {
-                  :tag => 'value',
-                  :content => 'MySQL'
-                }
-              }
-            }
-
-          assert_nothing_raised do
-            Hash.from_xml(response.body).to_xml
-          end
-        end
-      end
-    end
-
-    context "with multi custom fields" do
-      setup do
-        field = CustomField.find(1)
-        field.update_attribute :multiple, true
-        issue = Issue.find(3)
-        issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
-        issue.save!
-      end
-
-      context ".xml" do
-        should "display custom fields" do
-          get '/issues/3.xml'
-          assert_response :success
-          assert_tag :tag => 'issue',
-            :child => {
-              :tag => 'custom_fields',
-              :attributes => { :type => 'array' },
-              :child => {
-                :tag => 'custom_field',
-                :attributes => { :id => '1'},
-                :child => {
-                  :tag => 'value',
-                  :attributes => { :type => 'array' },
-                  :children => { :count => 2 }
-                }
-              }
-            }
-
-          xml = Hash.from_xml(response.body)
-          custom_fields = xml['issue']['custom_fields']
-          assert_kind_of Array, custom_fields
-          field = custom_fields.detect {|f| f['id'] == '1'}
-          assert_kind_of Hash, field
-          assert_equal ['MySQL', 'Oracle'], field['value'].sort
-        end
-      end
-
-      context ".json" do
-        should "display custom fields" do
-          get '/issues/3.json'
-          assert_response :success
-          json = ActiveSupport::JSON.decode(response.body)
-          custom_fields = json['issue']['custom_fields']
-          assert_kind_of Array, custom_fields
-          field = custom_fields.detect {|f| f['id'] == 1}
-          assert_kind_of Hash, field
-          assert_equal ['MySQL', 'Oracle'], field['value'].sort
-        end
-      end
-    end
-
-    context "with empty value for multi custom field" do
-      setup do
-        field = CustomField.find(1)
-        field.update_attribute :multiple, true
-        issue = Issue.find(3)
-        issue.custom_field_values = {1 => ['']}
-        issue.save!
-      end
-
-      context ".xml" do
-        should "display custom fields" do
-          get '/issues/3.xml'
-          assert_response :success
-          assert_tag :tag => 'issue',
-            :child => {
-              :tag => 'custom_fields',
-              :attributes => { :type => 'array' },
-              :child => {
-                :tag => 'custom_field',
-                :attributes => { :id => '1'},
-                :child => {
-                  :tag => 'value',
-                  :attributes => { :type => 'array' },
-                  :children => { :count => 0 }
-                }
-              }
-            }
-
-          xml = Hash.from_xml(response.body)
-          custom_fields = xml['issue']['custom_fields']
-          assert_kind_of Array, custom_fields
-          field = custom_fields.detect {|f| f['id'] == '1'}
-          assert_kind_of Hash, field
-          assert_equal [], field['value']
-        end
-      end
-
-      context ".json" do
-        should "display custom fields" do
-          get '/issues/3.json'
-          assert_response :success
-          json = ActiveSupport::JSON.decode(response.body)
-          custom_fields = json['issue']['custom_fields']
-          assert_kind_of Array, custom_fields
-          field = custom_fields.detect {|f| f['id'] == 1}
-          assert_kind_of Hash, field
-          assert_equal [], field['value'].sort
-        end
-      end
-    end
-
-    context "with attachments" do
-      context ".xml" do
-        should "display attachments" do
-          get '/issues/3.xml?include=attachments'
-
-          assert_tag :tag => 'issue',
-            :child => {
-              :tag => 'attachments',
-              :children => {:count => 5},
-              :child => {
-                :tag => 'attachment',
-                :child => {
-                  :tag => 'filename',
-                  :content => 'source.rb',
-                  :sibling => {
-                    :tag => 'content_url',
-                    :content => 'http://www.example.com/attachments/download/4/source.rb'
-                  }
-                }
-              }
-            }
-        end
-      end
-    end
-
-    context "with subtasks" do
-      setup do
-        @c1 = Issue.create!(
-                :status_id => 1, :subject => "child c1",
-                :tracker_id => 1, :project_id => 1, :author_id => 1,
-                :parent_issue_id => 1
-              )
-        @c2 = Issue.create!(
-                :status_id => 1, :subject => "child c2",
-                :tracker_id => 1, :project_id => 1, :author_id => 1,
-                :parent_issue_id => 1
-              )
-        @c3 = Issue.create!(
-                :status_id => 1, :subject => "child c3",
-                :tracker_id => 1, :project_id => 1, :author_id => 1,
-                :parent_issue_id => @c1.id
-              )
-      end
-
-      context ".xml" do
-        should "display children" do
-          get '/issues/1.xml?include=children'
-
-          assert_tag :tag => 'issue',
-            :child => {
-              :tag => 'children',
-              :children => {:count => 2},
-              :child => {
-                :tag => 'issue',
-                :attributes => {:id => @c1.id.to_s},
-                :child => {
-                  :tag => 'subject',
-                  :content => 'child c1',
-                  :sibling => {
-                    :tag => 'children',
-                    :children => {:count => 1},
-                    :child => {
-                      :tag => 'issue',
-                      :attributes => {:id => @c3.id.to_s}
-                    }
-                  }
-                }
-              }
-            }
-        end
-
-        context ".json" do
-          should "display children" do
-            get '/issues/1.json?include=children'
-
-            json = ActiveSupport::JSON.decode(response.body)
-            assert_equal([
-              {
-                'id' => @c1.id, 'subject' => 'child c1', 'tracker' => {'id' => 1, 'name' => 'Bug'},
-                'children' => [{'id' => @c3.id, 'subject' => 'child c3',
-                                'tracker' => {'id' => 1, 'name' => 'Bug'} }]
-              },
-              { 'id' => @c2.id, 'subject' => 'child c2', 'tracker' => {'id' => 1, 'name' => 'Bug'} }
-              ],
-              json['issue']['children'])
-          end
-        end
-      end
-    end
-  end
-
-  test "GET /issues/:id.xml?include=watchers should include watchers" do
-    Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
-
-    get '/issues/1.xml?include=watchers', {}, credentials('jsmith')
-
-    assert_response :ok
-    assert_equal 'application/xml', response.content_type
-    assert_select 'issue' do
-      assert_select 'watchers', Issue.find(1).watchers.count
-      assert_select 'watchers' do
-        assert_select 'user[id=3]'
-      end
-    end
-  end
-
-  context "POST /issues.xml" do
-    should_allow_api_authentication(
-      :post,
-      '/issues.xml',
-      {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
-      {:success_code => :created}
-    )
-    should "create an issue with the attributes" do
-      assert_difference('Issue.count') do
-        post '/issues.xml',
-             {:issue => {:project_id => 1, :subject => 'API test',
-              :tracker_id => 2, :status_id => 3}}, credentials('jsmith')
-      end
-      issue = Issue.first(:order => 'id DESC')
-      assert_equal 1, issue.project_id
-      assert_equal 2, issue.tracker_id
-      assert_equal 3, issue.status_id
-      assert_equal 'API test', issue.subject
-
-      assert_response :created
-      assert_equal 'application/xml', @response.content_type
-      assert_tag 'issue', :child => {:tag => 'id', :content => issue.id.to_s}
-    end
-  end
-
-  test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
-    assert_difference('Issue.count') do
-      post '/issues.xml',
-           {:issue => {:project_id => 1, :subject => 'Watchers',
-            :tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]}}, credentials('jsmith')
-      assert_response :created
-    end
-    issue = Issue.order('id desc').first
-    assert_equal 2, issue.watchers.size
-    assert_equal [1, 3], issue.watcher_user_ids.sort
-  end
-
-  context "POST /issues.xml with failure" do
-    should "have an errors tag" do
-      assert_no_difference('Issue.count') do
-        post '/issues.xml', {:issue => {:project_id => 1}}, credentials('jsmith')
-      end
-
-      assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
-    end
-  end
-
-  context "POST /issues.json" do
-    should_allow_api_authentication(:post,
-                                    '/issues.json',
-                                    {:issue => {:project_id => 1, :subject => 'API test',
-                                     :tracker_id => 2, :status_id => 3}},
-                                    {:success_code => :created})
-
-    should "create an issue with the attributes" do
-      assert_difference('Issue.count') do
-        post '/issues.json',
-             {:issue => {:project_id => 1, :subject => 'API test',
-                         :tracker_id => 2, :status_id => 3}},
-             credentials('jsmith')
-      end
-
-      issue = Issue.first(:order => 'id DESC')
-      assert_equal 1, issue.project_id
-      assert_equal 2, issue.tracker_id
-      assert_equal 3, issue.status_id
-      assert_equal 'API test', issue.subject
-    end
-
-  end
-
-  context "POST /issues.json with failure" do
-    should "have an errors element" do
-      assert_no_difference('Issue.count') do
-        post '/issues.json', {:issue => {:project_id => 1}}, credentials('jsmith')
-      end
-
-      json = ActiveSupport::JSON.decode(response.body)
-      assert json['errors'].include?("Subject can't be blank")
-    end
-  end
-
-  # Issue 6 is on a private project
-  context "PUT /issues/6.xml" do
-    setup do
-      @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
-    end
-
-    should_allow_api_authentication(:put,
-                                    '/issues/6.xml',
-                                    {:issue => {:subject => 'API update', :notes => 'A new note'}},
-                                    {:success_code => :ok})
-
-    should "not create a new issue" do
-      assert_no_difference('Issue.count') do
-        put '/issues/6.xml', @parameters, credentials('jsmith')
-      end
-    end
-
-    should "create a new journal" do
-      assert_difference('Journal.count') do
-        put '/issues/6.xml', @parameters, credentials('jsmith')
-      end
-    end
-
-    should "add the note to the journal" do
-      put '/issues/6.xml', @parameters, credentials('jsmith')
-
-      journal = Journal.last
-      assert_equal "A new note", journal.notes
-    end
-
-    should "update the issue" do
-      put '/issues/6.xml', @parameters, credentials('jsmith')
-
-      issue = Issue.find(6)
-      assert_equal "API update", issue.subject
-    end
-
-  end
-
-  context "PUT /issues/3.xml with custom fields" do
-    setup do
-      @parameters = {
-        :issue => {:custom_fields => [{'id' => '1', 'value' => 'PostgreSQL' },
-        {'id' => '2', 'value' => '150'}]}
-      }
-    end
-
-    should "update custom fields" do
-      assert_no_difference('Issue.count') do
-        put '/issues/3.xml', @parameters, credentials('jsmith')
-      end
-
-      issue = Issue.find(3)
-      assert_equal '150', issue.custom_value_for(2).value
-      assert_equal 'PostgreSQL', issue.custom_value_for(1).value
-    end
-  end
-
-  context "PUT /issues/3.xml with multi custom fields" do
-    setup do
-      field = CustomField.find(1)
-      field.update_attribute :multiple, true
-      @parameters = {
-        :issue => {:custom_fields => [{'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
-        {'id' => '2', 'value' => '150'}]}
-      }
-    end
-
-    should "update custom fields" do
-      assert_no_difference('Issue.count') do
-        put '/issues/3.xml', @parameters, credentials('jsmith')
-      end
-
-      issue = Issue.find(3)
-      assert_equal '150', issue.custom_value_for(2).value
-      assert_equal ['MySQL', 'PostgreSQL'], issue.custom_field_value(1).sort
-    end
-  end
-
-  context "PUT /issues/3.xml with project change" do
-    setup do
-      @parameters = {:issue => {:project_id => 2, :subject => 'Project changed'}}
-    end
-
-    should "update project" do
-      assert_no_difference('Issue.count') do
-        put '/issues/3.xml', @parameters, credentials('jsmith')
-      end
-
-      issue = Issue.find(3)
-      assert_equal 2, issue.project_id
-      assert_equal 'Project changed', issue.subject
-    end
-  end
-
-  context "PUT /issues/6.xml with failed update" do
-    setup do
-      @parameters = {:issue => {:subject => ''}}
-    end
-
-    should "not create a new issue" do
-      assert_no_difference('Issue.count') do
-        put '/issues/6.xml', @parameters, credentials('jsmith')
-      end
-    end
-
-    should "not create a new journal" do
-      assert_no_difference('Journal.count') do
-        put '/issues/6.xml', @parameters, credentials('jsmith')
-      end
-    end
-
-    should "have an errors tag" do
-      put '/issues/6.xml', @parameters, credentials('jsmith')
-
-      assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
-    end
-  end
-
-  context "PUT /issues/6.json" do
-    setup do
-      @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
-    end
-
-    should_allow_api_authentication(:put,
-                                    '/issues/6.json',
-                                    {:issue => {:subject => 'API update', :notes => 'A new note'}},
-                                    {:success_code => :ok})
-
-    should "update the issue" do
-      assert_no_difference('Issue.count') do
-        assert_difference('Journal.count') do
-          put '/issues/6.json', @parameters, credentials('jsmith')
-
-          assert_response :ok
-          assert_equal '', response.body
-        end
-      end
-
-      issue = Issue.find(6)
-      assert_equal "API update", issue.subject
-      journal = Journal.last
-      assert_equal "A new note", journal.notes
-    end
-  end
-
-  context "PUT /issues/6.json with failed update" do
-    should "return errors" do
-      assert_no_difference('Issue.count') do
-        assert_no_difference('Journal.count') do
-          put '/issues/6.json', {:issue => {:subject => ''}}, credentials('jsmith')
-
-          assert_response :unprocessable_entity
-        end
-      end
-
-      json = ActiveSupport::JSON.decode(response.body)
-      assert json['errors'].include?("Subject can't be blank")
-    end
-  end
-
-  context "DELETE /issues/1.xml" do
-    should_allow_api_authentication(:delete,
-                                    '/issues/6.xml',
-                                    {},
-                                    {:success_code => :ok})
-
-    should "delete the issue" do
-      assert_difference('Issue.count', -1) do
-        delete '/issues/6.xml', {}, credentials('jsmith')
-
-        assert_response :ok
-        assert_equal '', response.body
-      end
-
-      assert_nil Issue.find_by_id(6)
-    end
-  end
-
-  context "DELETE /issues/1.json" do
-    should_allow_api_authentication(:delete,
-                                    '/issues/6.json',
-                                    {},
-                                    {:success_code => :ok})
-
-    should "delete the issue" do
-      assert_difference('Issue.count', -1) do
-        delete '/issues/6.json', {}, credentials('jsmith')
-
-        assert_response :ok
-        assert_equal '', response.body
-      end
-
-      assert_nil Issue.find_by_id(6)
-    end
-  end
-
-  test "POST /issues/:id/watchers.xml should add watcher" do
-    assert_difference 'Watcher.count' do
-      post '/issues/1/watchers.xml', {:user_id => 3}, credentials('jsmith')
-
-      assert_response :ok
-      assert_equal '', response.body
-    end
-    watcher = Watcher.order('id desc').first
-    assert_equal Issue.find(1), watcher.watchable
-    assert_equal User.find(3), watcher.user
-  end
-
-  test "DELETE /issues/:id/watchers/:user_id.xml should remove watcher" do
-    Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
-
-    assert_difference 'Watcher.count', -1 do
-      delete '/issues/1/watchers/3.xml', {}, credentials('jsmith')
-
-      assert_response :ok
-      assert_equal '', response.body
-    end
-    assert_equal false, Issue.find(1).watched_by?(User.find(3))
-  end
-
-  def test_create_issue_with_uploaded_file
-    set_tmp_attachments_directory
-    # upload the file
-    assert_difference 'Attachment.count' do
-      post '/uploads.xml', 'test_create_with_upload',
-           {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
-      assert_response :created
-    end
-    xml = Hash.from_xml(response.body)
-    token = xml['upload']['token']
-    attachment = Attachment.first(:order => 'id DESC')
-
-    # create the issue with the upload's token
-    assert_difference 'Issue.count' do
-      post '/issues.xml',
-           {:issue => {:project_id => 1, :subject => 'Uploaded file',
-                       :uploads => [{:token => token, :filename => 'test.txt',
-                                     :content_type => 'text/plain'}]}},
-           credentials('jsmith')
-      assert_response :created
-    end
-    issue = Issue.first(:order => 'id DESC')
-    assert_equal 1, issue.attachments.count
-    assert_equal attachment, issue.attachments.first
-
-    attachment.reload
-    assert_equal 'test.txt', attachment.filename
-    assert_equal 'text/plain', attachment.content_type
-    assert_equal 'test_create_with_upload'.size, attachment.filesize
-    assert_equal 2, attachment.author_id
-
-    # get the issue with its attachments
-    get "/issues/#{issue.id}.xml", :include => 'attachments'
-    assert_response :success
-    xml = Hash.from_xml(response.body)
-    attachments = xml['issue']['attachments']
-    assert_kind_of Array, attachments
-    assert_equal 1, attachments.size
-    url = attachments.first['content_url']
-    assert_not_nil url
-
-    # download the attachment
-    get url
-    assert_response :success
-  end
-
-  def test_update_issue_with_uploaded_file
-    set_tmp_attachments_directory
-    # upload the file
-    assert_difference 'Attachment.count' do
-      post '/uploads.xml', 'test_upload_with_upload',
-           {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
-      assert_response :created
-    end
-    xml = Hash.from_xml(response.body)
-    token = xml['upload']['token']
-    attachment = Attachment.first(:order => 'id DESC')
-
-    # update the issue with the upload's token
-    assert_difference 'Journal.count' do
-      put '/issues/1.xml',
-          {:issue => {:notes => 'Attachment added',
-                      :uploads => [{:token => token, :filename => 'test.txt',
-                                    :content_type => 'text/plain'}]}},
-          credentials('jsmith')
-      assert_response :ok
-      assert_equal '', @response.body
-    end
-
-    issue = Issue.find(1)
-    assert_include attachment, issue.attachments
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/ca/ca8b0f9fbdc1a332f4c2f4861ef22155d5ef176c.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,33 @@
+<span id="attachments_fields">
+<% if defined?(container) && container && container.saved_attachments %>
+  <% container.saved_attachments.each_with_index do |attachment, i| %>
+    <span id="attachments_p<%= i %>">
+      <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename') +
+          text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 255, :placeholder => l(:label_optional_description), :class => 'description') +
+          link_to('&nbsp;'.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') %>
+      <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
+    </span>
+  <% end %>
+<% end %>
+</span>
+<span class="add_attachment">
+<%= file_field_tag 'attachments[dummy][file]',
+      :id => nil,
+      :class => 'file_selector',
+      :multiple => true,
+      :data => {
+        :max_file_size => Setting.attachment_max_size.to_i.kilobytes,
+        :max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
+        :max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
+        :upload_path => uploads_path(:format => 'js'),
+        :description_placeholder => l(:label_optional_description)
+      } %>
+(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
+</span>
+<%= javascript_tag do %>
+  $('input.file_selector').on('change', function(){addInputFiles(this);});
+<% end %>
+
+<% content_for :header_tags do %>
+  <%= javascript_include_tag 'attachments' %>
+<% end %>
--- a/.svn/pristine/cb/cbbbbf51cf00f3931cd57d857e449b95b77320ca.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Tracker < ActiveRecord::Base
-
-  CORE_FIELDS_UNDISABLABLE = %w(project_id tracker_id subject description priority_id is_private).freeze
-  # Fields that can be disabled
-  # Other (future) fields should be appended, not inserted!
-  CORE_FIELDS = %w(assigned_to_id category_id fixed_version_id parent_issue_id start_date due_date estimated_hours done_ratio).freeze
-  CORE_FIELDS_ALL = (CORE_FIELDS_UNDISABLABLE + CORE_FIELDS).freeze
-
-  before_destroy :check_integrity
-  has_many :issues
-  has_many :workflow_rules, :dependent => :delete_all do
-    def copy(source_tracker)
-      WorkflowRule.copy(source_tracker, nil, proxy_association.owner, nil)
-    end
-  end
-
-  has_and_belongs_to_many :projects
-  has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => "#{table_name_prefix}custom_fields_trackers#{table_name_suffix}", :association_foreign_key => 'custom_field_id'
-  acts_as_list
-
-  attr_protected :fields_bits
-
-  validates_presence_of :name
-  validates_uniqueness_of :name
-  validates_length_of :name, :maximum => 30
-
-  scope :sorted, lambda { order("#{table_name}.position ASC") }
-  scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
-
-  def to_s; name end
-
-  def <=>(tracker)
-    position <=> tracker.position
-  end
-
-  # Returns an array of IssueStatus that are used
-  # in the tracker's workflows
-  def issue_statuses
-    if @issue_statuses
-      return @issue_statuses
-    elsif new_record?
-      return []
-    end
-
-    ids = WorkflowTransition.
-            connection.select_rows("SELECT DISTINCT old_status_id, new_status_id FROM #{WorkflowTransition.table_name} WHERE tracker_id = #{id} AND type = 'WorkflowTransition'").
-            flatten.
-            uniq
-
-    @issue_statuses = IssueStatus.find_all_by_id(ids).sort
-  end
-
-  def disabled_core_fields
-    i = -1
-    @disabled_core_fields ||= CORE_FIELDS.select { i += 1; (fields_bits || 0) & (2 ** i) != 0}
-  end
-
-  def core_fields
-    CORE_FIELDS - disabled_core_fields
-  end
-
-  def core_fields=(fields)
-    raise ArgumentError.new("Tracker.core_fields takes an array") unless fields.is_a?(Array)
-
-    bits = 0
-    CORE_FIELDS.each_with_index do |field, i|
-      unless fields.include?(field)
-        bits |= 2 ** i
-      end
-    end
-    self.fields_bits = bits
-    @disabled_core_fields = nil
-    core_fields
-  end
-
-  # Returns the fields that are disabled for all the given trackers
-  def self.disabled_core_fields(trackers)
-    if trackers.present?
-      trackers.uniq.map(&:disabled_core_fields).reduce(:&)
-    else
-      []
-    end
-  end
-
-  # Returns the fields that are enabled for one tracker at least
-  def self.core_fields(trackers)
-    if trackers.present?
-      trackers.uniq.map(&:core_fields).reduce(:|)
-    else
-      CORE_FIELDS.dup
-    end
-  end
-
-private
-  def check_integrity
-    raise Exception.new("Can't delete tracker") if Issue.where(:tracker_id => self.id).any?
-  end
-end
--- a/.svn/pristine/cd/cd13f3dd427937eb092253330df74831980a985d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingMembersTest < ActionController::IntegrationTest
-  def test_members
-    assert_routing(
-        { :method => 'get', :path => "/projects/5234/memberships.xml" },
-        { :controller => 'members', :action => 'index', :project_id => '5234', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/memberships/5234.xml" },
-        { :controller => 'members', :action => 'show', :id => '5234', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/5234/memberships" },
-        { :controller => 'members', :action => 'create', :project_id => '5234' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/5234/memberships.xml" },
-        { :controller => 'members', :action => 'create', :project_id => '5234', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/memberships/5234" },
-        { :controller => 'members', :action => 'update', :id => '5234' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/memberships/5234.xml" },
-        { :controller => 'members', :action => 'update', :id => '5234', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/memberships/5234" },
-        { :controller => 'members', :action => 'destroy', :id => '5234' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/memberships/5234.xml" },
-        { :controller => 'members', :action => 'destroy', :id => '5234', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/5234/memberships/autocomplete" },
-        { :controller => 'members', :action => 'autocomplete', :project_id => '5234' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/5234/memberships/autocomplete.js" },
-        { :controller => 'members', :action => 'autocomplete', :project_id => '5234', :format => 'js' }
-      )
-  end
-end
--- a/.svn/pristine/cf/cf88629896a4d2bfd151981d52eb19dc48c7487b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class SettingTest < ActiveSupport::TestCase
-
-  def teardown
-    Setting.clear_cache
-  end
-
-  def test_read_default
-    assert_equal "Redmine", Setting.app_title
-    assert Setting.self_registration?
-    assert !Setting.login_required?
-  end
-
-  def test_update
-    Setting.app_title = "My title"
-    assert_equal "My title", Setting.app_title
-    # make sure db has been updated (INSERT)
-    assert_equal "My title", Setting.find_by_name('app_title').value
-
-    Setting.app_title = "My other title"
-    assert_equal "My other title", Setting.app_title
-    # make sure db has been updated (UPDATE)
-    assert_equal "My other title", Setting.find_by_name('app_title').value
-  end
-
-  def test_serialized_setting
-    Setting.notified_events = ['issue_added', 'issue_updated', 'news_added']
-    assert_equal ['issue_added', 'issue_updated', 'news_added'], Setting.notified_events
-    assert_equal ['issue_added', 'issue_updated', 'news_added'], Setting.find_by_name('notified_events').value
-  end
-
-  def test_setting_should_be_reloaded_after_clear_cache
-    Setting.app_title = "My title"
-    assert_equal "My title", Setting.app_title
-
-    s = Setting.find_by_name("app_title")
-    s.value = 'New title'
-    s.save!
-    assert_equal "My title", Setting.app_title
-
-    Setting.clear_cache
-    assert_equal "New title", Setting.app_title
-  end
-
-  def test_per_page_options_array_should_be_an_empty_array_when_setting_is_blank
-    with_settings :per_page_options => nil do
-      assert_equal [], Setting.per_page_options_array
-    end
-
-    with_settings :per_page_options => '' do
-      assert_equal [], Setting.per_page_options_array
-    end
-  end
-
-  def test_per_page_options_array_should_be_an_array_of_integers
-    with_settings :per_page_options => '10, 25, 50' do
-      assert_equal [10, 25, 50], Setting.per_page_options_array
-    end
-  end
-
-  def test_per_page_options_array_should_omit_non_numerial_values
-    with_settings :per_page_options => 'a, 25, 50' do
-      assert_equal [25, 50], Setting.per_page_options_array
-    end
-  end
-
-  def test_per_page_options_array_should_be_sorted
-    with_settings :per_page_options => '25, 10, 50' do
-      assert_equal [10, 25, 50], Setting.per_page_options_array
-    end
-  end
-end
--- a/.svn/pristine/cf/cf95716aca909d9dc04cf88a70448176a0b10143.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class FilesController < ApplicationController
-  menu_item :files
-
-  before_filter :find_project_by_project_id
-  before_filter :authorize
-
-  helper :sort
-  include SortHelper
-
-  def index
-    sort_init 'filename', 'asc'
-    sort_update 'filename' => "#{Attachment.table_name}.filename",
-                'created_on' => "#{Attachment.table_name}.created_on",
-                'size' => "#{Attachment.table_name}.filesize",
-                'downloads' => "#{Attachment.table_name}.downloads"
-
-    @containers = [ Project.includes(:attachments).reorder(sort_clause).find(@project.id)]
-    @containers += @project.versions.includes(:attachments).reorder(sort_clause).all.sort.reverse
-    render :layout => !request.xhr?
-  end
-
-  def new
-    @versions = @project.versions.sort
-  end
-
-  def create
-    container = (params[:version_id].blank? ? @project : @project.versions.find_by_id(params[:version_id]))
-    attachments = Attachment.attach_files(container, params[:attachments])
-    render_attachment_warning_if_needed(container)
-
-    if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
-      Mailer.attachments_added(attachments[:files]).deliver
-    end
-    redirect_to project_files_path(@project)
-  end
-end
--- a/.svn/pristine/cf/cf99c613decbc54df4a99c63e23764d371ea8fbc.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssueCategoriesController < ApplicationController
-  menu_item :settings
-  model_object IssueCategory
-  before_filter :find_model_object, :except => [:index, :new, :create]
-  before_filter :find_project_from_association, :except => [:index, :new, :create]
-  before_filter :find_project_by_project_id, :only => [:index, :new, :create]
-  before_filter :authorize
-  accept_api_auth :index, :show, :create, :update, :destroy
-
-  def index
-    respond_to do |format|
-      format.html { redirect_to_settings_in_projects }
-      format.api { @categories = @project.issue_categories.all }
-    end
-  end
-
-  def show
-    respond_to do |format|
-      format.html { redirect_to_settings_in_projects }
-      format.api
-    end
-  end
-
-  def new
-    @category = @project.issue_categories.build
-    @category.safe_attributes = params[:issue_category]
-
-    respond_to do |format|
-      format.html
-      format.js
-    end
-  end
-
-  def create
-    @category = @project.issue_categories.build
-    @category.safe_attributes = params[:issue_category]
-    if @category.save
-      respond_to do |format|
-        format.html do
-          flash[:notice] = l(:notice_successful_create)
-          redirect_to_settings_in_projects
-        end
-        format.js
-        format.api { render :action => 'show', :status => :created, :location => issue_category_path(@category) }
-      end
-    else
-      respond_to do |format|
-        format.html { render :action => 'new'}
-        format.js   { render :action => 'new'}
-        format.api { render_validation_errors(@category) }
-      end
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    @category.safe_attributes = params[:issue_category]
-    if @category.save
-      respond_to do |format|
-        format.html {
-          flash[:notice] = l(:notice_successful_update)
-          redirect_to_settings_in_projects
-        }
-        format.api { render_api_ok }
-      end
-    else
-      respond_to do |format|
-        format.html { render :action => 'edit' }
-        format.api { render_validation_errors(@category) }
-      end
-    end
-  end
-
-  def destroy
-    @issue_count = @category.issues.size
-    if @issue_count == 0 || params[:todo] || api_request?
-      reassign_to = nil
-      if params[:reassign_to_id] && (params[:todo] == 'reassign' || params[:todo].blank?)
-        reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id])
-      end
-      @category.destroy(reassign_to)
-      respond_to do |format|
-        format.html { redirect_to_settings_in_projects }
-        format.api { render_api_ok }
-      end
-      return
-    end
-    @categories = @project.issue_categories - [@category]
-  end
-
-  private
-
-  def redirect_to_settings_in_projects
-    redirect_to settings_project_path(@project, :tab => 'categories')
-  end
-
-  # Wrap ApplicationController's find_model_object method to set
-  # @category instead of just @issue_category
-  def find_model_object
-    super
-    @category = @object
-  end
-end
--- a/.svn/pristine/cf/cfa38091d70dac5ed0710a8ebb3ecb812073f2f5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Activity
-    # Class used to retrieve activity events
-    class Fetcher
-      attr_reader :user, :project, :scope
-
-      # Needs to be unloaded in development mode
-      @@constantized_providers = Hash.new {|h,k| h[k] = Redmine::Activity.providers[k].collect {|t| t.constantize } }
-
-      def initialize(user, options={})
-        options.assert_valid_keys(:project, :with_subprojects, :author)
-        @user = user
-        @project = options[:project]
-        @options = options
-
-        @scope = event_types
-      end
-
-      # Returns an array of available event types
-      def event_types
-        return @event_types unless @event_types.nil?
-
-        @event_types = Redmine::Activity.available_event_types
-        @event_types = @event_types.select {|o| @project.self_and_descendants.detect {|p| @user.allowed_to?("view_#{o}".to_sym, p)}} if @project
-        @event_types
-      end
-
-      # Yields to filter the activity scope
-      def scope_select(&block)
-        @scope = @scope.select {|t| yield t }
-      end
-
-      # Sets the scope
-      # Argument can be :all, :default or an array of event types
-      def scope=(s)
-        case s
-        when :all
-          @scope = event_types
-        when :default
-          default_scope!
-        else
-          @scope = s & event_types
-        end
-      end
-
-      # Resets the scope to the default scope
-      def default_scope!
-        @scope = Redmine::Activity.default_event_types
-      end
-
-      # Returns an array of events for the given date range
-      # sorted in reverse chronological order
-      def events(from = nil, to = nil, options={})
-        e = []
-        @options[:limit] = options[:limit]
-
-        @scope.each do |event_type|
-          constantized_providers(event_type).each do |provider|
-            e += provider.find_events(event_type, @user, from, to, @options)
-          end
-        end
-
-        e.sort! {|a,b| b.event_datetime <=> a.event_datetime}
-
-        if options[:limit]
-          e = e.slice(0, options[:limit])
-        end
-        e
-      end
-
-      private
-
-      def constantized_providers(event_type)
-        @@constantized_providers[event_type]
-      end
-    end
-  end
-end
--- a/.svn/pristine/d0/d009627e726f03a1c296b163bb2546a76eb0de0f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingProjectsTest < ActionController::IntegrationTest
-  def test_projects
-    assert_routing(
-        { :method => 'get', :path => "/projects" },
-        { :controller => 'projects', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects.atom" },
-        { :controller => 'projects', :action => 'index', :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects.xml" },
-        { :controller => 'projects', :action => 'index', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/new" },
-        { :controller => 'projects', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/test" },
-        { :controller => 'projects', :action => 'show', :id => 'test' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/1.xml" },
-        { :controller => 'projects', :action => 'show', :id => '1',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/4223/settings" },
-        { :controller => 'projects', :action => 'settings', :id => '4223' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/4223/settings/members" },
-        { :controller => 'projects', :action => 'settings', :id => '4223',
-          :tab => 'members' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects" },
-        { :controller => 'projects', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects.xml" },
-        { :controller => 'projects', :action => 'create', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/64/archive" },
-        { :controller => 'projects', :action => 'archive', :id => '64' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/64/unarchive" },
-        { :controller => 'projects', :action => 'unarchive', :id => '64' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/64/close" },
-        { :controller => 'projects', :action => 'close', :id => '64' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/64/reopen" },
-        { :controller => 'projects', :action => 'reopen', :id => '64' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/projects/4223" },
-        { :controller => 'projects', :action => 'update', :id => '4223' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/projects/1.xml" },
-        { :controller => 'projects', :action => 'update', :id => '1',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/projects/64" },
-        { :controller => 'projects', :action => 'destroy', :id => '64' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/projects/1.xml" },
-        { :controller => 'projects', :action => 'destroy', :id => '1',
-          :format => 'xml' }
-      )
-  end
-end
--- a/.svn/pristine/d0/d06e7cefb510a385899794a94c740218a4fb9cd9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module GroupsHelper
-  def group_settings_tabs
-    tabs = [{:name => 'general', :partial => 'groups/general', :label => :label_general},
-            {:name => 'users', :partial => 'groups/users', :label => :label_user_plural},
-            {:name => 'memberships', :partial => 'groups/memberships', :label => :label_project_plural}
-            ]
-  end
-
-  def render_principals_for_new_group_users(group)
-    scope = User.active.sorted.not_in_group(group).like(params[:q])
-    principal_count = scope.count
-    principal_pages = Redmine::Pagination::Paginator.new principal_count, 100, params['page']
-    principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
-
-    s = content_tag('div', principals_check_box_tags('user_ids[]', principals), :id => 'principals')
-
-    links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
-      link_to text, autocomplete_for_user_group_path(group, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
-    }
-
-    s + content_tag('p', links, :class => 'pagination')
-  end
-end
--- a/.svn/pristine/d0/d0bea3c38e05e7624a7186faf67962c248869550.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,302 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  # Class used to parse unified diffs
-  class UnifiedDiff < Array
-    attr_reader :diff_type, :diff_style
-
-    def initialize(diff, options={})
-      options.assert_valid_keys(:type, :style, :max_lines)
-      diff = diff.split("\n") if diff.is_a?(String)
-      @diff_type = options[:type] || 'inline'
-      @diff_style = options[:style]
-      lines = 0
-      @truncated = false
-      diff_table = DiffTable.new(diff_type, diff_style)
-      diff.each do |line_raw|
-        line = Redmine::CodesetUtil.to_utf8_by_setting(line_raw)
-        unless diff_table.add_line(line)
-          self << diff_table if diff_table.length > 0
-          diff_table = DiffTable.new(diff_type, diff_style)
-        end
-        lines += 1
-        if options[:max_lines] && lines > options[:max_lines]
-          @truncated = true
-          break
-        end
-      end
-      self << diff_table unless diff_table.empty?
-      self
-    end
-
-    def truncated?; @truncated; end
-  end
-
-  # Class that represents a file diff
-  class DiffTable < Array
-    attr_reader :file_name
-
-    # Initialize with a Diff file and the type of Diff View
-    # The type view must be inline or sbs (side_by_side)
-    def initialize(type="inline", style=nil)
-      @parsing = false
-      @added = 0
-      @removed = 0
-      @type = type
-      @style = style
-      @file_name = nil
-      @git_diff = false
-    end
-
-    # Function for add a line of this Diff
-    # Returns false when the diff ends
-    def add_line(line)
-      unless @parsing
-        if line =~ /^(---|\+\+\+) (.*)$/
-          self.file_name = $2
-        elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
-          @line_num_l = $2.to_i
-          @line_num_r = $5.to_i
-          @parsing = true
-        end
-      else
-        if line =~ %r{^[^\+\-\s@\\]}
-          @parsing = false
-          return false
-        elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
-          @line_num_l = $2.to_i
-          @line_num_r = $5.to_i
-        else
-          parse_line(line, @type)
-        end
-      end
-      return true
-    end
-
-    def each_line
-      prev_line_left, prev_line_right = nil, nil
-      each do |line|
-        spacing = prev_line_left && prev_line_right && (line.nb_line_left != prev_line_left+1) && (line.nb_line_right != prev_line_right+1)
-        yield spacing, line
-        prev_line_left = line.nb_line_left.to_i if line.nb_line_left.to_i > 0
-        prev_line_right = line.nb_line_right.to_i if line.nb_line_right.to_i > 0
-      end
-    end
-
-    def inspect
-      puts '### DIFF TABLE ###'
-      puts "file : #{file_name}"
-      self.each do |d|
-        d.inspect
-      end
-    end
-
-    private
-
-    def file_name=(arg)
-      both_git_diff = false
-      if file_name.nil?
-        @git_diff = true if arg =~ %r{^(a/|/dev/null)}
-      else
-        both_git_diff = (@git_diff && arg =~ %r{^(b/|/dev/null)})
-      end
-      if both_git_diff
-        if file_name && arg == "/dev/null"
-          # keep the original file name
-          @file_name = file_name.sub(%r{^a/}, '')
-        else
-          # remove leading b/
-          @file_name = arg.sub(%r{^b/}, '')
-        end
-      elsif @style == "Subversion"
-        # removing trailing "(revision nn)"
-        @file_name = arg.sub(%r{\t+\(.*\)$}, '')
-      else
-        @file_name = arg
-      end
-    end
-
-    def diff_for_added_line
-      if @type == 'sbs' && @removed > 0 && @added < @removed
-        self[-(@removed - @added)]
-      else
-        diff = Diff.new
-        self << diff
-        diff
-      end
-    end
-
-    def parse_line(line, type="inline")
-      if line[0, 1] == "+"
-        diff = diff_for_added_line
-        diff.line_right = line[1..-1]
-        diff.nb_line_right = @line_num_r
-        diff.type_diff_right = 'diff_in'
-        @line_num_r += 1
-        @added += 1
-        true
-      elsif line[0, 1] == "-"
-        diff = Diff.new
-        diff.line_left = line[1..-1]
-        diff.nb_line_left = @line_num_l
-        diff.type_diff_left = 'diff_out'
-        self << diff
-        @line_num_l += 1
-        @removed += 1
-        true
-      else
-        write_offsets
-        if line[0, 1] =~ /\s/
-          diff = Diff.new
-          diff.line_right = line[1..-1]
-          diff.nb_line_right = @line_num_r
-          diff.line_left = line[1..-1]
-          diff.nb_line_left = @line_num_l
-          self << diff
-          @line_num_l += 1
-          @line_num_r += 1
-          true
-        elsif line[0, 1] = "\\"
-          true
-        else
-          false
-        end
-      end
-    end
-
-    def write_offsets
-      if @added > 0 && @added == @removed
-        @added.times do |i|
-          line = self[-(1 + i)]
-          removed = (@type == 'sbs') ? line : self[-(1 + @added + i)]
-          offsets = offsets(removed.line_left, line.line_right)
-          removed.offsets = line.offsets = offsets
-        end
-      end
-      @added = 0
-      @removed = 0
-    end
-
-    def offsets(line_left, line_right)
-      if line_left.present? && line_right.present? && line_left != line_right
-        max = [line_left.size, line_right.size].min
-        starting = 0
-        while starting < max && line_left[starting] == line_right[starting]
-          starting += 1
-        end
-        if (! "".respond_to?(:force_encoding)) && starting < line_left.size
-          while line_left[starting].ord.between?(128, 191) && starting > 0
-            starting -= 1
-          end
-        end
-        ending = -1
-        while ending >= -(max - starting) && (line_left[ending] == line_right[ending])
-          ending -= 1
-        end
-        if (! "".respond_to?(:force_encoding)) && ending > (-1 * line_left.size)
-          while line_left[ending].ord.between?(128, 255) && ending < -1
-            if line_left[ending].ord.between?(128, 191)
-              if line_left[ending + 1].ord.between?(128, 191)
-                ending += 1
-              else
-                break
-              end
-            else
-              ending += 1
-            end
-          end
-        end
-        unless starting == 0 && ending == -1
-          [starting, ending]
-        end
-      end
-    end
-  end
-
-  # A line of diff
-  class Diff
-    attr_accessor :nb_line_left
-    attr_accessor :line_left
-    attr_accessor :nb_line_right
-    attr_accessor :line_right
-    attr_accessor :type_diff_right
-    attr_accessor :type_diff_left
-    attr_accessor :offsets
-
-    def initialize()
-      self.nb_line_left = ''
-      self.nb_line_right = ''
-      self.line_left = ''
-      self.line_right = ''
-      self.type_diff_right = ''
-      self.type_diff_left = ''
-    end
-
-    def type_diff
-      type_diff_right == 'diff_in' ? type_diff_right : type_diff_left
-    end
-
-    def line
-      type_diff_right == 'diff_in' ? line_right : line_left
-    end
-
-    def html_line_left
-      line_to_html(line_left, offsets)
-    end
-
-    def html_line_right
-      line_to_html(line_right, offsets)
-    end
-
-    def html_line
-      line_to_html(line, offsets)
-    end
-
-    def inspect
-      puts '### Start Line Diff ###'
-      puts self.nb_line_left
-      puts self.line_left
-      puts self.nb_line_right
-      puts self.line_right
-    end
-
-    private
-
-    def line_to_html(line, offsets)
-      html = line_to_html_raw(line, offsets)
-      html.force_encoding('UTF-8') if html.respond_to?(:force_encoding)
-      html
-    end
-
-    def line_to_html_raw(line, offsets)
-      if offsets
-        s = ''
-        unless offsets.first == 0
-          s << CGI.escapeHTML(line[0..offsets.first-1])
-        end
-        s << '<span>' + CGI.escapeHTML(line[offsets.first..offsets.last]) + '</span>'
-        unless offsets.last == -1
-          s << CGI.escapeHTML(line[offsets.last+1..-1])
-        end
-        s
-      else
-        CGI.escapeHTML(line)
-      end
-    end
-  end
-end
--- a/.svn/pristine/d0/d0ce7856bd86e4cf6960ce56a6e054a535f90e1e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::IssueRelationsTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :issue_relations
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /issues/:issue_id/relations.xml should return issue relations" do
-    get '/issues/9/relations.xml', {}, credentials('jsmith')
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-
-    assert_tag :tag => 'relations',
-      :attributes => { :type => 'array' },
-      :child => {
-        :tag => 'relation',
-        :child => {
-          :tag => 'id',
-          :content => '1'
-        }
-      }
-  end
-
-  test "POST /issues/:issue_id/relations.xml should create the relation" do
-    assert_difference('IssueRelation.count') do
-      post '/issues/2/relations.xml', {:relation => {:issue_to_id => 7, :relation_type => 'relates'}}, credentials('jsmith')
-    end
-
-    relation = IssueRelation.first(:order => 'id DESC')
-    assert_equal 2, relation.issue_from_id
-    assert_equal 7, relation.issue_to_id
-    assert_equal 'relates', relation.relation_type
-
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'relation', :child => {:tag => 'id', :content => relation.id.to_s}
-  end
-
-  test "POST /issues/:issue_id/relations.xml with failure should return errors" do
-    assert_no_difference('IssueRelation.count') do
-      post '/issues/2/relations.xml', {:relation => {:issue_to_id => 7, :relation_type => 'foo'}}, credentials('jsmith')
-    end
-
-    assert_response :unprocessable_entity
-    assert_tag :errors, :child => {:tag => 'error', :content => /relation_type is not included in the list/}
-  end
-
-  test "GET /relations/:id.xml should return the relation" do
-    get '/relations/2.xml', {}, credentials('jsmith')
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'relation', :child => {:tag => 'id', :content => '2'}
-  end
-
-  test "DELETE /relations/:id.xml should delete the relation" do
-    assert_difference('IssueRelation.count', -1) do
-      delete '/relations/2.xml', {}, credentials('jsmith')
-    end
-
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_nil IssueRelation.find_by_id(2)
-  end
-end
--- a/.svn/pristine/d1/d102e2042fa5903bbabfc16fdf04c8a155faa793.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Wiki < ActiveRecord::Base
-  include Redmine::SafeAttributes
-  belongs_to :project
-  has_many :pages, :class_name => 'WikiPage', :dependent => :destroy, :order => 'title'
-  has_many :redirects, :class_name => 'WikiRedirect', :dependent => :delete_all
-
-  acts_as_watchable
-
-  validates_presence_of :start_page
-  validates_format_of :start_page, :with => /\A[^,\.\/\?\;\|\:]*\z/
-
-  safe_attributes 'start_page'
-
-  def visible?(user=User.current)
-    !user.nil? && user.allowed_to?(:view_wiki_pages, project)
-  end
-
-  # Returns the wiki page that acts as the sidebar content
-  # or nil if no such page exists
-  def sidebar
-    @sidebar ||= find_page('Sidebar', :with_redirect => false)
-  end
-
-  # find the page with the given title
-  # if page doesn't exist, return a new page
-  def find_or_new_page(title)
-    title = start_page if title.blank?
-    find_page(title) || WikiPage.new(:wiki => self, :title => Wiki.titleize(title))
-  end
-
-  # find the page with the given title
-  def find_page(title, options = {})
-    @page_found_with_redirect = false
-    title = start_page if title.blank?
-    title = Wiki.titleize(title)
-    page = pages.where("LOWER(title) = LOWER(?)", title).first
-    if !page && !(options[:with_redirect] == false)
-      # search for a redirect
-      redirect = redirects.where("LOWER(title) = LOWER(?)", title).first
-      if redirect
-        page = find_page(redirect.redirects_to, :with_redirect => false)
-        @page_found_with_redirect = true
-      end
-    end
-    page
-  end
-
-  # Returns true if the last page was found with a redirect
-  def page_found_with_redirect?
-    @page_found_with_redirect
-  end
-
-  # Finds a page by title
-  # The given string can be of one of the forms: "title" or "project:title"
-  # Examples:
-  #   Wiki.find_page("bar", project => foo)
-  #   Wiki.find_page("foo:bar")
-  def self.find_page(title, options = {})
-    project = options[:project]
-    if title.to_s =~ %r{^([^\:]+)\:(.*)$}
-      project_identifier, title = $1, $2
-      project = Project.find_by_identifier(project_identifier) || Project.find_by_name(project_identifier)
-    end
-    if project && project.wiki
-      page = project.wiki.find_page(title)
-      if page && page.content
-        page
-      end
-    end
-  end
-
-  # turn a string into a valid page title
-  def self.titleize(title)
-    # replace spaces with _ and remove unwanted caracters
-    title = title.gsub(/\s+/, '_').delete(',./?;|:') if title
-    # upcase the first letter
-    title = (title.slice(0..0).upcase + (title.slice(1..-1) || '')) if title
-    title
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/d1/d118d601fbdc765e4b097715615b532bc2112521.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,2682 @@
+== Redmine changelog
+
+Redmine - project management software
+Copyright (C) 2006-2014  Jean-Philippe Lang
+http://www.redmine.org/
+
+== 2014-07-06 v2.4.6
+
+* Defect #13932: File upload does not work with Safari
+* Defect #16467: back_url redirection does not work for '/'
+* Defect #16511: Potentiel data leak in "Invalid form authenticity token" error screen
+* Defect #16530: back_url redirection work for non sub uri
+* Defect #16711: Non-ascii attachment file name get corrupted in IE11
+* Defect #17151: File upload broken on Chrome 36
+* Defect #17235: use test_email report can't modify frozen String
+* Defect #17391: Upgrade to Rails 3.2.19
+* Patch #17206: Fix Invalid CSS on Error-Pages
+
+== 2014-03-29 v2.4.5
+
+* Defect #16466: Fixed back url verification
+
+== 2014-03-02 v2.4.4
+
+* Defect #16081: Export CSV - Custom field true/false not using translation
+* Defect #16161: Parent task search and datepicker not available after changing status
+* Defect #16169: Wrong validation when updating integer custom field with spaces
+* Defect #16177: Mercurial 2.9 compatibility
+
+== 2014-02-08 v2.4.3
+
+* Defect #13544: Commit reference: autogenerated issue note has wrong commit link syntax in multi-repo or cross-project context
+* Defect #15664: Unable to upload attachments without add_issues, edit_issues or add_issue_notes permission
+* Defect #15756: 500 on admin info/settings page on development environment
+* Defect #15781: Customfields have a noticable impact on search performance due to slow database COUNT
+* Defect #15849: Redmine:Fetch_Changesets Single-inheritance issue in subclass "Repository:Git"
+* Defect #15870: Parent task completion is 104% after update of subtasks
+* Defect #16032: Repository.fetch_changesets > app/models/repository/git.rb:137:in `[]=': string not matched (IndexError)
+* Defect #16038: Issue#css_classes corrupts user.groups association cache
+* Patch #15960: pt-BR translation for 2.4-stable
+
+Additional note:
+
+#15781 was forgotten to merge to v2.4.3.
+It is in v2.5.0.
+
+== 2013-12-23 v2.4.2
+
+* Defect #15398: HTML 5 invalid <center> tag
+* Defect #15523: CSS class for done ratio is not properly generated
+* Defect #15623: Timelog filtering by activity field does not handle project activity overrides
+* Defect #15677: Links for relations in notifications do not include hostname
+* Defect #15684: MailHandler : text/plain attachments are added to description
+* Defect #15714: Notification on loosing assignment does not work
+* Defect #15735: OpenID login fails due to CSRF verification
+* Defect #15741: Multiple scrollbars in project selection tree
+* Patch #9442: Russian wiki syntax help translations
+* Patch #15524: Japanese translation update (r12278)
+* Patch #15601: Turkish translation update
+* Patch #15688: Spanish translation updated
+* Patch #15696: Russian translation update
+
+== 2013-11-23 v2.4.1
+
+* Defect #15401: Wiki syntax "bold italic" is incorrect
+* Defect #15414: Empty sidebar should not be displayed in project overview
+* Defect #15427: REST API POST and PUT broken
+* Patch #15376: Traditional Chinese translation (to r12295)
+* Patch #15395: German "ImageMagick convert available" translation
+* Patch #15400: Czech Wiki syntax traslation
+* Patch #15402: Czech translation for 2.4-stable
+
+== 2013-11-17 v2.4.0
+
+* Defect #1983: statistics get rather cramped with more than 15 or so contributers
+* Defect #7335: Sorting issues in gantt by date, not by id
+* Defect #12681: Treat group assignments as assigned to me
+* Defect #12824: Useless "edit" link in workflow menu
+* Defect #13260: JQuery Datepicker popup is missing multiple month/year modifiers
+* Defect #13537: Filters will show issues with unused custom fields.
+* Defect #13829: Favicon bug in IE8
+* Defect #13949: Handling of attachment uploads when 'Maximum attachment size' is set to 0
+* Defect #13989: Trac and Mantis importers reset global notification settings
+* Defect #13990: Trac importer breaks on exotic filenames and ruby 1.9+
+* Defect #14028: Plugins Gemfiles loading breaks __FILE__
+* Defect #14086: Better handling of issue start date validation
+* Defect #14206: Synchronize the lang attribute of the HTML with the display language
+* Defect #14403: No error message if notification mail could not delivered
+* Defect #14516: Missing Sort Column Label and Center Align on Admin-Enumerations
+* Defect #14517: Missing Html Tile on Admin (Groups, LDAP and Plugins)
+* Defect #14598: Wrong test with logger.info in model mail_handler
+* Defect #14615: Warn me when leaving a page with unsaved text doesn't work when editing an update note
+* Defect #14621: AJAX call on the issue form resets data entered during the request
+* Defect #14657: Wrong German translation for member inheritance
+* Defect #14773: ActiveRecord::Acts::Versioned::ActMethods#next_version Generates ArgumentError
+* Defect #14819: Newlines in attachment filename causes crash
+* Defect #14986: 500 error when viewing a wiki page without WikiContent
+* Defect #14995: Japanese "notice_not_authorized" translation is incorrect
+* Defect #15044: Patch for giving controller_issues_edit_after_save api hook the correct context
+* Defect #15050: redmine:migrate_from_mantis fails to migrate projects with all upper case name
+* Defect #15058: Project authorization EnabledModule N+1 queries
+* Defect #15113: The mail method should return a Mail::Message
+* Defect #15135: Issue#update_nested_set_attributes comparing nil with empty string
+* Defect #15191: HTML 5 validation failures
+* Defect #15227: Custom fields in issue form - splitting is incorrect
+* Defect #15307: HTML 5 deprecates width and align attributes
+* Feature #1005: Add the addition/removal/change of related issues to the history
+* Feature #1019: Role based custom queries
+* Feature #1391: Ability to force user to change password
+* Feature #2199: Ability to clear dates and text fields when bulk editing issues
+* Feature #2427: Document horizontal rule syntax
+* Feature #2795: Add a "Cancel" button to the "Delete" project page when deleting a project.
+* Feature #2865: One click filter in search view
+* Feature #3413: Exclude attachments from incoming emails based on file name
+* Feature #3872: New user password - better functionality
+* Feature #4911: Multiple issue update rules with different keywords in commit messages
+* Feature #5037: Role-based issue custom field visibility
+* Feature #7590: Different commit Keywords for each tracker
+* Feature #7836: Ability to save Gantt query filters
+* Feature #8253: Update CodeRay to 1.1 final
+* Feature #11159: REST API for getting CustomField definitions
+* Feature #12293: Add links to attachments in new issue email notification
+* Feature #12912: Issue-notes Redmine links: append actual note reference to rendered links
+* Feature #13157: Link on "My Page" to view all my spent time
+* Feature #13746: Highlighting of source link target line
+* Feature #13943: Better handling of validation errors when bulk editing issues
+* Feature #13945: Disable autofetching of repository changesets if projects are closed
+* Feature #14024: Default of issue start and due date
+* Feature #14060: Enable configuration of OpenIdAuthentication.store
+* Feature #14228: Registered users should have a way to get a new action email
+* Feature #14614: View hooks for user preferences
+* Feature #14630: wiki_syntax.html per language (wiki help localization mechanism)
+* Feature #15136: Activate Custom Fields on a selection of projects directly from Custom fields page
+* Feature #15182: Return to section anchor after wiki section edit
+* Feature #15218: Update Rails 3.2.15
+* Feature #15311: Add an indication to admin/info whether or not ImageMagick convert is available
+* Patch #6689: Document project-links in parse_redmine_links
+* Patch #13460: All translations: RSS -> Atom
+* Patch #13482: Do not add empty header/footer to notification emails
+* Patch #13528: Traditional Chinese "label_total_time" translation
+* Patch #13551: update Dutch translations - March 2013
+* Patch #13577: Japanese translation improvement ("done ratio")
+* Patch #13646: Fix handling multiple text parts in email
+* Patch #13674: Lithuanian translation
+* Patch #13687: Favicon bug in opera browser
+* Patch #13697: Back-button on diff page is not working when I'm directed from email
+* Patch #13745: Correct translation for member save button
+* Patch #13808: Changed Bulgarian "label_statistics" translation
+* Patch #13825: German translation: jquery.ui.datepicker-de.js
+* Patch #13900: Update URL when changing tab
+* Patch #13931: Error and inconsistencies in Croatian translation
+* Patch #13948: REST API should return user.status
+* Patch #13988: Enhanced Arabic translation
+* Patch #14138: Output changeset comment in html title
+* Patch #14180: Improve pt-BR translation
+* Patch #14222: German translation: grammar + spelling
+* Patch #14223: Fix icon transparency issues
+* Patch #14360: Slovene language translation
+* Patch #14767: More CSS classes on various fields
+* Patch #14901: Slovak translation
+* Patch #14920: Russian numeric translation
+* Patch #14981: Italian translation
+* Patch #15072: Optimization of issues journal custom fields display
+* Patch #15073: list custom fields : multiple select filter wider
+* Patch #15075: Fix typo in the Dutch "label_user_mail_option_all" translation
+* Patch #15277: Accept custom field format added at runtime
+* Patch #15295: Log error messages when moving attachements in sub-directories
+* Patch #15369: Bulgarian translation (r12278)
+
+== 2013-11-17 v2.3.4
+
+* Defect #13348: Repository tree can't handle two loading at once
+* Defect #13632: Empty page attached when exporting PDF
+* Defect #14590: migrate_from_trac.rake does not import Trac users, uses too short password
+* Defect #14656: JRuby: Encoding error when creating issues
+* Defect #14883: Update activerecord-jdbc-adapter
+* Defect #14902: Potential invalid SQL error with invalid group_ids
+* Defect #14931: SCM annotate with non ASCII author
+* Defect #14960: migrate_from_mantis.rake does not import Mantis users, uses too short password
+* Defect #14977: Internal Server Error while uploading file
+* Defect #15190: JS-error while using a global custom query w/ project filter in a project context
+* Defect #15235: Wiki Pages REST API with version returns wrong comments
+* Defect #15344: Default status always inserted to allowed statuses when changing status
+* Feature #14919: Update ruby-openid version above 2.3.0
+* Patch #14592: migrate_from_trac.rake does not properly parse First Name and Last Name
+* Patch #14886: Norweigan - label_copied_to and label_copied_from translated
+* Patch #15185: Simplified Chinese translation for 2.3-stable
+
+== 2013-09-14 v2.3.3
+
+* Defect #13008: Usage of attribute_present? in UserPreference
+* Defect #14340: Autocomplete fields rendering issue with alternate theme
+* Defect #14366: Spent Time report sorting on custom fields causes error
+* Defect #14369: Open/closed issue counts on issues summary are not displayed with SQLServer
+* Defect #14401: Filtering issues on "related to" may ignore other filters
+* Defect #14415: Spent time details and report should ignore 'Setting.display_subprojects_issues?' when 'Subproject' filter is enabled.
+* Defect #14422: CVS root_url not recognized when connection string does not include port
+* Defect #14447: Additional status transitions for assignees do not work if assigned to a group
+* Defect #14511: warning: class variable access from toplevel on Ruby 2.0
+* Defect #14562: diff of CJK (Chinese/Japanese/Korean) is broken on Ruby 1.8
+* Defect #14584: Standard fields disabled for certain trackers still appear in email notifications
+* Defect #14607: rake redmine:load_default_data Error
+* Defect #14697: Wrong Russian translation in close project message
+* Defect #14798: Wrong done_ratio calculation for parent with subtask having estimated_hours=0
+* Patch #14485: Traditional Chinese translation for 2.3-stable
+* Patch #14502: Russian translation for 2.3-stable
+* Patch #14531: Spanish translations for 2.3.x
+* Patch #14686: Portuguese translation for 2.3-stable
+
+== 2013-07-14 v2.3.2
+
+* Defect #9996: configuration.yml in documentation , but redmine ask me to create email.yml
+* Defect #13692: warning: already initialized constant on Ruby 1.8.7
+* Defect #13783: Internal error on time tracking activity enumeration deletion
+* Defect #13821: "obj" parameter is not defined for macros used in description of documents
+* Defect #13850: Unable to set custom fields for versions using the REST API
+* Defect #13910: Values of custom fields are not kept in issues when copying a project
+* Defect #13950: Duplicate Lithuanian "error_attachment_too_big" translation keys
+* Defect #14015: Ruby hangs when adding a subtask
+* Defect #14020: Locking and unlocking a user resets the email notification checkbox
+* Defect #14023: Can't delete relation when Redmine runs in a subpath
+* Defect #14051: Filtering issues with custom field in date format with NULL(empty) value
+* Defect #14178: PDF API broken in version 2.3.1
+* Defect #14186: Project name is not properly escaped in issue filters JSON
+* Defect #14242: Project auto generation fails when projects created in the same time
+* Defect #14245: Gem::InstallError: nokogiri requires Ruby version >= 1.9.2.
+* Defect #14346: Latvian translation for "Log time"
+* Feature #12888: Adding markings to emails generated by Private comments
+* Feature #14419: Include RUBY_PATCHLEVEL and RUBY_RELEASE_DATE in info.rb
+* Patch #14005: Swedish Translation for 2.3-stable
+* Patch #14101: Receive IMAP by uid's
+* Patch #14103: Disconnect and logout from IMAP after mail receive
+* Patch #14145: German translation of x_hours
+* Patch #14182: pt-BR translation for 2.3-stable
+* Patch #14196: Italian translation for 2.3-stable
+* Patch #14221: Translation of x_hours for many languages
+
+== 2013-05-01 v2.3.1
+
+* Defect #12650: Lost text after selection in issue list with IE
+* Defect #12684: Hotkey for Issue-Edit doesn't work as expected
+* Defect #13405: Commit link title is escaped twice when using "commit:" prefix
+* Defect #13541: Can't access SCM when log/production.scm.stderr.log is not writable
+* Defect #13579: Datepicker uses Simplified Chinese in Traditional Chinese locale
+* Defect #13584: Missing Portuguese jQuery UI date picker
+* Defect #13586: Circular loop testing prevents precedes/follows relation between subtasks
+* Defect #13618: CSV export of spent time ignores filters and columns selection
+* Defect #13630: PDF export generates the issue id twice
+* Defect #13644: Diff - Internal Error
+* Defect #13712: Fix email rake tasks to also support no_account_notice and default_group options
+* Defect #13811: Broken javascript in IE7 ; recurrence of #12195
+* Defect #13823: Trailing comma in javascript files
+* Patch #13531: Traditional Chinese translation for 2.3-stable
+* Patch #13552: Dutch translations for 2.3-stable
+* Patch #13678: Lithuanian translation for 2.3-stable
+
+== 2013-03-19 v2.3.0
+
+* Defect #3107: Issue with two digit year on Logtime
+* Defect #3371: Autologin does not work when using openid
+* Defect #3676: www. generates broken link in formatted text
+* Defect #4700: Adding news does not send notification to all project members
+* Defect #5329: Time entries report broken on first week of year
+* Defect #8794: Circular loop when using relations and subtasks
+* Defect #9475: German Translation "My custom queries" and "Custom queries"
+* Defect #9549: Only 100 users are displayed when adding new project members
+* Defect #10277: Redmine wikitext URL-into-link creation with hyphen is wrong
+* Defect #10364: Custom field float separator in CSV export
+* Defect #10930: rake redmine:load_default_data error in 2.0 with SQLServer
+* Defect #10977: Redmine shouldn't require all database gems
+* Defect #12528: Handle temporary failures gracefully in the external mail handler script
+* Defect #12629: Wrong German "label_issues_by" translation
+* Defect #12641: Diff outputs become ??? in some non ASCII words.
+* Defect #12707: Typo in app/models/tracker.rb
+* Defect #12716: Attachment description lost when issue validation fails
+* Defect #12735: Negative duration allowed
+* Defect #12736: Negative start/due dates allowed
+* Defect #12968: Subtasks don't resepect following/precedes
+* Defect #13006: Filter "Assignee's group" doesn't work with group assignments
+* Defect #13022: Image pointing towards /logout signs out user
+* Defect #13059: Custom fields are listed two times in workflow/Fields permission
+* Defect #13076: Project overview page shows trackers from subprojects with disabled issue module
+* Defect #13119: custom_field_values are not reloaded on #reload
+* Defect #13154: After upgrade to 2.2.2 ticket list on some projects fails
+* Defect #13188: Forms are not updated after changing the status field without "Add issues" permission
+* Defect #13251: Adding a "follows" relation may not refresh relations list
+* Defect #13272: translation missing: setting_default_projects_tracker_ids
+* Defect #13328: Copying an issue as a child of itself creates an extra issue
+* Defect #13335: Autologin does not work with custom autologin cookie name
+* Defect #13350: Japanese mistranslation fix
+* Feature #824: Add "closed_on" issue field (storing time of last closing) & add it as a column and filter on the issue list.
+* Feature #1766: Custom fields should become addable to Spent Time list/report
+* Feature #3436: Show relations in Gantt diagram
+* Feature #3957: Ajax file upload with progress bar
+* Feature #5298: Store attachments in sub directories
+* Feature #5605: Subprojects should (optionally) inherit Members from their parent
+* Feature #6727: Add/remove issue watchers via REST API
+* Feature #7159: Bulk watch/unwatch issues from the context menu
+* Feature #8529: Get the API key of the user through REST API
+* Feature #8579: Multiple file upload with HTML5 / Drag-and-Drop
+* Feature #10191: Add Filters For Spent time's Details and Report
+* Feature #10286: Auto-populate fields while creating a new user with LDAP
+* Feature #10352: Preview should already display the freshly attached images
+* Feature #11498: Add --no-account-notice option for the mail handler script
+* Feature #12122: Gantt progress lines (html only)
+* Feature #12228: JRuby 1.7.2 support
+* Feature #12251: Custom fields: 'Multiple values' should be able to be checked and then unchecked
+* Feature #12401: Split "Manage documents" permission into create, edit and delete permissions
+* Feature #12542: Group events in the activity view
+* Feature #12665: Link to a file in a repository branch
+* Feature #12713: Microsoft SQLServer support
+* Feature #12787: Remove "Warning - iconv will be deprecated in the future, use String#encode instead."
+* Feature #12843: Add links to projects in Group projects list
+* Feature #12898: Handle GET /issues/context_menu parameters nicely to prevent returning error 500 to crawlers
+* Feature #12992: Make JSONP support optional and disabled by default
+* Feature #13174: Raise group name maximum length to 255 characters
+* Feature #13175: Possibility to define the default enable trackers when creating a project
+* Feature #13329: Ruby 2.0 support
+* Feature #13337: Split translation "label_total"
+* Feature #13340: Mail handler: option to add created user to default group
+* Feature #13341: Mail handler: --no-notification option to disable notifications to the created user
+* Patch #7202: Polish translation for v1.0.4
+* Patch #7851: Italian translation for 'issue'
+* Patch #9225: Generate project identifier automatically with JavaScript
+* Patch #10916: Optimisation in issues relations display
+* Patch #12485: Don't force english language for default admin account
+* Patch #12499: Use lambda in model scopes
+* Patch #12611: Login link unexpected logs you out
+* Patch #12626: Updated Japanese translations for button_view and permission_commit_access
+* Patch #12640: Russian "about_x_hours" translation change
+* Patch #12645: Russian numeric translation
+* Patch #12660: Consistent German translation for my page
+* Patch #12708: Restructured german translation (Cleanup)
+* Patch #12721: Optimize MenuManager a bit
+* Patch #12725: Change pourcent to percent (#12724)
+* Patch #12754: Updated Japanese translation for notice_account_register_done
+* Patch #12788: Copyright for 2013
+* Patch #12806: Serbian translation change
+* Patch #12810: Swedish Translation change
+* Patch #12910: Plugin settings div should perhaps have 'settings' CSS class
+* Patch #12911: Fix 500 error for requests to the settings path for non-configurable plugins
+* Patch #12926: Bulgarian translation (r11218)
+* Patch #12927: Swedish Translation for r11244
+* Patch #12967: Change Spanish login/logout translations
+* Patch #12988: Russian translation for trunk
+* Patch #13080: German translation of label_in
+* Patch #13098: Small datepicker improvements
+* Patch #13152: Locale file for Azerbaijanian language
+* Patch #13155: Add login to /users/:id API for current user
+* Patch #13173: Put source :rubygems url HTTP secure
+* Patch #13190: Bulgarian translation (r11404)
+* Patch #13198: Traditional Chinese language file (to r11426)
+* Patch #13203: German translation change for follow and precedes is inconsitent
+* Patch #13206: Portuguese translation file
+* Patch #13246: Some german translation patches
+* Patch #13280: German translation (r11478)
+* Patch #13301: Performance: avoid querying all memberships in User#roles_for_project
+* Patch #13309: Add "tracker-[id]" CSS class to issues
+* Patch #13324: fixing some pt-br locales
+* Patch #13339: Complete language Vietnamese file
+* Patch #13391: Czech translation update
+* Patch #13399: Fixed some wrong or confusing translation in Korean locale
+* Patch #13414: Bulgarian translation (r11567)
+* Patch #13420: Korean translation for 2.3 (r11583)
+* Patch #13437: German translation of setting_emails_header
+* Patch #13438: English translation
+* Patch #13447: German translation - some patches
+* Patch #13450: Czech translation
+* Patch #13475: fixing some pt-br locales
+* Patch #13514: fixing some pt-br locales
+
+== 2013-03-19 v2.2.4
+
+* Upgrade to Rails 3.2.13
+* Defect #12243: Ordering forum replies by last reply date is broken
+* Defect #13127: h1 multiple lined titles breaks into main menu
+* Defect #13138: Generating PDF of issue causes UndefinedConversionError with htmlentities gem
+* Defect #13165: rdm-mailhandler.rb: initialize_http_header override basic auth
+* Defect #13232: Link to topic in nonexistent forum causes error 500
+* Patch #13181: Bulgarian translation of jstoolbar-bg.js
+* Patch #13207: Portuguese translation for 2.2-stable
+* Patch #13310: pt-BR label_last_n_weeks translation
+* Patch #13325: pt-BR translation for 2.2-stable
+* Patch #13343: Vietnamese translation for 2.2-stable
+* Patch #13398: Czech translation for 2.2-stable
+
+== 2013-02-12 v2.2.3
+
+* Upgrade to Rails 3.2.12
+* Defect #11987: pdf: Broken new line in table
+* Defect #12930: 404 Error when referencing different project source files in the wiki syntax
+* Defect #12979: Wiki link syntax commit:repo_a:abcd doesn't work
+* Defect #13075: Can't clear custom field value through context menu in the issue list
+* Defect #13097: Project copy fails when wiki module is disabled
+* Defect #13126: Issue view: estimated time vs. spent time
+* Patch #12922: Update Spanish translation
+* Patch #12928: Bulgarian translation for 2.2-stable
+* Patch #12987: Russian translation for 2.2-stable
+
+== 2013-01-20 v2.2.2
+
+* Defect #7510: Link to attachment should return latest attachment
+* Defect #9842: {{toc}} is not replaced by table of content when exporting wiki page to pdf
+* Defect #12749: Plugins cannot route wiki page sub-path
+* Defect #12799: Cannot edit a wiki section which title starts with a tab
+* Defect #12801: Viewing the history of a wiki page with attachments raises an error
+* Defect #12833: Input fields restricted on length should have maxlength parameter set
+* Defect #12838: Blank page when clicking Add with no block selected on my page layout
+* Defect #12851: "Parent task is invalid" while editing child issues by Role with restricted Issues Visibility
+* Patch #12800: Serbian Latin translation patch (sr-YU.yml)
+* Patch #12809: Swedish Translation for r11162
+* Patch #12818: Minor swedish translation fix
+
+== 2013-01-09 v2.2.1
+
+* Upgrade to Rails 3.2.11
+* Defect #12652: "Copy ticket" selects "new ticket"
+* Defect #12691: Textile Homepage Dead?
+* Defect #12711: incorrect fix of lib/SVG/Graph/TimeSeries.rb
+* Defect #12744: Unable to call a macro with a name that contains uppercase letters
+* Defect #12776: Security vulnerability in Rails 3.2.10 (CVE-2013-0156)
+* Patch #12630: Russian "x_hours" translation
+
+== 2012-12-18 v2.2.0
+
+* Defect #4787: Gannt to PNG - CJK (Chinese, Japanese and Korean) characters appear as ?
+* Defect #8106: Issues by Category should show tasks without category
+* Defect #8373: i18n string text_are_you_sure_with_children no longer used
+* Defect #11426: Filtering with Due Date in less than N days should show overdue issues
+* Defect #11834: Bazaar: "???" instead of non ASCII character in paths on non UTF-8 locale
+* Defect #11868: Git and Mercurial diff displays deleted files as /dev/null
+* Defect #11979: No validation errors when entering an invalid "Parent task"
+* Defect #12012: Redmine::VERSION.revision method does not work on Subversion 1.7 working copy
+* Defect #12018: Issue filter select box order changes randomly
+* Defect #12090: email recipients not written to action_mailer log if BCC recipients setting is checked
+* Defect #12092: Issue "start date" validation does not work correctly
+* Defect #12285: Some unit and functional tests miss fixtures and break when run alone
+* Defect #12286: Emails of private notes are sent to watcher users regardless of viewing permissions
+* Defect #12310: Attachments may not be displayed in the order they were selected
+* Defect #12356: Issue "Update" link broken focus
+* Defect #12397: Error in Textile conversion of HTTP links, containing russian letters
+* Defect #12434: Respond with 404 instead of 500 when requesting a wiki diff with invalid versions
+* Feature #1554: Private comments in tickets
+* Feature #2161: Time tracking code should respect weekends as "no work" days
+* Feature #3239: Show related issues on the Issues Listing
+* Feature #3265: Filter on issue relations
+* Feature #3447: Option to display the issue descriptions on the issues list
+* Feature #3511: Ability to sort issues by grouped column
+* Feature #4590: Precede-Follow relation should move following issues when rescheduling issue earlier
+* Feature #5487: Allow subtasks to cross projects
+* Feature #6899: Add a relation between the original and copied issue
+* Feature #7082: Rest API for wiki
+* Feature #9835: REST API - List priorities
+* Feature #10789: Macros {{child_pages}} with depth parameter
+* Feature #10852: Ability to delete a version from a wiki page history
+* Feature #10937: new user format #{lastname}
+* Feature #11502: Expose roles details via REST API
+* Feature #11755: Impersonate user through REST API auth
+* Feature #12085: New user name format: firstname + first letter of lastname
+* Feature #12125: Set filename used to store attachment updloaded via the REST API
+* Feature #12167: Macro for inserting collapsible block of text
+* Feature #12211: Wrap issue description and its contextual menu in a div
+* Feature #12216: Textual CSS class for priorities
+* Feature #12299: Redmine version requirement improvements (in plugins)
+* Feature #12393: Upgrade to Rails 3.2.9
+* Feature #12475: Lazy loading of translation files for faster startup
+* Patch #11846: Fill username when authentification failed
+* Patch #11862: Add "last 2 weeks" preset to time entries reporting
+* Patch #11992: Japanese translation about issue relations improved
+* Patch #12027: Incorrect Spanish "September" month name
+* Patch #12061: Japanese translation improvement (permission names)
+* Patch #12078: User#allowed_to? should return true or false
+* Patch #12117: Change Japanese translation of "admin"
+* Patch #12142: Updated translation in Lithuanian
+* Patch #12232: German translation enhancements
+* Patch #12316: Fix Lithuanian numeral translation
+* Patch #12494: Bulgarian "button_submit" translation change
+* Patch #12514: Updated translation in Lithuanian
+* Patch #12602: Korean translation update for 2.2-stable
+* Patch #12608: Norwegian translation changed
+* Patch #12619: Russian translation change
+
+== 2012-12-18 v2.1.5
+
+* Defect #12400: Validation fails when receiving an email with list custom fields
+* Defect #12451: Macros.rb extract_macro_options should use lazy search
+* Defect #12513: Grouping of issues by custom fields not correct in PDF export
+* Defect #12566: Issue history notes previews are broken
+* Defect #12568: Clicking "edit" on a journal multiple times shows multiple forms
+* Patch #12605: Norwegian translation for 1.4-stable update
+* Patch #12614: Dutch translation
+* Patch #12615: Russian translation
+
+== 2012-11-24 v2.1.4
+
+* Defect #12274: Wiki export from Index by title is truncated
+* Defect #12298: Right-click context menu unable to batch/bulk update (IE8)
+* Defect #12332: Repository identifier does not display on Project/Settings/Repositories
+* Defect #12396: Error when receiving an email without subject header
+* Defect #12399: Non ASCII attachment filename encoding broken (MOJIBAKE) in receiving mail on Ruby 1.8
+* Defect #12409: Git: changesets aren't read after clear_changesets call
+* Defect #12431: Project.rebuild! sorts root projects by id instead of name
+
+== 2012-11-17 v2.1.3
+
+* Defect #12050: :export links to repository files lead to a 404 error
+* Defect #12189: Missing tmp/pdf directory
+* Defect #12195: Javascript error with IE7 / IE8 on new issue form
+* Defect #12196: "Page not found" on OK button in SCM "View all revisions" page
+* Defect #12199: Confirmation message displayed when clicking a disabled delete link in the context menu
+* Defect #12231: Hardcoded "Back" in Repository
+* Defect #12294: Incorrect german translation for "registered" users filter
+* Defect #12349: Watchers auto-complete search on non-latin chars
+* Defect #12358: 'None' grouped issue list section should be translated
+* Defect #12359: Version date field regex validation accepts invalid date
+* Defect #12375: Receiving mail subject encoding broken (MOJIBAKE) in some cases on Ruby 1.8
+* Patch #9732: German translations
+* Patch #12021: Russian locale translations
+* Patch #12188: Simplified Chinese translation with zh.yml file based on Rev:10681
+* Patch #12235: German translation for 2.1-stable
+* Patch #12237: Added German Translation
+
+== 2012-09-30 v2.1.2
+
+* Defect #11929: XSS vulnerability in Redmine 2.1.x
+
+== 2012-09-30 v2.1.1
+
+* Defect #11290: ParseDate missing in Ruby 1.9x
+* Defect #11844: "load_default_data" rake task fails to print the error message if one occurs
+* Defect #11850: Can't create a user from ldap by on-the-fly on the redmine server using URI prefix
+* Defect #11872: Private issue visible to anonymous users after its author is deleted
+* Defect #11885: Filter misses Selectionfield on IE8
+* Defect #11893: New relation form Cancel link is broken with Chrome 21
+* Defect #11905: Potential "can't dup NilClass" error in UserPreference
+* Defect #11909: Autocomplete results not reset after clearing search field
+* Defect #11922: bs.yml and de.yml lead to error by number_to_currency()
+* Defect #11945: rake task prints "can't convert Errno::EACCES into String" in case of no permission of public/plugin_assets
+* Defect #11975: Undefined status transitions allowed in workflow (author of issue changes when selecting a new status)
+* Defect #11982: SCM diff view generates extra parameter for switching mode
+* Patch #11897: Traditional Chinese language file (to r10433)
+
+== 2012-09-16 v2.1.0
+
+* Defect #2071: Reordering priority-enumerations breaks alternate-theme's issue-colouring
+* Defect #2190: Month names not translated to german
+* Defect #8978: LDAP timeout if an LDAP auth provider is unreachable
+* Defect #9839: Gantt abbr of weekday should not be necessarily the first letter of the long day name
+* Defect #10928: Documentation about generating a plugin is not up-to-date
+* Defect #11034: TLS configuration documentation for Rails 3
+* Defect #11073: UserCustomField order_statement returns wrong output
+* Defect #11153: Default sorting for target version is DESC instead of ASC
+* Defect #11207: Issues associated with a locked version are not copied when copying a project
+* Defect #11304: Issue-class: status-1, status-2 etc. refer to status position instead of status id
+* Defect #11331: Openid registration form should not require user to enter password
+* Defect #11345: Context menu should show shared versions when editing issues from different projects
+* Defect #11355: Plain text notification emails content is HTML escaped
+* Defect #11388: Updating a version through rest API returns invalid JSON
+* Defect #11389: Warning in awesome_nested_set.rb
+* Defect #11503: Accessing /projects/:project/wiki/something.png fails with error 500
+* Defect #11506: Versions that are not shared should not be assignable when selecting another project
+* Defect #11508: Projects not ordered alphabetically after renaming project
+* Defect #11540: Roadmap anchor links can be ambigous
+* Defect #11545: Overwriting existing method Issue.open
+* Defect #11552: MailHandler does not match assignee name with spaces
+* Defect #11571: Custom fields of type version not proper handled in receiving e-mails
+* Defect #11577: Can't use non-latin anchor in wiki
+* Defect #11612: Revision graph sometimes broken due to raphael.js error
+* Defect #11621: Redmine MIME Detection Of Javascript Files Non-Standard
+* Defect #11633: Macro arguments should not be parsed by text formatters
+* Defect #11662: Invalid query returned from Issues.visible scope after accessing User#projects_by_role with a role that is not present
+* Defect #11691: 404 response when deleting a user from the edit page
+* Defect #11723: redmine:send_reminders notification misses if assignee is a group
+* Defect #11738: Batch update of issues clears project path
+* Defect #11749: Redmine.pm: HEAD is not considered as a read-only method
+* Defect #11814: Date picker does not respect week start setting
+* Feature #703: Configurable required fields per tracker/status/role
+* Feature #1006: Display thumbnails of attached images
+* Feature #1091: Disabling default ticket fields per tracker
+* Feature #1360: Permission for adding an issue to a version.
+* Feature #3061: Let macros optionally match over multiple lines and ignore single curly braces
+* Feature #3510: Inserting image thumbnails inside the wiki
+* Feature #3521: Permissions for roles to change fields per tracker/status
+* Feature #3640: Freeze / Close Projects
+* Feature #3831: Support for subforums
+* Feature #6597: Configurable session lifetime and timeout
+* Feature #6965: Option to Copy Subtasks when copying an issue
+* Feature #8161: Ability to filter issues on project custom fields
+* Feature #8577: "Private" column and filter on the issue list
+* Feature #8981: REST Api for Groups
+* Feature #9258: Create role by copy
+* Feature #9419: Group/sort the issue list by user/version-format custom fields
+* Feature #10362: Show images in repositories inline when clicking the 'View' link
+* Feature #10419: Upgrade raphael.js (2.1.0)
+* Feature #11068: Ability to set default column order in issue list
+* Feature #11102: Add autocomplete to "Related issue" field on revision
+* Feature #11109: Repository Identifier should be frozen
+* Feature #11181: Additional "Log time" link on project overview
+* Feature #11205: Reversed order of priorities on the issue summary page
+* Feature #11445: Switch from Prototype to JQuery
+* Feature #11469: JSONP support
+* Feature #11475: Redmine.pm: Allow fallback to other Apache auth providers
+* Feature #11494: Don't turn #nnn with leading zeros into links
+* Feature #11539: Display a projects tree instead of a flat list in notification preferences
+* Feature #11578: Option to pass whole arguments to a macro without splitting them
+* Feature #11595: Missing mime type for svg files
+* Feature #11758: Upgrade to Rails 3.2.8
+* Patch #4905: Redmine.pm: add support for Git's smart HTTP protocol
+* Patch #10988: New Korean translation patch
+* Patch #11201: Korean translation special update
+* Patch #11401: Fix Japanese mistranslation for "button_submit"
+* Patch #11402: Japanese translation added for default role names
+* Patch #11411: Fix disordered use of long sound in Japanese "user" translation
+* Patch #11412: Unnatural Japanese message when users failed to login
+* Patch #11419: Fix wrong Japanese "label_attachment" translation
+* Patch #11496: Make labels clickable in Adminstration/Settings
+* Patch #11704: Avoid the use of tag("...", "...", true) in layout
+* Patch #11818: Redmine.pm fails when permissions are NULL
+
+== 2012-09-16 v2.0.4
+
+* Defect #10818: Running rake in test environment causes exception
+* Defect #11209: Wiki diff may generate broken HTML
+* Defect #11217: Project names in drop-down are escaped twice
+* Defect #11262: Link is escaped in wiki added/updated notification email
+* Defect #11307: Can't filter for negative numeric custom fields
+* Defect #11325: Unified diff link broken on specific file/revision diff view
+* Defect #11341: Escaped link in conflict resolution form
+* Defect #11365: Attachment description length is not validated
+* Defect #11511: Confirmation page has broken HTML when a project folding sub project is deleted
+* Defect #11533: rake redmine:plugins:test doesn't run tests in subdirectories
+* Defect #11541: Version sharing is missing in the REST API
+* Defect #11550: Issue reminder doesn't work when using asynchronous delivery
+* Defect #11776: Can't override mailer views inside redmine plugin.
+* Defect #11789: Edit section links broken with h5/h6 headings
+* Feature #11338: Exclude emails with auto-submitted => auto-generated
+* Patch #11299: redmine:plugins:migrate should update db/schema.rb
+* Patch #11328: Fix Japanese mistranslation for 'label_language_based'
+* Patch #11448: Russian translation for 1.4-stable and 2.0-stable
+* Patch #11600: Fix plural form of the abbreviation for hours in Brazilian Portuguese
+
+== 2012-06-18 v2.0.3
+
+* Defect #10688: PDF export from Wiki - Problems with tables
+* Defect #11061: Cannot choose commit versions to view differences in Git/Mercurial repository view
+* Defect #11065: E-Mail submitted tickets: German umlauts in 'Subject' get malformed (ruby 1.8)
+* Defect #11098: Default priorities have the same position and can't be reordered
+* Defect #11105: <% content_for :header_tags do %> doesn't work inside hook
+* Defect #11112: REST API - custom fields in POST/PUT ignored for time_entries
+* Defect #11118: "Maximum file size" displayed on upload forms is incorrect
+* Defect #11124: Link to user is escaped in activity title
+* Defect #11133: Wiki-page section edit link can point to incorrect section
+* Defect #11160: SQL Error on time report if a custom field has multiple values for an entry
+* Defect #11170: Topics sort order is broken in Redmine 2.x
+* Defect #11178: Spent time sorted by date-descending order lists same-date entries in physical order (not-reverse)
+* Defect #11185: Redmine fails to delete a project with parent/child task
+* Feature #11162: Upgrade to Rails 3.2.6
+* Patch #11113: Small glitch in German localization
+
+== 2012-06-05 v2.0.2
+
+* Defect #11032: Project list is not shown when "For any event on the selected projects only..." is selected on user edit panel
+* Defect #11038: "Create and continue" should preserve project, issue and activity when logging time
+* Defect #11046: Redmine.pm does not support "bind as user" ldap authentication
+* Defect #11051: reposman.rb fails in 1.4.2 because of missing require for rubygems
+* Defect #11085: Wiki start page can't be changed
+* Feature #11084: Update Rails to 3.2.5
+
+== 2012-05-28 v2.0.1
+
+* Defect #10923: After creating a new Version Redmine jumps back to "Information"
+* Defect #10932: Links to delete watchers are escaped when gravatars are enabled
+* Defect #10964: Updated column doesn't get updated on issues
+* Defect #10965: rake yard does not work for generating documentation.
+* Defect #10972: Columns selection not displayed on the custom query form
+* Defect #10991: My page > Spent time 'project' column is html-encoded
+* Defect #10996: Time zones lost when upgrading from Redmine 1.4 to 2.0
+* Defect #11013: Fetching Email from IMAP/POP3 - uninitialized constant RAILS_DEFAULT_LOGGER error
+* Defect #11024: redmine_plugin_model generator does not create the migration
+* Defect #11027: Saving new query without name causes escaping of input field
+* Defect #11028: Project identifier can be updated
+
+== 2012-05-15 v2.0.0
+
+* Feature #4796: Rails 3 support
+* Feature #7720: Limit the pagination-limit when max-results is fewer than max-pagination-limit
+* Feature #9034: Add an id to the flash messages
+* Patch #10782: Better translation for Estonian language
+
+== 2012-05-13 v1.4.2
+
+* Defect #10744: rake task redmine:email:test broken
+* Defect #10787: "Allow users to unsubscribe" option is confusing
+* Defect #10827: Cannot access Repositories page and Settings in a Project - Error 500
+* Defect #10829: db:migrate fails 0.8.2 -> 1.4.1
+* Defect #10832: REST Uploads fail with fastcgi
+* Defect #10837: reposman and rdm-mailhandler not working with ruby 1.9.x
+* Defect #10856: can not load translations from hr.yml with ruby1.9.3-p194
+* Defect #10865: Filter reset when deleting locked user
+* Feature #9790: Allow filtering text custom fields on "is null" and "is not null"
+* Feature #10778: svn:ignore for config/additional_environment.rb
+* Feature #10875: Partial Albanian Translations
+* Feature #10888: Bring back List-Id to help aid Gmail filtering
+* Patch #10733: Traditional Chinese language file (to r9502)
+* Patch #10745: Japanese translation update (r9519)
+* Patch #10750: Swedish Translation for r9522
+* Patch #10785: Bulgarian translation (jstoolbar)
+* Patch #10800: Simplified Chinese translation
+
+== 2012-04-20 v1.4.1
+
+* Defect #8574: Time report: date range fields not enabled when using the calendar popup
+* Defect #10642: Nested textile ol/ul lists generate invalid HTML
+* Defect #10668: RSS key is generated twice when user is not reloaded
+* Defect #10669: Token.destroy_expired should not delete API tokens
+* Defect #10675: "Submit and continue" is broken
+* Defect #10711: User cannot change account details with "Login has already been taken" error
+* Feature #10664: Unsubscribe Own User Account
+* Patch #10693: German Translation Update
+
+== 2012-04-14 v1.4.0
+
+* Defect #2719: Increase username length limit from 30 to 60
+* Defect #3087: Revision referring to issues across all projects
+* Defect #4824: Unable to connect (can't convert Net::LDAP::LdapError into String)
+* Defect #5058: reminder mails are not sent when delivery_method is :async_smtp
+* Defect #6859: Moving issues to a tracker with different custom fields should let fill these fields
+* Defect #7398: Error when trying to quick create a version with required custom field
+* Defect #7495: Python multiline comments highlighting problem in Repository browser
+* Defect #7826: bigdecimal-segfault-fix.rb must be removed for Oracle
+* Defect #7920: Attempted to update a stale object when copying a project
+* Defect #8857: Git: Too long in fetching repositories after upgrade from 1.1 or new branch at first time
+* Defect #9472: The git scm module causes an excess amount of DB traffic.
+* Defect #9685: Adding multiple times the same related issue relation is possible
+* Defect #9798: Release 1.3.0 does not detect rubytree under ruby 1.9.3p0 / rails 2.3.14
+* Defect #9978: Japanese "permission_add_issue_watchers" is wrong
+* Defect #10006: Email reminders are sent for closed issues
+* Defect #10150: CSV export and spent time: rounding issue
+* Defect #10168: CSV export breaks custom columns
+* Defect #10181: Issue context menu and bulk edit form show irrelevant statuses
+* Defect #10198: message_id regex in pop3.rb only recognizes Message-ID header (not Message-Id)
+* Defect #10251: Description diff link in note details is relative when received by email
+* Defect #10272: Ruby 1.9.3: "incompatible character encoding" with LDAP auth
+* Defect #10275: Message object not passed to wiki macros for head topic and in preview edit mode
+* Defect #10334: Full name is not unquoted when creating users from emails
+* Defect #10410: [Localization] Grammar issue of Simplified Chinese in zh.yml
+* Defect #10442: Ruby 1.9.3 Time Zone setting Internal error.
+* Defect #10467: Confusing behavior while moving issue to a project with disabled Issues module
+* Defect #10575: Uploading of attachments which filename contains non-ASCII chars fails with Ruby 1.9
+* Defect #10590: WikiContent::Version#text return string with #<Encoding:ASCII-8BIT> when uncompressed
+* Defect #10593: Error: 'incompatible character encodings: UTF-8 and ASCII-8BIT' (old annoing issue) on ruby-1.9.3
+* Defect #10600: Watchers search generates an Internal error
+* Defect #10605: Bulk edit selected issues does not allow selection of blank values for custom fields
+* Defect #10619: When changing status before tracker, it shows improper status
+* Feature #779: Multiple SCM per project
+* Feature #971: Add "Spent time" column to query
+* Feature #1060: Add a LDAP-filter using external auth sources
+* Feature #1102: Shortcut for assigning an issue to me
+* Feature #1189: Multiselect custom fields
+* Feature #1363: Allow underscores in project identifiers
+* Feature #1913: LDAP - authenticate as user
+* Feature #1972: Attachments for News
+* Feature #2009: Manually add related revisions
+* Feature #2323: Workflow permissions for administrators
+* Feature #2416: {background:color} doesn't work in text formatting
+* Feature #2694: Notification on loosing assignment
+* Feature #2715: "Magic links" to notes
+* Feature #2850: Add next/previous navigation to issue
+* Feature #3055: Option to copy attachments when copying an issue
+* Feature #3108: set parent automatically for new pages
+* Feature #3463: Export all wiki pages to PDF
+* Feature #4050: Ruby 1.9 support
+* Feature #4769: Ability to move an issue to a different project from the update form
+* Feature #4774: Change the hyperlink for file attachment to view and download
+* Feature #5159: Ability to add Non-Member watchers to the watch list
+* Feature #5638: Use Bundler (Gemfile) for gem management
+* Feature #5643: Add X-Redmine-Sender header to email notifications
+* Feature #6296: Bulk-edit custom fields through context menu
+* Feature #6386: Issue mail should render the HTML version of the issue details
+* Feature #6449: Edit a wiki page's parent on the edit page
+* Feature #6555: Double-click on "Submit" and "Save" buttons should not send two requests to server
+* Feature #7361: Highlight active query in the side bar
+* Feature #7420: Rest API for projects members
+* Feature #7603: Please make editing issues more obvious than "Change properties (More)"
+* Feature #8171: Adding attachments through the REST API
+* Feature #8691: Better handling of issue update conflict
+* Feature #9803: Change project through REST API issue update
+* Feature #9923: User type custom fields should be filterable by "Me".
+* Feature #9985: Group time report by the Status field
+* Feature #9995: Time entries insertion, "Create and continue" button
+* Feature #10020: Enable global time logging at /time_entries/new
+* Feature #10042: Bulk change private flag
+* Feature #10126: Add members of subprojects in the assignee and author filters
+* Feature #10131: Include custom fiels in time entries API responses
+* Feature #10207: Git: use default branch from HEAD
+* Feature #10208: Estonian translation
+* Feature #10253: Better handling of attachments when validation fails
+* Feature #10350: Bulk copy should allow for changing the target version
+* Feature #10607: Ignore out-of-office incoming emails
+* Feature #10635: Adding time like "123 Min" is invalid
+* Patch #9998: Make attachement "Optional Description" less wide
+* Patch #10066: i18n not working with russian gem
+* Patch #10128: Disable IE 8 compatibility mode to fix wrong div.autoscroll scroll bar behaviour 
+* Patch #10155: Russian translation changed
+* Patch #10464: Enhanced PDF output for Issues list
+* Patch #10470: Efficiently process new git revisions in a single batch
+* Patch #10513: Dutch translation improvement
+
+== 2012-04-14 v1.3.3
+
+* Defect #10505: Error when exporting to PDF with NoMethodError (undefined method `downcase' for nil:NilClass)
+* Defect #10554: Defect symbols when exporting tasks in pdf
+* Defect #10564: Unable to change locked, sticky flags and board when editing a message
+* Defect #10591: Dutch "label_file_added" translation is wrong
+* Defect #10622: "Default administrator account changed" is always true
+* Patch #10555: rake redmine:send_reminders aborted if issue assigned to group
+* Patch #10611: Simplified Chinese translations for 1.3-stable
+
+== 2012-03-11 v1.3.2
+
+* Defect #8194: {{toc}} uses identical anchors for subsections with the same name
+* Defect #9143: Partial diff comparison should be done on actual code, not on html
+* Defect #9523: {{toc}} does not display headers with @ code markup
+* Defect #9815: Release 1.3.0 does not detect rubytree with rubgems 1.8
+* Defect #10053: undefined method `<=>' for nil:NilClass when accessing the settings of a project
+* Defect #10135: ActionView::TemplateError (can't convert Fixnum into String)
+* Defect #10193: Unappropriate icons in highlighted code block
+* Defect #10199: No wiki section edit when title contains code
+* Defect #10218: Error when creating a project with a version custom field
+* Defect #10241: "get version by ID" fails with "401 not authorized" error when using API access key
+* Defect #10284: Note added by commit from a subproject does not contain project identifier
+* Defect #10374: User list is empty when adding users to project / group if remaining users are added late
+* Defect #10390: Mass assignment security vulnerability
+* Patch #8413: Confirmation message before deleting a relationship
+* Patch #10160: Bulgarian translation (r8777)
+* Patch #10242: Migrate Redmine.pm from Digest::Sha1 to Digest::Sha
+* Patch #10258: Italian translation for 1.3-stable
+
+== 2012-02-06 v1.3.1
+
+* Defect #9775: app/views/repository/_revision_graph.html.erb sets window.onload directly..
+* Defect #9792: Ruby 1.9: [v1.3.0] Error: incompatible character encodings for it translation on Calendar page
+* Defect #9793: Bad spacing between numbered list and heading (recently broken).
+* Defect #9795: Unrelated error message when creating a group with an invalid name
+* Defect #9832: Revision graph height should depend on height of rows in revisions table
+* Defect #9937: Repository settings are not saved when all SCM are disabled
+* Defect #9961: Ukrainian "default_tracker_bug" is wrong
+* Defect #10013: Rest API - Create Version -> Internal server error 500
+* Defect #10115: Javascript error - Can't attach more than 1 file on IE 6 and 7
+* Defect #10130: Broken italic text style in edited comment preview
+* Defect #10152: Attachment diff type is not saved in user preference
+* Feature #9943: Arabic translation
+* Patch #9874: pt-BR translation updates
+* Patch #9922: Spanish translation updated
+* Patch #10137: Korean language file ko.yml updated to Redmine 1.3.0
+
+== 2011-12-10 v1.3.0
+
+* Defect #2109: Context menu is being submitted twice per right click
+* Defect #7717: MailHandler user creation for unknown_user impossible due to diverging length-limits of login and email fields
+* Defect #7917: Creating users via email fails if user real name containes special chars
+* Defect #7966: MailHandler does not include JournalDetail for attached files
+* Defect #8368: Bad decimal separator in time entry CSV
+* Defect #8371: MySQL error when filtering a custom field using the REST api
+* Defect #8549: Export CSV has character encoding error
+* Defect #8573: Do not show inactive Enumerations where not needed
+* Defect #8611: rake/rdoctask is deprecated
+* Defect #8751: Email notification: bug, when number of recipients more then 8
+* Defect #8894: Private issues - make it more obvious in the UI?
+* Defect #8994: Hardcoded French string "anonyme"
+* Defect #9043: Hardcoded string "diff" in Wiki#show and Repositories_Helper
+* Defect #9051: wrong "text_issue_added" in russian translation.
+* Defect #9108: Custom query not saving status filter
+* Defect #9252: Regression: application title escaped 2 times
+* Defect #9264: Bad Portuguese translation
+* Defect #9470: News list is missing Avatars
+* Defect #9471: Inline markup broken in Wiki link labels
+* Defect #9489: Label all input field and control tags
+* Defect #9534: Precedence: bulk email header is non standard and discouraged
+* Defect #9540: Issue filter by assigned_to_role is not project specific
+* Defect #9619: Time zone ignored when logging time while editing ticket
+* Defect #9638: Inconsistent image filename extensions
+* Defect #9669: Issue list doesn't sort assignees/authors regarding user display format
+* Defect #9672: Message-quoting in forums module broken
+* Defect #9719: Filtering by numeric custom field types broken after update to master
+* Defect #9724: Can't remote add new categories
+* Defect #9738: Setting of cross-project custom query is not remembered inside project
+* Defect #9748: Error about configuration.yml validness should mention file path
+* Feature #69: Textilized description in PDF
+* Feature #401: Add pdf export for WIKI page
+* Feature #1567: Make author column sortable and groupable
+* Feature #2222: Single section edit.
+* Feature #2269: Default issue start date should become configurable.
+* Feature #2371: character encoding for attachment file
+* Feature #2964: Ability to assign issues to groups
+* Feature #3033: Bug Reporting: Using "Create and continue" should show bug id of saved bug
+* Feature #3261: support attachment images in PDF export
+* Feature #4264: Update CodeRay to 1.0 final
+* Feature #4324: Redmine renames my files, it shouldn't.
+* Feature #4729: Add Date-Based Filters for Issues List
+* Feature #4742: CSV export: option to export selected or all columns
+* Feature #4976: Allow rdm-mailhandler to read the API key from a file
+* Feature #5501: Git: Mercurial: Adding visual merge/branch history to repository view
+* Feature #5634: Export issue to PDF does not include Subtasks and Related Issues
+* Feature #5670: Cancel option for file upload
+* Feature #5737: Custom Queries available through the REST Api
+* Feature #6180: Searchable custom fields do not provide adequate operators
+* Feature #6954: Filter from date to date
+* Feature #7180: List of statuses in REST API
+* Feature #7181: List of trackers in REST API
+* Feature #7366: REST API for Issue Relations
+* Feature #7403: REST API for Versions
+* Feature #7671: REST API for reading attachments
+* Feature #7832: Ability to assign issue categories to groups
+* Feature #8420: Consider removing #7013 workaround
+* Feature #9196: Improve logging in MailHandler when user creation fails
+* Feature #9496: Adds an option in mailhandler to disable server certificate verification
+* Feature #9553: CRUD operations for "Issue categories" in REST API
+* Feature #9593: HTML title should be reordered
+* Feature #9600: Wiki links for news and forums
+* Feature #9607: Filter for issues without start date (or any another field based on date type)
+* Feature #9609: Upgrade to Rails 2.3.14
+* Feature #9612: "side by side" and "inline" patch view for attachments
+* Feature #9667: Check attachment size before upload
+* Feature #9690: Link in notification pointing to the actual update
+* Feature #9720: Add note number for single issue's PDF
+* Patch #8617: Indent subject of subtask ticket in exported issues PDF
+* Patch #8778: Traditional Chinese 'issue' translation change
+* Patch #9053: Fix up Russian translation
+* Patch #9129: Improve wording of Git repository note at project setting
+* Patch #9148: Better handling of field_due_date italian translation
+* Patch #9273: Fix typos in russian localization
+* Patch #9484: Limit SCM annotate to text files under the maximum file size for viewing
+* Patch #9659: Indexing rows in auth_sources/index view
+* Patch #9692: Fix Textilized description in PDF for CodeRay
+
+== 2011-12-10 v1.2.3
+
+* Defect #8707: Reposman: wrong constant name
+* Defect #8809: Table in timelog report overflows
+* Defect #9055: Version files in Files module cannot be downloaded if issue tracking is disabled
+* Defect #9137: db:encrypt fails to handle repositories with blank password
+* Defect #9394: Custom date field only validating on regex and not a valid date
+* Defect #9405: Any user with :log_time permission can edit time entries via context menu
+* Defect #9448: The attached images are not shown in documents
+* Defect #9520: Copied private query not visible after project copy
+* Defect #9552: Error when reading ciphered text from the database without cipher key configured
+* Defect #9566: Redmine.pm considers all projects private when login_required is enabled
+* Defect #9567: Redmine.pm potential security issue with cache credential enabled and subversion
+* Defect #9577: Deleting a subtasks doesn't update parent's rgt & lft values
+* Defect #9597: Broken version links in wiki annotate history
+* Defect #9682: Wiki HTML Export only useful when Access history is accessible
+* Defect #9737: Custom values deleted before issue submit
+* Defect #9741: calendar-hr.js (Croatian) is not UTF-8
+* Patch #9558: Simplified Chinese translation for 1.2.2 updated
+* Patch #9695: Bulgarian translation (r7942)
+
+== 2011-11-11 v1.2.2
+
+* Defect #3276: Incorrect handling of anchors in Wiki to HTML export
+* Defect #7215: Wiki formatting mangles links to internal headers
+* Defect #7613: Generated test instances may share the same attribute value object
+* Defect #8411: Can't remove "Project" column on custom query
+* Defect #8615: Custom 'version' fields don't show shared versions
+* Defect #8633: Pagination counts non visible issues
+* Defect #8651: Email attachments are not added to issues any more in v1.2
+* Defect #8825: JRuby + Windows: SCMs do not work on Redmine 1.2
+* Defect #8836: Additional workflow transitions not available when set to both author and assignee
+* Defect #8865: Custom field regular expression is not validated
+* Defect #8880: Error deleting issue with grandchild
+* Defect #8884: Assignee is cleared when updating issue with locked assignee
+* Defect #8892: Unused fonts in rfpdf plugin folder
+* Defect #9161: pt-BR field_warn_on_leaving_unsaved has a small gramatical error
+* Defect #9308: Search fails when a role haven't "view wiki" permission
+* Defect #9465: Mercurial: can't browse named branch below Mercurial 1.5
+
+== 2011-07-11 v1.2.1
+
+* Defect #5089: i18N error on truncated revision diff view
+* Defect #7501: Search options get lost after clicking on a specific result type
+* Defect #8229: "project.xml" response does not include the parent ID
+* Defect #8449: Wiki annotated page does not display author of version 1
+* Defect #8467: Missing german translation - Warn me when leaving a page with unsaved text
+* Defect #8468: No warning when leaving page with unsaved text that has not lost focus
+* Defect #8472: Private checkbox ignored on issue creation with "Set own issues public or private" permission
+* Defect #8510: JRuby: Can't open administrator panel if scm command is not available
+* Defect #8512: Syntax highlighter on Welcome page
+* Defect #8554: Translation missing error on custom field validation
+* Defect #8565: JRuby: Japanese PDF export error
+* Defect #8566: Exported PDF UTF-8 Vietnamese not correct
+* Defect #8569: JRuby: PDF export error with TypeError
+* Defect #8576: Missing german translation - different things
+* Defect #8616: Circular relations
+* Defect #8646: Russian translation "label_follows" and "label_follows" are wrong
+* Defect #8712: False 'Description updated' journal details messages
+* Defect #8729: Not-public queries are not private
+* Defect #8737: Broken line of long issue description on issue PDF.
+* Defect #8738: Missing revision number/id of associated revisions on issue PDF
+* Defect #8739: Workflow copy does not copy advanced workflow settings
+* Defect #8759: Setting issue attributes from mail should be case-insensitive
+* Defect #8777: Mercurial: Not able to Resetting Redmine project respository
+
+== 2011-05-30 v1.2.0
+
+* Defect #61: Broken character encoding in pdf export
+* Defect #1965: Redmine is not Tab Safe
+* Defect #2274: Filesystem Repository path encoding of non UTF-8 characters
+* Defect #2664: Mercurial: Repository path encoding of non UTF-8 characters
+* Defect #3421: Mercurial reads files from working dir instead of changesets
+* Defect #3462: CVS: Repository path encoding of non UTF-8 characters
+* Defect #3715: Login page should not show projects link and search box if authentication is required
+* Defect #3724: Mercurial repositories display revision ID instead of changeset ID
+* Defect #3761: Most recent CVS revisions are missing in "revisions" view
+* Defect #4270: CVS Repository view in Project doesn't show Author, Revision, Comment
+* Defect #5138: Don't use Ajax for pagination
+* Defect #5152: Cannot use certain characters for user and role names.
+* Defect #5251: Git: Repository path encoding of non UTF-8 characters
+* Defect #5373: Translation missing when adding invalid watchers
+* Defect #5817: Shared versions not shown in subproject's gantt chart
+* Defect #6013: git tab,browsing, very slow -- even after first time
+* Defect #6148: Quoting, newlines, and nightmares...
+* Defect #6256: Redmine considers non ASCII and UTF-16 text files as binary in SCM
+* Defect #6476: Subproject's issues are not shown in the subproject's gantt
+* Defect #6496: Remove i18n 0.3.x/0.4.x hack for Rails 2.3.5
+* Defect #6562: Context-menu deletion of issues deletes all subtasks too without explicit prompt
+* Defect #6604: Issues targeted at parent project versions' are not shown on gantt chart
+* Defect #6706: Resolving issues with the commit message produces the wrong comment with CVS
+* Defect #6901: Copy/Move an issue does not give any history of who actually did the action.
+* Defect #6905: Specific heading-content breaks CSS
+* Defect #7000: Project filter not applied on versions in Gantt chart
+* Defect #7097: Starting day of week cannot be set to Saturday
+* Defect #7114: New gantt doesn't display some projects
+* Defect #7146: Git adapter lost commits before 7 days from database latest changeset
+* Defect #7218: Date range error on issue query
+* Defect #7257: "Issues by" version links bad criterias
+* Defect #7279: CSS class ".icon-home" is not used.
+* Defect #7320: circular dependency >2 issues
+* Defect #7352: Filters not working in Gantt charts
+* Defect #7367: Receiving pop3 email should not output debug messages
+* Defect #7373: Error with PDF output and ruby 1.9.2
+* Defect #7379: Remove extraneous hidden_field on wiki history
+* Defect #7516: Redmine does not work with RubyGems 1.5.0
+* Defect #7518: Mercurial diff can be wrong if the previous changeset isn't the parent
+* Defect #7581: Not including a spent time value on the main issue update screen causes silent data loss
+* Defect #7582: hiding form pages from search engines
+* Defect #7597: Subversion and Mercurial log have the possibility to miss encoding
+* Defect #7604: ActionView::TemplateError (undefined method `name' for nil:NilClass)
+* Defect #7605: Using custom queries always redirects to "Issues" tab
+* Defect #7615: CVS diffs do not handle new files properly
+* Defect #7618: SCM diffs do not handle one line new files properly
+* Defect #7639: Some date fields do not have requested format.
+* Defect #7657: Wrong commit range in git log command on Windows
+* Defect #7818: Wiki pages don't use the local timezone to display the "Updated ? hours ago" mouseover
+* Defect #7821: Git "previous" and "next" revisions are incorrect
+* Defect #7827: CVS: Age column on repository view is off by timezone delta
+* Defect #7843: Add a relation between issues = explicit login window ! (basic authentication popup is prompted on AJAX request)
+* Defect #8011: {{toc}} does not display headlines with inline code markup
+* Defect #8029: List of users for adding to a group may be empty if 100 first users have been added
+* Defect #8064: Text custom fields do not wrap on the issue list
+* Defect #8071: Watching a subtask from the context menu updates main issue watch link
+* Defect #8072: Two untranslatable default role names
+* Defect #8075: Some "notifiable" names are not i18n-enabled
+* Defect #8081: GIT: Commits missing when user has the "decorate" git option enabled
+* Defect #8088: Colorful indentation of subprojects must be on right in RTL locales
+* Defect #8239: notes field is not propagated during issue copy
+* Defect #8356: GET /time_entries.xml ignores limit/offset parameters
+* Defect #8432: Private issues information shows up on Activity page for unauthorized users
+* Feature #746: Versioned issue descriptions
+* Feature #1067: Differentiate public/private saved queries in the sidebar
+* Feature #1236: Make destination folder for attachment uploads configurable
+* Feature #1735: Per project repository log encoding setting
+* Feature #1763: Autologin-cookie should be configurable
+* Feature #1981: display mercurial tags
+* Feature #2074: Sending email notifications when comments are added in the news section
+* Feature #2096: Custom fields referencing system tables (users and versions)
+* Feature #2732: Allow additional workflow transitions for author and assignee
+* Feature #2910: Warning on leaving edited issue/wiki page without saving
+* Feature #3396: Git: use --encoding=UTF-8 in "git log"
+* Feature #4273: SCM command availability automatic check in administration panel
+* Feature #4477: Use mime types in downloading from repository
+* Feature #5518: Graceful fallback for "missing translation" needed
+* Feature #5520: Text format buttons and preview link missing when editing comment
+* Feature #5831: Parent Task to Issue Bulk Edit
+* Feature #6887: Upgrade to Rails 2.3.11
+* Feature #7139: Highlight changes inside diff lines
+* Feature #7236: Collapse All for Groups
+* Feature #7246: Handle "named branch" for mercurial
+* Feature #7296: Ability for admin to delete users
+* Feature #7318: Add user agent to Redmine Mailhandler
+* Feature #7408: Add an application configuration file
+* Feature #7409: Cross project Redmine links
+* Feature #7410: Add salt to user passwords
+* Feature #7411: Option to cipher LDAP ans SCM passwords stored in the database
+* Feature #7412: Add an issue visibility level to each role
+* Feature #7414: Private issues
+* Feature #7517: Configurable path of executable for scm adapters
+* Feature #7640: Add "mystery man" gravatar to options
+* Feature #7858: RubyGems 1.6 support
+* Feature #7893: Group filter on the users list
+* Feature #7899: Box for editing comments should open with the formatting toolbar
+* Feature #7921: issues by pulldown should have 'status' option
+* Feature #7996: Bulk edit and context menu for time entries
+* Feature #8006: Right click context menu for Related Issues
+* Feature #8209: I18n YAML files not parsable with psych yaml library
+* Feature #8345: Link to user profile from account page
+* Feature #8365: Git: per project setting to report last commit or not in repository tree
+* Patch #5148: metaKey not handled in issues selection
+* Patch #5629: Wrap text fields properly in PDF
+* Patch #7418: Redmine Persian Translation
+* Patch #8295: Wrap title fields properly in PDF
+* Patch #8310: fixes automatic line break problem with TCPDF
+* Patch #8312: Switch to TCPDF from FPDF for PDF export
+
+== 2011-04-29 v1.1.3
+
+* Defect #5773: Email reminders are sent to locked users
+* Defect #6590: Wrong file list link in email notification on new file upload
+* Defect #7589: Wiki page with backslash in title can not be found
+* Defect #7785: Mailhandler keywords are not removed when updating issues
+* Defect #7794: Internal server error on formatting an issue as a PDF in Japanese
+* Defect #7838: Gantt- Issues does not show up in green when start and end date are the same
+* Defect #7846: Headers (h1, etc.) containing backslash followed by a digit are not displayed correctly
+* Defect #7875: CSV export separators in polish locale (pl.yml)
+* Defect #7890: Internal server error when referencing an issue without project in commit message
+* Defect #7904: Subprojects not properly deleted when deleting a parent project
+* Defect #7939: Simultaneous Wiki Updates Cause Internal Error
+* Defect #7951: Atom links broken on wiki index
+* Defect #7954: IE 9 can not select issues, does not display context menu
+* Defect #7985: Trying to do a bulk edit results in "Internal Error"
+* Defect #8003: Error raised by reposman.rb under Windows server 2003
+* Defect #8012: Wrong selection of modules when adding new project after validation error
+* Defect #8038: Associated Revisions OL/LI items are not styled properly in issue view
+* Defect #8067: CSV exporting in Italian locale
+* Defect #8235: bulk edit issues and copy issues error in es, gl and ca locales
+* Defect #8244: selected modules are not activated when copying a project
+* Patch #7278: Update Simplified Chinese translation to 1.1
+* Patch #7390: Fixes in Czech localization
+* Patch #7963: Reminder email: Link for show all issues does not sort
+
+== 2011-03-07 v1.1.2
+
+* Defect #3132: Bulk editing menu non-functional in Opera browser
+* Defect #6090: Most binary files become corrupted when downloading from CVS repository browser when Redmine is running on a Windows server
+* Defect #7280: Issues subjects wrap in Gantt
+* Defect #7288: Non ASCII filename downloaded from repo is broken on Internet Explorer.
+* Defect #7317: Gantt tab gives internal error due to nil avatar icon
+* Defect #7497: Aptana Studio .project file added to version 1.1.1-stable
+* Defect #7611: Workflow summary shows X icon for workflow with exactly 1 status transition
+* Defect #7625: Syntax highlighting unavailable from board new topic or topic edit preview
+* Defect #7630: Spent time in commits not recognized
+* Defect #7656: MySQL SQL Syntax Error when filtering issues by Assignee's Group
+* Defect #7718: Minutes logged in commit message are converted to hours
+* Defect #7763: Email notification are sent to watchers even if 'No events' setting is chosen
+* Feature #7608: Add "retro" gravatars
+* Patch #7598: Extensible MailHandler
+* Patch #7795: Internal server error at journals#index with custom fields
+
+== 2011-01-30 v1.1.1
+
+* Defect #4899: Redmine fails to list files for darcs repository
+* Defect #7245: Wiki fails to find pages with cyrillic characters using postgresql
+* Defect #7256: redmine/public/.htaccess must be moved for non-fastcgi installs/upgrades
+* Defect #7258: Automatic spent time logging does not work properly with SQLite3
+* Defect #7259: Released 1.1.0 uses "devel" label inside admin information
+* Defect #7265: "Loading..." icon does not disappear after add project member
+* Defect #7266: Test test_due_date_distance_in_words fail due to undefined locale
+* Defect #7274: CSV value separator in dutch locale
+* Defect #7277: Enabling gravatas causes usernames to overlap first name field in user list
+* Defect #7294: "Notifiy for only project I select" is not available anymore in 1.1.0
+* Defect #7307: HTTP 500 error on query for empty revision
+* Defect #7313: Label not translated in french in Settings/Email Notification tab
+* Defect #7329: <code class="javascript"> with long strings may hang server
+* Defect #7337: My page french translation
+* Defect #7348: French Translation of "Connection"
+* Defect #7385: Error when viewing an issue which was related to a deleted subtask
+* Defect #7386: NoMethodError on pdf export
+* Defect #7415: Darcs adapter recognizes new files as modified files above Darcs 2.4
+* Defect #7421: no email sent with 'Notifiy for any event on the selected projects only'
+* Feature #5344: Update to latest CodeRay 0.9.x
+
+== 2011-01-09 v1.1.0
+
+* Defect #2038: Italics in wiki headers show-up wrong in the toc
+* Defect #3449: Redmine Takes Too Long On Large Mercurial Repository
+* Defect #3567: Sorting for changesets might go wrong on Mercurial repos
+* Defect #3707: {{toc}} doesn't work with {{include}}
+* Defect #5096: Redmine hangs up while browsing Git repository
+* Defect #6000: Safe Attributes prevents plugin extension of Issue model...
+* Defect #6064: Modules not assigned to projects created via API
+* Defect #6110: MailHandler should allow updating Issue Priority and Custom fields
+* Defect #6136: JSON API holds less information than XML API
+* Defect #6345: xml used by rest API is invalid
+* Defect #6348: Gantt chart PDF rendering errors
+* Defect #6403: Updating an issue with custom fields fails
+* Defect #6467: "Member of role", "Member of group" filter not work correctly
+* Defect #6473: New gantt broken after clearing issue filters
+* Defect #6541: Email notifications send to everybody
+* Defect #6549: Notification settings not migrated properly
+* Defect #6591: Acronyms must have a minimum of three characters
+* Defect #6674: Delete time log broken after changes to REST
+* Defect #6681: Mercurial, Bazaar and Darcs auto close issue text should be commit id instead of revision number
+* Defect #6724: Wiki uploads does not work anymore (SVN 4266)
+* Defect #6746: Wiki links are broken on Activity page
+* Defect #6747: Wiki diff does not work since r4265
+* Defect #6763: New gantt charts: subject displayed twice on issues
+* Defect #6826: Clicking "Add" twice creates duplicate member record
+* Defect #6844: Unchecking status filter on the issue list has no effect
+* Defect #6895: Wrong Polish translation of "blocks"
+* Defect #6943: Migration from boolean to varchar fails on PostgreSQL 8.1
+* Defect #7064: Mercurial adapter does not recognize non alphabetic nor numeric in UTF-8 copied files
+* Defect #7128: New gantt chart does not render subtasks under parent task
+* Defect #7135: paging mechanism returns the same last page forever
+* Defect #7188: Activity page not refreshed when changing language
+* Defect #7195: Apply CLI-supplied defaults for incoming mail only to new issues not replies
+* Defect #7197: Tracker reset to default when replying to an issue email
+* Defect #7213: Copy project does not copy all roles and permissions
+* Defect #7225: Project settings: Trackers & Custom fields only relevant if module Issue tracking is active
+* Feature #630: Allow non-unique names for projects
+* Feature #1738: Add a "Visible" flag to project/user custom fields
+* Feature #2803: Support for Javascript in Themes
+* Feature #2852: Clean Incoming Email of quoted text "----- Reply above this line ------"
+* Feature #2995: Improve error message when trying to access an archived project
+* Feature #3170: Autocomplete issue relations on subject
+* Feature #3503: Administrator Be Able To Modify Email settings Of Users
+* Feature #4155: Automatic spent time logging from commit messages
+* Feature #5136: Parent select on Wiki rename page
+* Feature #5338: Descendants (subtasks) should be available via REST API
+* Feature #5494: Wiki TOC should display heading from level 4
+* Feature #5594: Improve MailHandler's keyword handling
+* Feature #5622: Allow version to be set via incoming email
+* Feature #5712: Reload themes
+* Feature #5869: Issue filters by Group and Role
+* Feature #6092: Truncate Git revision labels in Activity page/feed and allow configurable length
+* Feature #6112: Accept localized keywords when receiving emails
+* Feature #6140: REST issues response with issue count limit and offset
+* Feature #6260: REST API for Users
+* Feature #6276: Gantt Chart rewrite
+* Feature #6446: Remove length limits on project identifier and name
+* Feature #6628: Improvements in truncate email
+* Feature #6779: Project JSON API
+* Feature #6823: REST API for time tracker.
+* Feature #7072: REST API for news
+* Feature #7111: Expose more detail on journal entries
+* Feature #7141: REST API: get information about current user
+* Patch #4807: Allow to set the done_ratio field with the incoming mail system
+* Patch #5441: Initialize TimeEntry attributes with params[:time_entry]
+* Patch #6762: Use GET instead of POST to retrieve context_menu
+* Patch #7160: French translation ofr "not_a_date" is missing
+* Patch #7212: Missing remove_index in AddUniqueIndexOnMembers down migration
+
+
+== 2010-12-23 v1.0.5
+
+* #6656: Mercurial adapter loses seconds of commit times
+* #6996: Migration trac(sqlite3) -> redmine(postgresql) doesnt escape ' char
+* #7013: v-1.0.4 trunk - see {{count}} in page display rather than value
+* #7016: redundant 'field_start_date' in ja.yml
+* #7018: 'undefined method `reschedule_after' for nil:NilClass' on new issues
+* #7024: E-mail notifications about Wiki changes.
+* #7033: 'class' attribute of <pre> tag shouldn't be truncate
+* #7035: CSV value separator in russian
+* #7122: Issue-description Quote-button missing
+* #7144: custom queries making use of deleted custom fields cause a 500 error
+* #7162: Multiply defined label in french translation
+
+== 2010-11-28 v1.0.4
+
+* #5324: Git not working if color.ui is enabled
+* #6447: Issues API doesn't allow full key auth for all actions
+* #6457: Edit User group problem
+* #6575: start date being filled with current date even when blank value is submitted
+* #6740: Max attachment size, incorrect usage of 'KB'
+* #6760: Select box sorted by ID instead of name in Issue Category
+* #6766: Changing target version name can cause an internal error
+* #6784: Redmine not working with i18n gem 0.4.2
+* #6839: Hardcoded absolute links in my/page_layout
+* #6841: Projects API doesn't allow full key auth for all actions
+* #6860: svn: Write error: Broken pipe when browsing repository
+* #6874: API should return XML description when creating a project
+* #6932: submitting wrong parent task input creates a 500 error
+* #6966: Records of Forums are remained, deleting project
+* #6990: Layout problem in workflow overview
+* #5117: mercurial_adapter should ensure the right LANG environment variable
+* #6782: Traditional Chinese language file (to r4352)
+* #6783: Swedish Translation for r4352
+* #6804: Bugfix: spelling fixes
+* #6814: Japanese Translation for r4362
+* #6948: Bulgarian translation
+* #6973: Update es.yml
+
+== 2010-10-31 v1.0.3
+
+* #4065: Redmine.pm doesn't work with LDAPS and a non-standard port
+* #4416: Link from version details page to edit the wiki.
+* #5484: Add new issue as subtask to an existing ticket
+* #5948: Update help/wiki_syntax_detailed.html with more link options
+* #6494: Typo in pt_BR translation for 1.0.2
+* #6508: Japanese translation update
+* #6509: Localization pt-PT (new strings)
+* #6511: Rake task to test email
+* #6525: Traditional Chinese language file (to r4225)
+* #6536: Patch for swedish translation
+* #6548: Rake tasks to add/remove i18n strings
+* #6569: Updated Hebrew translation
+* #6570: Japanese Translation for r4231
+* #6596: pt-BR translation updates
+* #6629: Change field-name of issues start date
+* #6669: Bulgarian translation
+* #6731: Macedonian translation fix
+* #6732: Japanese Translation for r4287
+* #6735: Add user-agent to reposman
+* #6736: Traditional Chinese language file (to r4288)
+* #6739: Swedish Translation for r4288
+* #6765: Traditional Chinese language file (to r4302)
+* Fixed #5324: Git not working if color.ui is enabled
+* Fixed #5652: Bad URL parsing in the wiki when it ends with right-angle-bracket(greater-than mark).
+* Fixed #5803: Precedes/Follows Relationships Broke
+* Fixed #6435: Links to wikipages bound to versions do not respect version-sharing in Settings -> Versions
+* Fixed #6438: Autologin cannot be disabled again once it's enabled
+* Fixed #6513: "Move" and "Copy" are not displayed when deployed in subdirectory
+* Fixed #6521: Tooltip/label for user "search-refinment" field on group/project member list
+* Fixed #6563: i18n-issues on calendar view
+* Fixed #6598: Wrong caption for button_create_and_continue in German language file
+* Fixed #6607: Unclear caption for german button_update
+* Fixed #6612: SortHelper missing from CalendarsController
+* Fixed #6740: Max attachment size, incorrect usage of 'KB'
+* Fixed #6750: ActionView::TemplateError (undefined method `empty?' for nil:NilClass) on line #12 of app/views/context_menus/issues.html.erb:
+
+== 2010-09-26 v1.0.2
+
+* #2285: issue-refinement: pressing enter should result to an "apply"
+* #3411: Allow mass status update trough context menu
+* #5929: https-enabled gravatars when called over https
+* #6189: Japanese Translation for r4011
+* #6197: Traditional Chinese language file (to r4036)
+* #6198: Updated german translation
+* #6208: Macedonian translation
+* #6210: Swedish Translation for r4039
+* #6248: nl translation update for r4050
+* #6263: Catalan translation update
+* #6275: After submitting a related issue, the Issue field should be re-focused
+* #6289: Checkboxes in issues list shouldn't be displayed when printing
+* #6290: Make journals theming easier
+* #6291: User#allowed_to? is not tested
+* #6306: Traditional Chinese language file (to r4061)
+* #6307: Korean translation update for 4066(4061)
+* #6316: pt_BR update
+* #6339: SERBIAN Updated
+* #6358: Updated Polish translation
+* #6363: Japanese Translation for r4080
+* #6365: Traditional Chinese language file (to r4081)
+* #6382: Issue PDF export variable usage
+* #6428: Interim solution for i18n >= 0.4
+* #6441: Japanese Translation for r4162
+* #6451: Traditional Chinese language file (to r4167)
+* #6465: Japanese Translation for r4171
+* #6466: Traditional Chinese language file (to r4171)
+* #6490: pt-BR translation for 1.0.2
+* Fixed #3935: stylesheet_link_tag with plugin doesn't take into account relative_url_root
+* Fixed #4998: Global issue list's context menu has enabled options for parent menus but there are no valid selections
+* Fixed #5170: Done ratio can not revert to 0% if status is used for done ratio
+* Fixed #5608: broken with i18n 0.4.0
+* Fixed #6054: Error 500 on filenames with whitespace in git reposities
+* Fixed #6135: Default logger configuration grows without bound.
+* Fixed #6191: Deletion of a main task deletes all subtasks
+* Fixed #6195: Missing move issues between projects
+* Fixed #6242: can't switch between inline and side-by-side diff
+* Fixed #6249: Create and continue returns 404
+* Fixed #6267: changing the authentication mode from ldap to internal with setting the password
+* Fixed #6270: diff coderay malformed in the "news" page
+* Fixed #6278: missing "cant_link_an_issue_with_a_descendant"from locale files
+* Fixed #6333: Create and continue results in a 404 Error
+* Fixed #6346: Age column on repository view is skewed for git, probably CVS too
+* Fixed #6351: Context menu on roadmap broken
+* Fixed #6388: New Subproject leads to a 404
+* Fixed #6392: Updated/Created links to activity broken
+* Fixed #6413: Error in SQL
+* Fixed #6443: Redirect to project settings after Copying a Project
+* Fixed #6448: Saving a wiki page with no content has a translation missing
+* Fixed #6452: Unhandled exception on creating File
+* Fixed #6471: Typo in label_report in Czech translation
+* Fixed #6479: Changing tracker type will lose watchers
+* Fixed #6499: Files with leading or trailing whitespace are not shown in git.
+
+== 2010-08-22 v1.0.1
+
+* #819: Add a body ID and class to all pages
+* #871: Commit new CSS styles!
+* #3301: Add favicon to base layout
+* #4656: On Issue#show page, clicking on “Add related issue� should focus on the input
+* #4896: Project identifier should be a limited field
+* #5084: Filter all isssues by projects
+* #5477: Replace Test::Unit::TestCase with ActiveSupport::TestCase
+* #5591: 'calendar' action is used with 'issue' controller in issue/sidebar
+* #5735: Traditional Chinese language file (to r3810)
+* #5740: Swedish Translation for r3810
+* #5785: pt-BR translation update
+* #5898: Projects should be displayed as links in users/memberships
+* #5910: Chinese translation to redmine-1.0.0
+* #5912: Translation update for french locale
+* #5962: Hungarian translation update to r3892
+* #5971: Remove falsly applied chrome on revision links
+* #5972: Updated Hebrew translation for 1.0.0
+* #5982: Updated german translation
+* #6008: Move admin_menu to Redmine::MenuManager
+* #6012: RTL layout
+* #6021: Spanish translation 1.0.0-RC
+* #6025: nl translation updated for r3905
+* #6030: Japanese Translation for r3907
+* #6074: sr-CY.yml contains DOS-type newlines (\r\n)
+* #6087: SERBIAN translation updated
+* #6093: Updated italian translation
+* #6142: Swedish Translation for r3940
+* #6153: Move view_calendar and view_gantt to own modules
+* #6169: Add issue status to issue tooltip
+* Fixed #3834: Add a warning when not choosing a member role
+* Fixed #3922: Bad english arround "Assigned to" text in journal entries
+* Fixed #5158: Simplified Chinese language file zh.yml updated to r3608
+* Fixed #5162: translation missing: zh-TW, field_time_entrie
+* Fixed #5297: openid not validated correctly
+* Fixed #5628: Wrong commit range in git log command
+* Fixed #5760: Assigned_to and author filters in "Projects>View all issues" should be based on user's project visibility
+* Fixed #5771: Problem when importing git repository
+* Fixed #5775: ldap authentication in admin menu should have an icon
+* Fixed #5811: deleting statuses doesnt delete workflow entries
+* Fixed #5834: Emails with trailing spaces incorrectly detected as invalid
+* Fixed #5846: ChangeChangesPathLengthLimit does not remove default for MySQL
+* Fixed #5861: Vertical scrollbar always visible in Wiki "code" blocks in Chrome.
+* Fixed #5883: correct label_project_latest Chinese translation
+* Fixed #5892: Changing status from contextual menu opens the ticket instead
+* Fixed #5904: Global gantt PDF and PNG should display project names
+* Fixed #5925: parent task's priority edit should be disabled through shortcut menu in issues list page
+* Fixed #5935: Add Another file to ticket doesn't work in IE Internet Explorer
+* Fixed #5937: Harmonize french locale "zero" translation with other locales
+* Fixed #5945: Forum message permalinks don't take pagination into account
+* Fixed #5978: Debug code still remains
+* Fixed #6009: When using "English (British)", the repository browser (svn) shows files over 1000 bytes as floating point (2.334355)
+* Fixed #6045: Repository file Diff view sometimes shows more than selected file
+* Fixed #6079: German Translation error in TimeEntryActivity
+* Fixed #6100: User's profile should display all visible projects
+* Fixed #6132: Allow Key based authentication in the Boards atom feed
+* Fixed #6163: Bad CSS class for calendar project menu_item
+* Fixed #6172: Browsing to a missing user's page shows the admin sidebar
+
+== 2010-07-18 v1.0.0 (Release candidate)
+
+* #443: Adds context menu to the roadmap issue lists
+* #443: Subtasking
+* #741: Description preview while editing an issue
+* #1131: Add support for alternate (non-LDAP) authentication
+* #1214: REST API for Issues
+* #1223: File upload on wiki edit form
+* #1755: add "blocked by" as a related issues option
+* #2420: Fetching emails from an POP server
+* #2482: Named scopes in Issue and ActsAsWatchable plus some view refactoring (logic extraction).
+* #2924: Make the right click menu more discoverable using a cursor property
+* #2985: Make syntax highlighting pluggable
+* #3201: Workflow Check/Uncheck All Rows/Columns
+* #3359: Update CodeRay 0.9
+* #3706: Allow assigned_to field configuration on Issue creation by email
+* #3936: configurable list of models to include in search
+* #4480: Create a link to the user profile from the administration interface
+* #4482: Cache textile rendering
+* #4572: Make it harder to ruin your database
+* #4573: Move github gems to Gemcutter
+* #4664: Add pagination to forum threads
+* #4732: Make login case-insensitive also for PostgreSQL
+* #4812: Create links to other projects
+* #4819: Replace images with smushed ones for speed
+* #4945: Allow custom fields attached to project to be searchable
+* #5121: Fix issues list layout overflow
+* #5169: Issue list view hook request
+* #5208: Aibility to edit wiki sidebar
+* #5281: Remove empty ul tags in the issue history
+* #5291: Updated basque translations
+* #5328: Automatically add "Repository" menu_item after repository creation
+* #5415: Fewer SQL statements generated for watcher_recipients
+* #5416: Exclude "fields_for" from overridden methods in TabularFormBuilder
+* #5573: Allow issue assignment in email
+* #5595: Allow start date and due dates to be set via incoming email
+* #5752: The projects view (/projects) renders ul's wrong
+* #5781: Allow to use more macros on the welcome page and project list
+* Fixed #1288: Unable to past escaped wiki syntax in an issue description
+* Fixed #1334: Wiki formatting character *_ and _*
+* Fixed #1416: Inline code with less-then/greater-than produces @lt; and @gt; respectively
+* Fixed #2473: Login and mail should not be case sensitive
+* Fixed #2990: Ruby 1.9 - wrong number of arguments (1 for 0) on rake db:migrate
+* Fixed #3089: Text formatting sometimes breaks when combined
+* Fixed #3690: Status change info duplicates on the issue screen
+* Fixed #3691: Redmine allows two files with the same file name to be uploaded to the same issue
+* Fixed #3764: ApplicationHelperTest fails with JRuby
+* Fixed #4265: Unclosed code tags in issue descriptions affects main UI
+* Fixed #4745: Bug in index.xml.builder (issues)
+* Fixed #4852: changing user/roles of project member not possible without javascript
+* Fixed #4857: Week number calculation in date picker is wrong if a week starts with Sunday
+* Fixed #4883: Bottom "contextual" placement in issue with associated changeset
+* Fixed #4918: Revisions r3453 and r3454 broke On-the-fly user creation with LDAP
+* Fixed #4935: Navigation to the Master Timesheet page (time_entries)
+* Fixed #5043: Flash messages are not displayed after the project settings[module/activity] saved
+* Fixed #5081: Broken links on public/help/wiki_syntax_detailed.html
+* Fixed #5104: Description of document not wikified on documents index
+* Fixed #5108: Issue linking fails inside of []s
+* Fixed #5199: diff code coloring using coderay
+* Fixed #5233: Add a hook to the issue report (Summary) view
+* Fixed #5265: timetracking: subtasks time is added to the main task
+* Fixed #5343: acts_as_event Doesn't Accept Outside URLs
+* Fixed #5440: UI Inconsistency : Administration > Enumerations table row headers should be enclosed in <thead>
+* Fixed #5463: 0.9.4 INSTALL and/or UPGRADE, missing session_store.rb
+* Fixed #5524: Update_parent_attributes doesn't work for the old parent issue when reparenting
+* Fixed #5548: SVN Repository: Can not list content of a folder which includes square brackets.
+* Fixed #5589: "with subproject" malfunction
+* Fixed #5676: Search for Numeric Value
+* Fixed #5696: Redmine + PostgreSQL 8.4.4 fails on _dir_list_content.rhtml
+* Fixed #5698: redmine:email:receive_imap fails silently for mails with subject longer than 255 characters
+* Fixed #5700: TimelogController#destroy assumes success
+* Fixed #5751: developer role is mispelled
+* Fixed #5769: Popup Calendar doesn't Advance in Chrome
+* Fixed #5771: Problem when importing git repository
+* Fixed #5823: Error in comments in plugin.rb
+
+
+== 2010-07-07 v0.9.6
+
+* Fixed: Redmine.pm access by unauthorized users
+
+== 2010-06-24 v0.9.5
+
+* Linkify folder names on revision view
+* "fiters" and "options" should be hidden in print view via css
+* Fixed: NoMethodError when no issue params are submitted
+* Fixed: projects.atom with required authentication
+* Fixed: External links not correctly displayed in Wiki TOC
+* Fixed: Member role forms in project settings are not hidden after member added
+* Fixed: pre can't be inside p
+* Fixed: session cookie path does not respect RAILS_RELATIVE_URL_ROOT
+* Fixed: mail handler fails when the from address is empty
+
+
+== 2010-05-01 v0.9.4
+
+* Filters collapsed by default on issues index page for a saved query
+* Fixed: When categories list is too big the popup menu doesn't adjust (ex. in the issue list)
+* Fixed: remove "main-menu" div when the menu is empty
+* Fixed: Code syntax highlighting not working in Document page
+* Fixed: Git blame/annotate fails on moved files
+* Fixed: Failing test in test_show_atom
+* Fixed: Migrate from trac - not displayed Wikis
+* Fixed: Email notifications on file upload sent to empty recipient list
+* Fixed: Migrating from trac is not possible, fails to allocate memory
+* Fixed: Lost password no longer flashes a confirmation message
+* Fixed: Crash while deleting in-use enumeration
+* Fixed: Hard coded English string at the selection of issue watchers
+* Fixed: Bazaar v2.1.0 changed behaviour
+* Fixed: Roadmap display can raise an exception if no trackers are selected
+* Fixed: Gravatar breaks layout of "logged in" page
+* Fixed: Reposman.rb on Windows
+* Fixed: Possible error 500 while moving an issue to another project with SQLite
+* Fixed: backslashes in issue description/note should be escaped when quoted
+* Fixed: Long text in <pre> disrupts Associated revisions
+* Fixed: Links to missing wiki pages not red on project overview page
+* Fixed: Cannot delete a project with subprojects that shares versions
+* Fixed: Update of Subversion changesets broken under Solaris
+* Fixed: "Move issues" permission not working for Non member
+* Fixed: Sidebar overlap on Users tab of Group editor
+* Fixed: Error on db:migrate with table prefix set (hardcoded name in principal.rb)
+* Fixed: Report shows sub-projects for non-members
+* Fixed: 500 internal error when browsing any Redmine page in epiphany
+* Fixed: Watchers selection lost when issue creation fails
+* Fixed: When copying projects, redmine should not generate an email to people who created issues
+* Fixed: Issue "#" table cells should have a class attribute to enable fine-grained CSS theme
+* Fixed: Plugin generators should display help if no parameter is given
+
+
+== 2010-02-28 v0.9.3
+
+* Adds filter for system shared versions on the cross project issue list
+* Makes project identifiers searchable
+* Remove invalid utf8 sequences from commit comments and author name
+* Fixed: Wrong link when "http" not included in project "Homepage" link
+* Fixed: Escaping in html email templates
+* Fixed: Pound (#) followed by number with leading zero (0) removes leading zero when rendered in wiki
+* Fixed: Deselecting textile text formatting causes interning empty string errors
+* Fixed: error with postgres when entering a non-numeric id for an issue relation
+* Fixed: div.task incorrectly wrapping on Gantt Chart
+* Fixed: Project copy loses wiki pages hierarchy
+* Fixed: parent project field doesn't include blank value when a member with 'add subproject' permission edits a child project
+* Fixed: Repository.fetch_changesets tries to fetch changesets for archived projects
+* Fixed: Duplicated project name for subproject version on gantt chart
+* Fixed: roadmap shows subprojects issues even if subprojects is unchecked
+* Fixed: IndexError if all the :last menu items are deleted from a menu
+* Fixed: Very high CPU usage for a long time when fetching commits from a large Git repository
+
+
+== 2010-02-07 v0.9.2
+
+* Fixed: Sub-project repository commits not displayed on parent project issues
+* Fixed: Potential security leak on my page calendar
+* Fixed: Project tree structure is broken by deleting the project with the subproject
+* Fixed: Error message shown duplicated when creating a new group
+* Fixed: Firefox cuts off large pages
+* Fixed: Invalid format parameter returns a DoubleRenderError on issues index
+* Fixed: Unnecessary Quote button on locked forum message
+* Fixed: Error raised when trying to view the gantt or calendar with a grouped query
+* Fixed: PDF support for Korean locale
+* Fixed: Deprecation warning in extra/svn/reposman.rb
+
+
+== 2010-01-30 v0.9.1
+
+* Vertical alignment for inline images in formatted text set to 'middle'
+* Fixed: Redmine.pm error "closing dbh with active statement handles at /usr/lib/perl5/Apache/Redmine.pm"
+* Fixed: copyright year in footer set to 2010
+* Fixed: Trac migration script may not output query lines
+* Fixed: Email notifications may affect language of notice messages on the UI
+* Fixed: Can not search for 2 letters word
+* Fixed: Attachments get saved on issue update even if validation fails
+* Fixed: Tab's 'border-bottom' not absent when selected
+* Fixed: Issue summary tables that list by user are not sorted
+* Fixed: Issue pdf export fails if target version is set
+* Fixed: Issue list export to PDF breaks when issues are sorted by a custom field
+* Fixed: SQL error when adding a group
+* Fixes: Min password length during password reset always displays as 4 chars
+
+
+== 2010-01-09 v0.9.0 (Release candidate)
+
+* Unlimited subproject nesting
+* Multiple roles per user per project
+* User groups
+* Inheritence of versions
+* OpenID login
+* "Watched by me" issue filter
+* Project copy
+* Project creation by non admin users
+* Accept emails from anyone on a private project
+* Add email notification on Wiki changes
+* Make issue description non-required field
+* Custom fields for Versions
+* Being able to sort the issue list by custom fields
+* Ability to close versions
+* User display/editing of custom fields attached to their user profile
+* Add "follows" issue relation
+* Copy workflows between trackers and roles
+* Defaults enabled modules list for project creation
+* Weighted version completion percentage on the roadmap
+* Autocreate user account when user submits email that creates new issue
+* CSS class on overdue issues on the issue list
+* Enable tracker update on issue edit form
+* Remove issue watchers
+* Ability to move threads between project forums
+* Changed custom field "Possible values" to a textarea
+* Adds projects association on tracker form
+* Set session store to cookie store by default
+* Set a default wiki page on project creation
+* Roadmap for main project should see Roadmaps for sub projects
+* Ticket grouping on the issue list
+* Hierarchical Project links in the page header
+* Allow My Page blocks to be added to from a plugin
+* Sort issues by multiple columns
+* Filters of saved query are now visible and be adjusted without editing the query
+* Saving "sort order" in custom queries
+* Url to fetch changesets for a repository
+* Managers able to create subprojects
+* Issue Totals on My Page Modules
+* Convert Enumerations to single table inheritance (STI)
+* Allow custom my_page blocks to define drop-down names
+* "View Issues" user permission added
+* Ask user what to do with child pages when deleting a parent wiki page
+* Contextual quick search
+* Allow resending of password by email
+* Change reply subject to be a link to the reply itself
+* Include Logged Time as part of the project's Activity history
+* REST API for authentication
+* Browse through Git branches
+* Setup Object Daddy to replace test fixtures
+* Setup shoulda to make it easier to test
+* Custom fields and overrides on Enumerations
+* Add or remove columns from the issue list
+* Ability to add new version from issues screen
+* Setting to choose which day calendars start
+* Asynchronous email delivery method
+* RESTful URLs for (almost) everything
+* Include issue status in search results and activity pages
+* Add email to admin user search filter
+* Proper content type for plain text mails
+* Default value of project jump box
+* Tree based menus
+* Ability to use issue status to update percent done
+* Second set of issue "Action Links" at the bottom of an issue page
+* Proper exist status code for rdm-mailhandler.rb
+* Remove incoming email body via a delimiter
+* Fixed: Custom querry 'Export to PDF' ignores field selection
+* Fixed: Related e-mail notifications aren't threaded
+* Fixed: No warning when the creation of a categories from the issue form fails
+* Fixed: Actually block issues from closing when relation 'blocked by' isn't closed
+* Fixed: Include both first and last name when sorting by users
+* Fixed: Table cell with multiple line text
+* Fixed: Project overview page shows disabled trackers
+* Fixed: Cross project issue relations and user permissions
+* Fixed: My page shows tickets the user doesn't have access to
+* Fixed: TOC does not parse wiki page reference links with description
+* Fixed: Target version-list on bulk edit form is incorrectly sorted
+* Fixed: Cannot modify/delete project named "Documents"
+* Fixed: Email address in brackets breaks html
+* Fixed: Timelog detail loose issue filter passing to report tab
+* Fixed: Inform about custom field's name maximum length
+* Fixed: Activity page and Atom feed links contain project id instead of identifier
+* Fixed: no Atom key for forums with only 1 forum
+* Fixed: When reading RSS feed in MS Outlook, the inline links are broken.
+* Fixed: Sometimes new posts don't show up in the topic list of a forum.
+* Fixed: The all/active filter selection in the project view does not stick.
+* Fixed: Login box has Different width
+* Fixed: User removed from project - still getting project update emails
+* Fixed: Project with the identifier of 'new' cannot be viewed
+* Fixed: Artefacts in search view (Cyrillic)
+* Fixed: Allow [#id] as subject to reply by email
+* Fixed: Wrong language used when closing an issue via a commit message
+* Fixed: email handler drops emails for new issues with no subject
+* Fixed: Calendar misspelled under Roles/Permissions
+* Fixed: Emails from no-reply redmine's address hell cycle
+* Fixed: child_pages macro fails on wiki page history
+* Fixed: Pre-filled time tracking date ignores timezone
+* Fixed: Links on locked users lead to 404 page
+* Fixed: Page changes in issue-list when using context menu
+* Fixed: diff parser removes lines starting with multiple dashes
+* Fixed: Quoting in forums resets message subject
+* Fixed: Editing issue comment removes quote link
+* Fixed: Redmine.pm ignore browse_repository permission
+* Fixed: text formatting breaks on [msg1][msg2]
+* Fixed: Spent Time Default Value of 0.0
+* Fixed: Wiki pages in search results are referenced by project number, not by project identifier.
+* Fixed: When logging in via an autologin cookie the user's last_login_on should be updated
+* Fixed: 50k users cause problems in project->settings->members screen
+* Fixed: Document timestamp needs to show updated timestamps
+* Fixed: Users getting notifications for issues they are no longer allowed to view
+* Fixed: issue summary counts should link to the issue list without subprojects
+* Fixed: 'Delete' link on LDAP list has no effect
+
+
+== 2009-11-15 v0.8.7
+
+* Fixed: Hide paragraph terminator at the end of headings on html export
+* Fixed: pre tags containing "<pre*"
+* Fixed: First date of the date range not included in the time report with SQLite
+* Fixed: Password field not styled correctly on alternative stylesheet
+* Fixed: Error when sumbitting a POST request that requires a login
+* Fixed: CSRF vulnerabilities
+
+
+== 2009-11-04 v0.8.6
+
+* Change links to closed issues to be a grey color
+* Change subversion adapter to not cache authentication and run non interactively
+* Fixed: Custom Values with a nil value cause HTTP error 500
+* Fixed: Failure to convert HTML entities when editing an Issue reply
+* Fixed: Error trying to show repository when there are no comments in a changeset
+* Fixed: account/show/:user_id should not be accessible for other users not in your projects
+* Fixed: XSS vulnerabilities
+* Fixed: IssuesController#destroy should accept POST only
+* Fixed: Inline images in wiki headings
+
+
+== 2009-09-13 v0.8.5
+
+* Incoming mail handler : Allow spaces between keywords and colon
+* Do not require a non-word character after a comma in Redmine links
+* Include issue hyperlinks in reminder emails
+* Prevent nil error when retrieving svn version
+* Various plugin hooks added
+* Add plugins information to script/about
+* Fixed: 500 Internal Server Error is raised if add an empty comment to the news
+* Fixed: Atom links for wiki pages are not correct
+* Fixed: Atom feeds leak email address
+* Fixed: Case sensitivity in Issue filtering
+* Fixed: When reading RSS feed, the inline-embedded images are not properly shown
+
+
+== 2009-05-17 v0.8.4
+
+* Allow textile mailto links
+* Fixed: memory consumption when uploading file
+* Fixed: Mercurial integration doesn't work if Redmine is installed in folder path containing space
+* Fixed: an error is raised when no tab is available on project settings
+* Fixed: insert image macro corrupts urls with excalamation marks
+* Fixed: error on cross-project gantt PNG export
+* Fixed: self and alternate links in atom feeds do not respect Atom specs
+* Fixed: accept any svn tunnel scheme in repository URL
+* Fixed: issues/show should accept user's rss key
+* Fixed: consistency of custom fields display on the issue detail view
+* Fixed: wiki comments length validation is missing
+* Fixed: weak autologin token generation algorithm causes duplicate tokens
+
+
+== 2009-04-05 v0.8.3
+
+* Separate project field and subject in cross-project issue view
+* Ability to set language for redmine:load_default_data task using REDMINE_LANG environment variable
+* Rescue Redmine::DefaultData::DataAlreadyLoaded in redmine:load_default_data task
+* CSS classes to highlight own and assigned issues
+* Hide "New file" link on wiki pages from printing
+* Flush buffer when asking for language in redmine:load_default_data task
+* Minimum project identifier length set to 1
+* Include headers so that emails don't trigger vacation auto-responders
+* Fixed: Time entries csv export links for all projects are malformed
+* Fixed: Files without Version aren't visible in the Activity page
+* Fixed: Commit logs are centered in the repo browser
+* Fixed: News summary field content is not searchable
+* Fixed: Journal#save has a wrong signature
+* Fixed: Email footer signature convention
+* Fixed: Timelog report do not show time for non-versioned issues
+
+
+== 2009-03-07 v0.8.2
+
+* Send an email to the user when an administrator activates a registered user
+* Strip keywords from received email body
+* Footer updated to 2009
+* Show RSS-link even when no issues is found
+* One click filter action in activity view
+* Clickable/linkable line #'s while browsing the repo or viewing a file
+* Links to versions on files list
+* Added request and controller objects to the hooks by default
+* Fixed: exporting an issue with attachments to PDF raises an error
+* Fixed: "too few arguments" error may occur on activerecord error translation
+* Fixed: "Default columns Displayed on the Issues list" setting is not easy to read
+* Fixed: visited links to closed tickets are not striked through with IE6
+* Fixed: MailHandler#plain_text_body returns nil if there was nothing to strip
+* Fixed: MailHandler raises an error when processing an email without From header
+
+
+== 2009-02-15 v0.8.1
+
+* Select watchers on new issue form
+* Issue description is no longer a required field
+* Files module: ability to add files without version
+* Jump to the current tab when using the project quick-jump combo
+* Display a warning if some attachments were not saved
+* Import custom fields values from emails on issue creation
+* Show view/annotate/download links on entry and annotate views
+* Admin Info Screen: Display if plugin assets directory is writable
+* Adds a 'Create and continue' button on the new issue form
+* IMAP: add options to move received emails
+* Do not show Category field when categories are not defined
+* Lower the project identifier limit to a minimum of two characters
+* Add "closed" html class to closed entries in issue list
+* Fixed: broken redirect URL on login failure
+* Fixed: Deleted files are shown when using Darcs
+* Fixed: Darcs adapter works on Win32 only
+* Fixed: syntax highlight doesn't appear in new ticket preview
+* Fixed: email notification for changes I make still occurs when running Repository.fetch_changesets
+* Fixed: no error is raised when entering invalid hours on the issue update form
+* Fixed: Details time log report CSV export doesn't honour date format from settings
+* Fixed: invalid css classes on issue details
+* Fixed: Trac importer creates duplicate custom values
+* Fixed: inline attached image should not match partial filename
+
+
+== 2008-12-30 v0.8.0
+
+* Setting added in order to limit the number of diff lines that should be displayed
+* Makes logged-in username in topbar linking to
+* Mail handler: strip tags when receiving a html-only email
+* Mail handler: add watchers before sending notification
+* Adds a css class (overdue) to overdue issues on issue lists and detail views
+* Fixed: project activity truncated after viewing user's activity
+* Fixed: email address entered for password recovery shouldn't be case-sensitive
+* Fixed: default flag removed when editing a default enumeration
+* Fixed: default category ignored when adding a document
+* Fixed: error on repository user mapping when a repository username is blank
+* Fixed: Firefox cuts off large diffs
+* Fixed: CVS browser should not show dead revisions (deleted files)
+* Fixed: escape double-quotes in image titles
+* Fixed: escape textarea content when editing a issue note
+* Fixed: JS error on context menu with IE
+* Fixed: bold syntax around single character in series doesn't work
+* Fixed several XSS vulnerabilities
+* Fixed a SQL injection vulnerability
+
+
+== 2008-12-07 v0.8.0-rc1
+
+* Wiki page protection
+* Wiki page hierarchy. Parent page can be assigned on the Rename screen
+* Adds support for issue creation via email
+* Adds support for free ticket filtering and custom queries on Gantt chart and calendar
+* Cross-project search
+* Ability to search a project and its subprojects
+* Ability to search the projects the user belongs to
+* Adds custom fields on time entries
+* Adds boolean and list custom fields for time entries as criteria on time report
+* Cross-project time reports
+* Display latest user's activity on account/show view
+* Show last connexion time on user's page
+* Obfuscates email address on user's account page using javascript
+* wiki TOC rendered as an unordered list
+* Adds the ability to search for a user on the administration users list
+* Adds the ability to search for a project name or identifier on the administration projects list
+* Redirect user to the previous page after logging in
+* Adds a permission 'view wiki edits' so that wiki history can be hidden to certain users
+* Adds permissions for viewing the watcher list and adding new watchers on the issue detail view
+* Adds permissions to let users edit and/or delete their messages
+* Link to activity view when displaying dates
+* Hide Redmine version in atom feeds and pdf properties
+* Maps repository users to Redmine users. Users with same username or email are automatically mapped. Mapping can be manually adjusted in repository settings. Multiple usernames can be mapped to the same Redmine user.
+* Sort users by their display names so that user dropdown lists are sorted alphabetically
+* Adds estimated hours to issue filters
+* Switch order of current and previous revisions in side-by-side diff
+* Render the commit changes list as a tree
+* Adds watch/unwatch functionality at forum topic level
+* When moving an issue to another project, reassign it to the category with same name if any
+* Adds child_pages macro for wiki pages
+* Use GET instead of POST on roadmap (#718), gantt and calendar forms
+* Search engine: display total results count and count by result type
+* Email delivery configuration moved to an unversioned YAML file (config/email.yml, see the sample file)
+* Adds icons on search results
+* Adds 'Edit' link on account/show for admin users
+* Adds Lock/Unlock/Activate link on user edit screen
+* Adds user count in status drop down on admin user list
+* Adds multi-levels blockquotes support by using > at the beginning of lines
+* Adds a Reply link to each issue note
+* Adds plain text only option for mail notifications
+* Gravatar support for issue detail, user grid, and activity stream (disabled by default)
+* Adds 'Delete wiki pages attachments' permission
+* Show the most recent file when displaying an inline image
+* Makes permission screens localized
+* AuthSource list: display associated users count and disable 'Delete' buton if any
+* Make the 'duplicates of' relation asymmetric
+* Adds username to the password reminder email
+* Adds links to forum messages using message#id syntax
+* Allow same name for custom fields on different object types
+* One-click bulk edition using the issue list context menu within the same project
+* Adds support for commit logs reencoding to UTF-8 before insertion in the database. Source encoding of commit logs can be selected in Application settings -> Repositories.
+* Adds checkboxes toggle links on permissions report
+* Adds Trac-Like anchors on wiki headings
+* Adds support for wiki links with anchor
+* Adds category to the issue context menu
+* Adds a workflow overview screen
+* Appends the filename to the attachment url so that clients that ignore content-disposition http header get the real filename
+* Dots allowed in custom field name
+* Adds posts quoting functionality
+* Adds an option to generate sequential project identifiers
+* Adds mailto link on the user administration list
+* Ability to remove enumerations (activities, priorities, document categories) that are in use. Associated objects can be reassigned to another value
+* Gantt chart: display issues that don't have a due date if they are assigned to a version with a date
+* Change projects homepage limit to 255 chars
+* Improved on-the-fly account creation. If some attributes are missing (eg. not present in the LDAP) or are invalid, the registration form is displayed so that the user is able to fill or fix these attributes
+* Adds "please select" to activity select box if no activity is set as default
+* Do not silently ignore timelog validation failure on issue edit
+* Adds a rake task to send reminder emails
+* Allow empty cells in wiki tables
+* Makes wiki text formatter pluggable
+* Adds back textile acronyms support
+* Remove pre tag attributes
+* Plugin hooks
+* Pluggable admin menu
+* Plugins can provide activity content
+* Moves plugin list to its own administration menu item
+* Adds url and author_url plugin attributes
+* Adds Plugin#requires_redmine method so that plugin compatibility can be checked against current Redmine version
+* Adds atom feed on time entries details
+* Adds project name to issues feed title
+* Adds a css class on menu items in order to apply item specific styles (eg. icons)
+* Adds a Redmine plugin generators
+* Adds timelog link to the issue context menu
+* Adds links to the user page on various views
+* Turkish translation by Ismail Sezen
+* Catalan translation
+* Vietnamese translation
+* Slovak translation
+* Better naming of activity feed if only one kind of event is displayed
+* Enable syntax highlight on issues, messages and news
+* Add target version to the issue list context menu
+* Hide 'Target version' filter if no version is defined
+* Add filters on cross-project issue list for custom fields marked as 'For all projects'
+* Turn ftp urls into links
+* Hiding the View Differences button when a wiki page's history only has one version
+* Messages on a Board can now be sorted by the number of replies
+* Adds a class ('me') to events of the activity view created by current user
+* Strip pre/code tags content from activity view events
+* Display issue notes in the activity view
+* Adds links to changesets atom feed on repository browser
+* Track project and tracker changes in issue history
+* Adds anchor to atom feed messages links
+* Adds a key in lang files to set the decimal separator (point or comma) in csv exports
+* Makes importer work with Trac 0.8.x
+* Upgraded to Prototype 1.6.0.1
+* File viewer for attached text files
+* Menu mapper: add support for :before, :after and :last options to #push method and add #delete method
+* Removed inconsistent revision numbers on diff view
+* CVS: add support for modules names with spaces
+* Log the user in after registration if account activation is not needed
+* Mercurial adapter improvements
+* Trac importer: read session_attribute table to find user's email and real name
+* Ability to disable unused SCM adapters in application settings
+* Adds Filesystem adapter
+* Clear changesets and changes with raw sql when deleting a repository for performance
+* Redmine.pm now uses the 'commit access' permission defined in Redmine
+* Reposman can create any type of scm (--scm option)
+* Reposman creates a repository if the 'repository' module is enabled at project level only
+* Display svn properties in the browser, svn >= 1.5.0 only
+* Reduces memory usage when importing large git repositories
+* Wider SVG graphs in repository stats
+* SubversionAdapter#entries performance improvement
+* SCM browser: ability to download raw unified diffs
+* More detailed error message in log when scm command fails
+* Adds support for file viewing with Darcs 2.0+
+* Check that git changeset is not in the database before creating it
+* Unified diff viewer for attached files with .patch or .diff extension
+* File size display with Bazaar repositories
+* Git adapter: use commit time instead of author time
+* Prettier url for changesets
+* Makes changes link to entries on the revision view
+* Adds a field on the repository view to browse at specific revision
+* Adds new projects atom feed
+* Added rake tasks to generate rcov code coverage reports
+* Add Redcloth's :block_markdown_rule to allow horizontal rules in wiki
+* Show the project hierarchy in the drop down list for new membership on user administration screen
+* Split user edit screen into tabs
+* Renames bundled RedCloth to RedCloth3 to avoid RedCloth 4 to be loaded instead
+* Fixed: Roadmap crashes when a version has a due date > 2037
+* Fixed: invalid effective date (eg. 99999-01-01) causes an error on version edition screen
+* Fixed: login filter providing incorrect back_url for Redmine installed in sub-directory
+* Fixed: logtime entry duplicated when edited from parent project
+* Fixed: wrong digest for text files under Windows
+* Fixed: associated revisions are displayed in wrong order on issue view
+* Fixed: Git Adapter date parsing ignores timezone
+* Fixed: Printing long roadmap doesn't split across pages
+* Fixes custom fields display order at several places
+* Fixed: urls containing @ are parsed as email adress by the wiki formatter
+* Fixed date filters accuracy with SQLite
+* Fixed: tokens not escaped in highlight_tokens regexp
+* Fixed Bazaar shared repository browsing
+* Fixes platform determination under JRuby
+* Fixed: Estimated time in issue's journal should be rounded to two decimals
+* Fixed: 'search titles only' box ignored after one search is done on titles only
+* Fixed: non-ASCII subversion path can't be displayed
+* Fixed: Inline images don't work if file name has upper case letters or if image is in BMP format
+* Fixed: document listing shows on "my page" when viewing documents is disabled for the role
+* Fixed: Latest news appear on the homepage for projects with the News module disabled
+* Fixed: cross-project issue list should not show issues of projects for which the issue tracking module was disabled
+* Fixed: the default status is lost when reordering issue statuses
+* Fixes error with Postgresql and non-UTF8 commit logs
+* Fixed: textile footnotes no longer work
+* Fixed: http links containing parentheses fail to reder correctly
+* Fixed: GitAdapter#get_rev should use current branch instead of hardwiring master
+
+
+== 2008-07-06 v0.7.3
+
+* Allow dot in firstnames and lastnames
+* Add project name to cross-project Atom feeds
+* Encoding set to utf8 in example database.yml
+* HTML titles on forums related views
+* Fixed: various XSS vulnerabilities
+* Fixed: Entourage (and some old client) fails to correctly render notification styles
+* Fixed: Fixed: timelog redirects inappropriately when :back_url is blank
+* Fixed: wrong relative paths to images in wiki_syntax.html
+
+
+== 2008-06-15 v0.7.2
+
+* "New Project" link on Projects page
+* Links to repository directories on the repo browser
+* Move status to front in Activity View
+* Remove edit step from Status context menu
+* Fixed: No way to do textile horizontal rule
+* Fixed: Repository: View differences doesn't work
+* Fixed: attachement's name maybe invalid.
+* Fixed: Error when creating a new issue
+* Fixed: NoMethodError on @available_filters.has_key?
+* Fixed: Check All / Uncheck All in Email Settings
+* Fixed: "View differences" of one file at /repositories/revision/ fails
+* Fixed: Column width in "my page"
+* Fixed: private subprojects are listed on Issues view
+* Fixed: Textile: bold, italics, underline, etc... not working after parentheses
+* Fixed: Update issue form: comment field from log time end out of screen
+* Fixed: Editing role: "issue can be assigned to this role" out of box
+* Fixed: Unable use angular braces after include word
+* Fixed: Using '*' as keyword for repository referencing keywords doesn't work
+* Fixed: Subversion repository "View differences" on each file rise ERROR
+* Fixed: View differences for individual file of a changeset fails if the repository URL doesn't point to the repository root
+* Fixed: It is possible to lock out the last admin account
+* Fixed: Wikis are viewable for anonymous users on public projects, despite not granting access
+* Fixed: Issue number display clipped on 'my issues'
+* Fixed: Roadmap version list links not carrying state
+* Fixed: Log Time fieldset in IssueController#edit doesn't set default Activity as default
+* Fixed: git's "get_rev" API should use repo's current branch instead of hardwiring "master"
+* Fixed: browser's language subcodes ignored
+* Fixed: Error on project selection with numeric (only) identifier.
+* Fixed: Link to PDF doesn't work after creating new issue
+* Fixed: "Replies" should not be shown on forum threads that are locked
+* Fixed: SVN errors lead to svn username/password being displayed to end users (security issue)
+* Fixed: http links containing hashes don't display correct
+* Fixed: Allow ampersands in Enumeration names
+* Fixed: Atom link on saved query does not include query_id
+* Fixed: Logtime info lost when there's an error updating an issue
+* Fixed: TOC does not parse colorization markups
+* Fixed: CVS: add support for modules names with spaces
+* Fixed: Bad rendering on projects/add
+* Fixed: exception when viewing differences on cvs
+* Fixed: export issue to pdf will messup when use Chinese language
+* Fixed: Redmine::Scm::Adapters::GitAdapter#get_rev ignored GIT_BIN constant
+* Fixed: Adding non-ASCII new issue type in the New Issue page have encoding error using IE
+* Fixed: Importing from trac : some wiki links are messed
+* Fixed: Incorrect weekend definition in Hebrew calendar locale
+* Fixed: Atom feeds don't provide author section for repository revisions
+* Fixed: In Activity views, changesets titles can be multiline while they should not
+* Fixed: Ignore unreadable subversion directories (read disabled using authz)
+* Fixed: lib/SVG/Graph/Graph.rb can't externalize stylesheets
+* Fixed: Close statement handler in Redmine.pm
+
+
+== 2008-05-04 v0.7.1
+
+* Thai translation added (Gampol Thitinilnithi)
+* Translations updates
+* Escape HTML comment tags
+* Prevent "can't convert nil into String" error when :sort_order param is not present
+* Fixed: Updating tickets add a time log with zero hours
+* Fixed: private subprojects names are revealed on the project overview
+* Fixed: Search for target version of "none" fails with postgres 8.3
+* Fixed: Home, Logout, Login links shouldn't be absolute links
+* Fixed: 'Latest projects' box on the welcome screen should be hidden if there are no projects
+* Fixed: error when using upcase language name in coderay
+* Fixed: error on Trac import when :due attribute is nil
+
+
+== 2008-04-28 v0.7.0
+
+* Forces Redmine to use rails 2.0.2 gem when vendor/rails is not present
+* Queries can be marked as 'For all projects'. Such queries will be available on all projects and on the global issue list.
+* Add predefined date ranges to the time report
+* Time report can be done at issue level
+* Various timelog report enhancements
+* Accept the following formats for "hours" field: 1h, 1 h, 1 hour, 2 hours, 30m, 30min, 1h30, 1h30m, 1:30
+* Display the context menu above and/or to the left of the click if needed
+* Make the admin project files list sortable
+* Mercurial: display working directory files sizes unless browsing a specific revision
+* Preserve status filter and page number when using lock/unlock/activate links on the users list
+* Redmine.pm support for LDAP authentication
+* Better error message and AR errors in log for failed LDAP on-the-fly user creation
+* Redirected user to where he is coming from after logging hours
+* Warn user that subprojects are also deleted when deleting a project
+* Include subprojects versions on calendar and gantt
+* Notify project members when a message is posted if they want to receive notifications
+* Fixed: Feed content limit setting has no effect
+* Fixed: Priorities not ordered when displayed as a filter in issue list
+* Fixed: can not display attached images inline in message replies
+* Fixed: Boards are not deleted when project is deleted
+* Fixed: trying to preview a new issue raises an exception with postgresql
+* Fixed: single file 'View difference' links do not work because of duplicate slashes in url
+* Fixed: inline image not displayed when including a wiki page
+* Fixed: CVS duplicate key violation
+* Fixed: ActiveRecord::StaleObjectError exception on closing a set of circular duplicate issues
+* Fixed: custom field filters behaviour
+* Fixed: Postgresql 8.3 compatibility
+* Fixed: Links to repository directories don't work
+
+
+== 2008-03-29 v0.7.0-rc1
+
+* Overall activity view and feed added, link is available on the project list
+* Git VCS support
+* Rails 2.0 sessions cookie store compatibility
+* Use project identifiers in urls instead of ids
+* Default configuration data can now be loaded from the administration screen
+* Administration settings screen split to tabs (email notifications options moved to 'Settings')
+* Project description is now unlimited and optional
+* Wiki annotate view
+* Escape HTML tag in textile content
+* Add Redmine links to documents, versions, attachments and repository files
+* New setting to specify how many objects should be displayed on paginated lists. There are 2 ways to select a set of issues on the issue list:
+    * by using checkbox and/or the little pencil that will select/unselect all issues
+    * by clicking on the rows (but not on the links), Ctrl and Shift keys can be used to select multiple issues
+* Context menu disabled on links so that the default context menu of the browser is displayed when right-clicking on a link (click anywhere else on the row to display the context menu)
+* User display format is now configurable in administration settings
+* Issue list now supports bulk edit/move/delete (for a set of issues that belong to the same project)
+* Merged 'change status', 'edit issue' and 'add note' actions:
+    * Users with 'edit issues' permission can now update any property including custom fields when adding a note or changing the status
+    * 'Change issue status' permission removed. To change an issue status, a user just needs to have either 'Edit' or 'Add note' permissions and some workflow transitions allowed
+* Details by assignees on issue summary view
+* 'New issue' link in the main menu (accesskey 7). The drop-down lists to add an issue on the project overview and the issue list are removed
+* Change status select box default to current status
+* Preview for issue notes, news and messages
+* Optional description for attachments
+* 'Fixed version' label changed to 'Target version'
+* Let the user choose when deleting issues with reported hours to:
+    * delete the hours
+    * assign the hours to the project
+    * reassign the hours to another issue
+* Date range filter and pagination on time entries detail view
+* Propagate time tracking to the parent project
+* Switch added on the project activity view to include subprojects
+* Display total estimated and spent hours on the version detail view
+* Weekly time tracking block for 'My page'
+* Permissions to edit time entries
+* Include subprojects on the issue list, calendar, gantt and timelog by default (can be turned off is administration settings)
+* Roadmap enhancements (separate related issues from wiki contents, leading h1 in version wiki pages is hidden, smaller wiki headings)
+* Make versions with same date sorted by name
+* Allow issue list to be sorted by target version
+* Related changesets messages displayed on the issue details view
+* Create a journal and send an email when an issue is closed by commit
+* Add 'Author' to the available columns for the issue list
+* More appropriate default sort order on sortable columns
+* Add issue subject to the time entries view and issue subject, description and tracker to the csv export
+* Permissions to edit issue notes
+* Display date/time instead of date on files list
+* Do not show Roadmap menu item if the project doesn't define any versions
+* Allow longer version names (60 chars)
+* Ability to copy an existing workflow when creating a new role
+* Display custom fields in two columns on the issue form
+* Added 'estimated time' in the csv export of the issue list
+* Display the last 30 days on the activity view rather than the current month (number of days can be configured in the application settings)
+* Setting for whether new projects should be public by default
+* User preference to choose how comments/replies are displayed: in chronological or reverse chronological order
+* Added default value for custom fields
+* Added tabindex property on wiki toolbar buttons (to easily move from field to field using the tab key)
+* Redirect to issue page after creating a new issue
+* Wiki toolbar improvements (mainly for Firefox)
+* Display wiki syntax quick ref link on all wiki textareas
+* Display links to Atom feeds
+* Breadcrumb nav for the forums
+* Show replies when choosing to display messages in the activity
+* Added 'include' macro to include another wiki page
+* RedmineWikiFormatting page available as a static HTML file locally
+* Wrap diff content
+* Strip out email address from authors in repository screens
+* Highlight the current item of the main menu
+* Added simple syntax highlighters for php and java languages
+* Do not show empty diffs
+* Show explicit error message when the scm command failed (eg. when svn binary is not available)
+* Lithuanian translation added (Sergej Jegorov)
+* Ukrainan translation added (Natalia Konovka & Mykhaylo Sorochan)
+* Danish translation added (Mads Vestergaard)
+* Added i18n support to the jstoolbar and various settings screen
+* RedCloth's glyphs no longer user
+* New icons for the wiki toolbar (from http://www.famfamfam.com/lab/icons/silk/)
+* The following menus can now be extended by plugins: top_menu, account_menu, application_menu
+* Added a simple rake task to fetch changesets from the repositories: rake redmine:fetch_changesets
+* Remove hardcoded "Redmine" strings in account related emails and use application title instead
+* Mantis importer preserve bug ids
+* Trac importer: Trac guide wiki pages skipped
+* Trac importer: wiki attachments migration added
+* Trac importer: support database schema for Trac migration
+* Trac importer: support CamelCase links
+* Removes the Redmine version from the footer (can be viewed on admin -> info)
+* Rescue and display an error message when trying to delete a role that is in use
+* Add various 'X-Redmine' headers to email notifications: X-Redmine-Host, X-Redmine-Site, X-Redmine-Project, X-Redmine-Issue-Id, -Author, -Assignee, X-Redmine-Topic-Id
+* Add "--encoding utf8" option to the Mercurial "hg log" command in order to get utf8 encoded commit logs
+* Fixed: Gantt and calendar not properly refreshed (fragment caching removed)
+* Fixed: Textile image with style attribute cause internal server error
+* Fixed: wiki TOC not rendered properly when used in an issue or document description
+* Fixed: 'has already been taken' error message on username and email fields if left empty
+* Fixed: non-ascii attachement filename with IE
+* Fixed: wrong url for wiki syntax pop-up when Redmine urls are prefixed
+* Fixed: search for all words doesn't work
+* Fixed: Do not show sticky and locked checkboxes when replying to a message
+* Fixed: Mantis importer: do not duplicate Mantis username in firstname and lastname if realname is blank
+* Fixed: Date custom fields not displayed as specified in application settings
+* Fixed: titles not escaped in the activity view
+* Fixed: issue queries can not use custom fields marked as 'for all projects' in a project context
+* Fixed: on calendar, gantt and in the tracker filter on the issue list, only active trackers of the project (and its sub projects) should be available
+* Fixed: locked users should not receive email notifications
+* Fixed: custom field selection is not saved when unchecking them all on project settings
+* Fixed: can not lock a topic when creating it
+* Fixed: Incorrect filtering for unset values when using 'is not' filter
+* Fixed: PostgreSQL issues_seq_id not updated when using Trac importer
+* Fixed: ajax pagination does not scroll up
+* Fixed: error when uploading a file with no content-type specified by the browser
+* Fixed: wiki and changeset links not displayed when previewing issue description or notes
+* Fixed: 'LdapError: no bind result' error when authenticating
+* Fixed: 'LdapError: invalid binding information' when no username/password are set on the LDAP account
+* Fixed: CVS repository doesn't work if port is used in the url
+* Fixed: Email notifications: host name is missing in generated links
+* Fixed: Email notifications: referenced changesets, wiki pages, attachments... are not turned into links
+* Fixed: Do not clear issue relations when moving an issue to another project if cross-project issue relations are allowed
+* Fixed: "undefined method 'textilizable'" error on email notification when running Repository#fetch_changesets from the console
+* Fixed: Do not send an email with no recipient, cc or bcc
+* Fixed: fetch_changesets fails on commit comments that close 2 duplicates issues.
+* Fixed: Mercurial browsing under unix-like os and for directory depth > 2
+* Fixed: Wiki links with pipe can not be used in wiki tables
+* Fixed: migrate_from_trac doesn't import timestamps of wiki and tickets
+* Fixed: when bulk editing, setting "Assigned to" to "nobody" causes an sql error with Postgresql
+
+
+== 2008-03-12 v0.6.4
+
+* Fixed: private projects name are displayed on account/show even if the current user doesn't have access to these private projects
+* Fixed: potential LDAP authentication security flaw
+* Fixed: context submenus on the issue list don't show up with IE6.
+* Fixed: Themes are not applied with Rails 2.0
+* Fixed: crash when fetching Mercurial changesets if changeset[:files] is nil
+* Fixed: Mercurial repository browsing
+* Fixed: undefined local variable or method 'log' in CvsAdapter when a cvs command fails
+* Fixed: not null constraints not removed with Postgresql
+* Doctype set to transitional
+
+
+== 2007-12-18 v0.6.3
+
+* Fixed: upload doesn't work in 'Files' section
+
+
+== 2007-12-16 v0.6.2
+
+* Search engine: issue custom fields can now be searched
+* News comments are now textilized
+* Updated Japanese translation (Satoru Kurashiki)
+* Updated Chinese translation (Shortie Lo)
+* Fixed Rails 2.0 compatibility bugs:
+  * Unable to create a wiki
+  * Gantt and calendar error
+  * Trac importer error (readonly? is defined by ActiveRecord)
+* Fixed: 'assigned to me' filter broken
+* Fixed: crash when validation fails on issue edition with no custom fields
+* Fixed: reposman "can't find group" error
+* Fixed: 'LDAP account password is too long' error when leaving the field empty on creation
+* Fixed: empty lines when displaying repository files with Windows style eol
+* Fixed: missing body closing tag in repository annotate and entry views
+
+
+== 2007-12-10 v0.6.1
+
+* Rails 2.0 compatibility
+* Custom fields can now be displayed as columns on the issue list
+* Added version details view (accessible from the roadmap)
+* Roadmap: more accurate completion percentage calculation (done ratio of open issues is now taken into account)
+* Added per-project tracker selection. Trackers can be selected on project settings
+* Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums
+* Forums: messages can now be edited/deleted (explicit permissions need to be given)
+* Forums: topics can be locked so that no reply can be added
+* Forums: topics can be marked as sticky so that they always appear at the top of the list
+* Forums: attachments can now be added to replies
+* Added time zone support
+* Added a setting to choose the account activation strategy (available in application settings)
+* Added 'Classic' theme (inspired from the v0.51 design)
+* Added an alternate theme which provides issue list colorization based on issues priority
+* Added Bazaar SCM adapter
+* Added Annotate/Blame view in the repository browser (except for Darcs SCM)
+* Diff style (inline or side by side) automatically saved as a user preference
+* Added issues status changes on the activity view (by Cyril Mougel)
+* Added forums topics on the activity view (disabled by default)
+* Added an option on 'My account' for users who don't want to be notified of changes that they make
+* Trac importer now supports mysql and postgresql databases
+* Trac importer improvements (by Mat Trudel)
+* 'fixed version' field can now be displayed on the issue list
+* Added a couple of new formats for the 'date format' setting
+* Added Traditional Chinese translation (by Shortie Lo)
+* Added Russian translation (iGor kMeta)
+* Project name format limitation removed (name can now contain any character)
+* Project identifier maximum length changed from 12 to 20
+* Changed the maximum length of LDAP account to 255 characters
+* Removed the 12 characters limit on passwords
+* Added wiki macros support
+* Performance improvement on workflow setup screen
+* More detailed html title on several views
+* Custom fields can now be reordered
+* Search engine: search can be restricted to an exact phrase by using quotation marks
+* Added custom fields marked as 'For all projects' to the csv export of the cross project issue list
+* Email notifications are now sent as Blind carbon copy by default
+* Fixed: all members (including non active) should be deleted when deleting a project
+* Fixed: Error on wiki syntax link (accessible from wiki/edit)
+* Fixed: 'quick jump to a revision' form on the revisions list
+* Fixed: error on admin/info if there's more than 1 plugin installed
+* Fixed: svn or ldap password can be found in clear text in the html source in editing mode
+* Fixed: 'Assigned to' drop down list is not sorted
+* Fixed: 'View all issues' link doesn't work on issues/show
+* Fixed: error on account/register when validation fails
+* Fixed: Error when displaying the issue list if a float custom field is marked as 'used as filter'
+* Fixed: Mercurial adapter breaks on missing :files entry in changeset hash (James Britt)
+* Fixed: Wrong feed URLs on the home page
+* Fixed: Update of time entry fails when the issue has been moved to an other project
+* Fixed: Error when moving an issue without changing its tracker (Postgresql)
+* Fixed: Changes not recorded when using :pserver string (CVS adapter)
+* Fixed: admin should be able to move issues to any project
+* Fixed: adding an attachment is not possible when changing the status of an issue
+* Fixed: No mime-types in documents/files downloading
+* Fixed: error when sorting the messages if there's only one board for the project
+* Fixed: 'me' doesn't appear in the drop down filters on a project issue list.
+
+== 2007-11-04 v0.6.0
+
+* Permission model refactoring.
+* Permissions: there are now 2 builtin roles that can be used to specify permissions given to other users than members of projects
+* Permissions: some permissions (eg. browse the repository) can be removed for certain roles
+* Permissions: modules (eg. issue tracking, news, documents...) can be enabled/disabled at project level
+* Added Mantis and Trac importers
+* New application layout
+* Added "Bulk edit" functionality on the issue list
+* More flexible mail notifications settings at user level
+* Added AJAX based context menu on the project issue list that provide shortcuts for editing, re-assigning, changing the status or the priority, moving or deleting an issue
+* Added the hability to copy an issue. It can be done from the "issue/show" view or from the context menu on the issue list
+* Added the ability to customize issue list columns (at application level or for each saved query)
+* Overdue versions (date reached and open issues > 0) are now always displayed on the roadmap
+* Added the ability to rename wiki pages (specific permission required)
+* Search engines now supports pagination. Results are sorted in reverse chronological order
+* Added "Estimated hours" attribute on issues
+* A category with assigned issue can now be deleted. 2 options are proposed: remove assignments or reassign issues to another category
+* Forum notifications are now also sent to the authors of the thread, even if they don�t watch the board
+* Added an application setting to specify the application protocol (http or https) used to generate urls in emails
+* Gantt chart: now starts at the current month by default
+* Gantt chart: month count and zoom factor are automatically saved as user preferences
+* Wiki links can now refer to other project wikis
+* Added wiki index by date
+* Added preview on add/edit issue form
+* Emails footer can now be customized from the admin interface (Admin -> Email notifications)
+* Default encodings for repository files can now be set in application settings (used to convert files content and diff to UTF-8 so that they�re properly displayed)
+* Calendar: first day of week can now be set in lang files
+* Automatic closing of duplicate issues
+* Added a cross-project issue list
+* AJAXified the SCM browser (tree view)
+* Pretty URL for the repository browser (Cyril Mougel)
+* Search engine: added a checkbox to search titles only
+* Added "% done" in the filter list
+* Enumerations: values can now be reordered and a default value can be specified (eg. default issue priority)
+* Added some accesskeys
+* Added "Float" as a custom field format
+* Added basic Theme support
+* Added the ability to set the �done ratio� of issues fixed by commit (Nikolay Solakov)
+* Added custom fields in issue related mail notifications
+* Email notifications are now sent in plain text and html
+* Gantt chart can now be exported to a graphic file (png). This functionality is only available if RMagick is installed.
+* Added syntax highlightment for repository files and wiki
+* Improved automatic Redmine links
+* Added automatic table of content support on wiki pages
+* Added radio buttons on the documents list to sort documents by category, date, title or author
+* Added basic plugin support, with a sample plugin
+* Added a link to add a new category when creating or editing an issue
+* Added a "Assignable" boolean on the Role model. If unchecked, issues can not be assigned to users having this role.
+* Added an option to be able to relate issues in different projects
+* Added the ability to move issues (to another project) without changing their trackers.
+* Atom feeds added on project activity, news and changesets
+* Added the ability to reset its own RSS access key
+* Main project list now displays root projects with their subprojects
+* Added anchor links to issue notes
+* Added reposman Ruby version. This script can now register created repositories in Redmine (Nicolas Chuche)
+* Issue notes are now included in search
+* Added email sending test functionality
+* Added LDAPS support for LDAP authentication
+* Removed hard-coded URLs in mail templates
+* Subprojects are now grouped by projects in the navigation drop-down menu
+* Added a new value for date filters: this week
+* Added cache for application settings
+* Added Polish translation (Tomasz Gawryl)
+* Added Czech translation (Jan Kadlecek)
+* Added Romanian translation (Csongor Bartus)
+* Added Hebrew translation (Bob Builder)
+* Added Serbian translation (Dragan Matic)
+* Added Korean translation (Choi Jong Yoon)
+* Fixed: the link to delete issue relations is displayed even if the user is not authorized to delete relations
+* Performance improvement on calendar and gantt
+* Fixed: wiki preview doesn�t work on long entries
+* Fixed: queries with multiple custom fields return no result
+* Fixed: Can not authenticate user against LDAP if its DN contains non-ascii characters
+* Fixed: URL with ~ broken in wiki formatting
+* Fixed: some quotation marks are rendered as strange characters in pdf
+
+
+== 2007-07-15 v0.5.1
+
+* per project forums added
+* added the ability to archive projects
+* added �Watch� functionality on issues. It allows users to receive notifications about issue changes
+* custom fields for issues can now be used as filters on issue list
+* added per user custom queries
+* commit messages are now scanned for referenced or fixed issue IDs (keywords defined in Admin -> Settings)
+* projects list now shows the list of public projects and private projects for which the user is a member
+* versions can now be created with no date
+* added issue count details for versions on Reports view
+* added time report, by member/activity/tracker/version and year/month/week for the selected period
+* each category can now be associated to a user, so that new issues in that category are automatically assigned to that user
+* added autologin feature (disabled by default)
+* optimistic locking added for wiki edits
+* added wiki diff
+* added the ability to destroy wiki pages (requires permission)
+* a wiki page can now be attached to each version, and displayed on the roadmap
+* attachments can now be added to wiki pages (original patch by Pavol Murin) and displayed online
+* added an option to see all versions in the roadmap view (including completed ones)
+* added basic issue relations
+* added the ability to log time when changing an issue status
+* account information can now be sent to the user when creating an account
+* author and assignee of an issue always receive notifications (even if they turned of mail notifications)
+* added a quick search form in page header
+* added 'me' value for 'assigned to' and 'author' query filters
+* added a link on revision screen to see the entire diff for the revision
+* added last commit message for each entry in repository browser
+* added the ability to view a file diff with free to/from revision selection.
+* text files can now be viewed online when browsing the repository
+* added basic support for other SCM: CVS (Ralph Vater), Mercurial and Darcs
+* added fragment caching for svn diffs
+* added fragment caching for calendar and gantt views
+* login field automatically focused on login form
+* subproject name displayed on issue list, calendar and gantt
+* added an option to choose the date format: language based or ISO 8601
+* added a simple mail handler. It lets users add notes to an existing issue by replying to the initial notification email.
+* a 403 error page is now displayed (instead of a blank page) when trying to access a protected page
+* added portuguese translation (Joao Carlos Clementoni)
+* added partial online help japanese translation (Ken Date)
+* added bulgarian translation (Nikolay Solakov)
+* added dutch translation (Linda van den Brink)
+* added swedish translation (Thomas Habets)
+* italian translation update (Alessio Spadaro)
+* japanese translation update (Satoru Kurashiki)
+* fixed: error on history atom feed when there�s no notes on an issue change
+* fixed: error in journalizing an issue with longtext custom fields (Postgresql)
+* fixed: creation of Oracle schema
+* fixed: last day of the month not included in project activity
+* fixed: files with an apostrophe in their names can't be accessed in SVN repository
+* fixed: performance issue on RepositoriesController#revisions when a changeset has a great number of changes (eg. 100,000)
+* fixed: open/closed issue counts are always 0 on reports view (postgresql)
+* fixed: date query filters (wrong results and sql error with postgresql)
+* fixed: confidentiality issue on account/show (private project names displayed to anyone)
+* fixed: Long text custom fields displayed without line breaks
+* fixed: Error when editing the wokflow after deleting a status
+* fixed: SVN commit dates are now stored as local time
+
+
+== 2007-04-11 v0.5.0
+
+* added per project Wiki
+* added rss/atom feeds at project level (custom queries can be used as feeds)
+* added search engine (search in issues, news, commits, wiki pages, documents)
+* simple time tracking functionality added
+* added version due dates on calendar and gantt
+* added subprojects issue count on project Reports page
+* added the ability to copy an existing workflow when creating a new tracker
+* added the ability to include subprojects on calendar and gantt
+* added the ability to select trackers to display on calendar and gantt (Jeffrey Jones)
+* added side by side svn diff view (Cyril Mougel)
+* added back subproject filter on issue list
+* added permissions report in admin area
+* added a status filter on users list
+* support for password-protected SVN repositories
+* SVN commits are now stored in the database
+* added simple svn statistics SVG graphs
+* progress bars for roadmap versions (Nick Read)
+* issue history now shows file uploads and deletions
+* #id patterns are turned into links to issues in descriptions and commit messages
+* japanese translation added (Satoru Kurashiki)
+* chinese simplified translation added (Andy Wu)
+* italian translation added (Alessio Spadaro)
+* added scripts to manage SVN repositories creation and user access control using ssh+svn (Nicolas Chuche)
+* better calendar rendering time
+* fixed migration scripts to work with mysql 5 running in strict mode
+* fixed: error when clicking "add" with no block selected on my/page_layout
+* fixed: hard coded links in navigation bar
+* fixed: table_name pre/suffix support
+
+
+== 2007-02-18 v0.4.2
+
+* Rails 1.2 is now required
+* settings are now stored in the database and editable through the application in: Admin -> Settings (config_custom.rb is no longer used)
+* added project roadmap view
+* mail notifications added when a document, a file or an attachment is added
+* tooltips added on Gantt chart and calender to view the details of the issues
+* ability to set the sort order for roles, trackers, issue statuses
+* added missing fields to csv export: priority, start date, due date, done ratio
+* added total number of issues per tracker on project overview
+* all icons replaced (new icons are based on GPL icon set: "KDE Crystal Diamond 2.5" -by paolino- and "kNeu! Alpha v0.1" -by Pablo Fabregat-)
+* added back "fixed version" field on issue screen and in filters
+* project settings screen split in 4 tabs
+* custom fields screen split in 3 tabs (one for each kind of custom field)
+* multiple issues pdf export now rendered as a table
+* added a button on users/list to manually activate an account
+* added a setting option to disable "password lost" functionality
+* added a setting option to set max number of issues in csv/pdf exports
+* fixed: subprojects count is always 0 on projects list
+* fixed: locked users are proposed when adding a member to a project
+* fixed: setting an issue status as default status leads to an sql error with SQLite
+* fixed: unable to delete an issue status even if it's not used yet
+* fixed: filters ignored when exporting a predefined query to csv/pdf
+* fixed: crash when french "issue_edit" email notification is sent
+* fixed: hide mail preference not saved (my/account)
+* fixed: crash when a new user try to edit its "my page" layout
+
+
+== 2007-01-03 v0.4.1
+
+* fixed: emails have no recipient when one of the project members has notifications disabled
+
+
+== 2007-01-02 v0.4.0
+
+* simple SVN browser added (just needs svn binaries in PATH)
+* comments can now be added on news
+* "my page" is now customizable 
+* more powerfull and savable filters for issues lists
+* improved issues change history
+* new functionality: move an issue to another project or tracker
+* new functionality: add a note to an issue
+* new report: project activity
+* "start date" and "% done" fields added on issues
+* project calendar added
+* gantt chart added (exportable to pdf)
+* single/multiple issues pdf export added
+* issues reports improvements
+* multiple file upload for issues, documents and files
+* option to set maximum size of uploaded files
+* textile formating of issue and news descritions (RedCloth required)
+* integration of DotClear jstoolbar for textile formatting
+* calendar date picker for date fields (LGPL DHTML Calendar http://sourceforge.net/projects/jscalendar)
+* new filter in issues list: Author
+* ajaxified paginators
+* news rss feed added
+* option to set number of results per page on issues list
+* localized csv separator (comma/semicolon)
+* csv output encoded to ISO-8859-1
+* user custom field displayed on account/show
+* default configuration improved (default roles, trackers, status, permissions and workflows)
+* language for default configuration data can now be chosen when running 'load_default_data' task
+* javascript added on custom field form to show/hide fields according to the format of custom field
+* fixed: custom fields not in csv exports
+* fixed: project settings now displayed according to user's permissions
+* fixed: application error when no version is selected on projects/add_file
+* fixed: public actions not authorized for members of non public projects
+* fixed: non public projects were shown on welcome screen even if current user is not a member
+
+
+== 2006-10-08 v0.3.0
+
+* user authentication against multiple LDAP (optional)
+* token based "lost password" functionality
+* user self-registration functionality (optional)
+* custom fields now available for issues, users and projects
+* new custom field format "text" (displayed as a textarea field) 
+* project & administration drop down menus in navigation bar for quicker access
+* text formatting is preserved for long text fields (issues, projects and news descriptions)
+* urls and emails are turned into clickable links in long text fields
+* "due date" field added on issues
+* tracker selection filter added on change log
+* Localization plugin replaced with GLoc 1.1.0 (iconv required)
+* error messages internationalization
+* german translation added (thanks to Karim Trott)
+* data locking for issues to prevent update conflicts (using ActiveRecord builtin optimistic locking)
+* new filter in issues list: "Fixed version"
+* active filters are displayed with colored background on issues list
+* custom configuration is now defined in config/config_custom.rb
+* user object no more stored in session (only user_id)
+* news summary field is no longer required
+* tables and forms redesign
+* Fixed: boolean custom field not working
+* Fixed: error messages for custom fields are not displayed
+* Fixed: invalid custom fields should have a red border
+* Fixed: custom fields values are not validated on issue update
+* Fixed: unable to choose an empty value for 'List' custom fields
+* Fixed: no issue categories sorting
+* Fixed: incorrect versions sorting
+
+
+== 2006-07-12 - v0.2.2
+
+* Fixed: bug in "issues list"
+
+
+== 2006-07-09 - v0.2.1
+
+* new databases supported: Oracle, PostgreSQL, SQL Server
+* projects/subprojects hierarchy (1 level of subprojects only)
+* environment information display in admin/info
+* more filter options in issues list (rev6)
+* default language based on browser settings (Accept-Language HTTP header)
+* issues list exportable to CSV (rev6)
+* simple_format and auto_link on long text fields
+* more data validations
+* Fixed: error when all mail notifications are unchecked in admin/mail_options
+* Fixed: all project news are displayed on project summary
+* Fixed: Can't change user password in users/edit
+* Fixed: Error on tables creation with PostgreSQL (rev5)
+* Fixed: SQL error in "issue reports" view with PostgreSQL (rev5)
+
+
+== 2006-06-25 - v0.1.0
+
+* multiple users/multiple projects
+* role based access control
+* issue tracking system
+* fully customizable workflow
+* documents/files repository
+* email notifications on issue creation and update
+* multilanguage support (except for error messages):english, french, spanish
+* online manual in french (unfinished)
--- a/.svn/pristine/d1/d16034fcce26ab77343a09774e57112c6aad2670.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::MembershipsTest < Redmine::ApiTest::Base
-  fixtures :projects, :users, :roles, :members, :member_roles
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /projects/:project_id/memberships.xml should return memberships" do
-    get '/projects/1/memberships.xml', {}, credentials('jsmith')
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'memberships',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'membership',
-        :child => {
-          :tag => 'id',
-          :content => '2',
-          :sibling => {
-            :tag => 'user',
-            :attributes => {:id => '3', :name => 'Dave Lopper'},
-            :sibling => {
-              :tag => 'roles',
-              :child => {
-                :tag => 'role',
-                :attributes => {:id => '2', :name => 'Developer'}
-              }
-            }
-          }
-        }
-      }
-  end
-
-  test "GET /projects/:project_id/memberships.json should return memberships" do
-    get '/projects/1/memberships.json', {}, credentials('jsmith')
-
-    assert_response :success
-    assert_equal 'application/json', @response.content_type
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_equal({
-      "memberships" =>
-        [{"id"=>1,
-          "project" => {"name"=>"eCookbook", "id"=>1},
-          "roles" => [{"name"=>"Manager", "id"=>1}],
-          "user" => {"name"=>"John Smith", "id"=>2}},
-         {"id"=>2,
-          "project" => {"name"=>"eCookbook", "id"=>1},
-          "roles" => [{"name"=>"Developer", "id"=>2}],
-          "user" => {"name"=>"Dave Lopper", "id"=>3}}],
-     "limit" => 25,
-     "total_count" => 2,
-     "offset" => 0},
-     json)
-  end
-
-  test "POST /projects/:project_id/memberships.xml should create the membership" do
-    assert_difference 'Member.count' do
-      post '/projects/1/memberships.xml', {:membership => {:user_id => 7, :role_ids => [2,3]}}, credentials('jsmith')
-
-      assert_response :created
-    end
-  end
-
-  test "POST /projects/:project_id/memberships.xml with invalid parameters should return errors" do
-    assert_no_difference 'Member.count' do
-      post '/projects/1/memberships.xml', {:membership => {:role_ids => [2,3]}}, credentials('jsmith')
-
-      assert_response :unprocessable_entity
-      assert_equal 'application/xml', @response.content_type
-      assert_tag 'errors', :child => {:tag => 'error', :content => "Principal can't be blank"}
-    end
-  end
-
-  test "GET /memberships/:id.xml should return the membership" do
-    get '/memberships/2.xml', {}, credentials('jsmith')
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'membership',
-      :child => {
-        :tag => 'id',
-        :content => '2',
-        :sibling => {
-          :tag => 'user',
-          :attributes => {:id => '3', :name => 'Dave Lopper'},
-          :sibling => {
-            :tag => 'roles',
-            :child => {
-              :tag => 'role',
-              :attributes => {:id => '2', :name => 'Developer'}
-            }
-          }
-        }
-      }
-  end
-
-  test "GET /memberships/:id.json should return the membership" do
-    get '/memberships/2.json', {}, credentials('jsmith')
-
-    assert_response :success
-    assert_equal 'application/json', @response.content_type
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_equal(
-      {"membership" => {
-        "id" => 2,
-        "project" => {"name"=>"eCookbook", "id"=>1},
-        "roles" => [{"name"=>"Developer", "id"=>2}],
-        "user" => {"name"=>"Dave Lopper", "id"=>3}}
-      },
-      json)
-  end
-
-  test "PUT /memberships/:id.xml should update the membership" do
-    assert_not_equal [1,2], Member.find(2).role_ids.sort
-    assert_no_difference 'Member.count' do
-      put '/memberships/2.xml', {:membership => {:user_id => 3, :role_ids => [1,2]}}, credentials('jsmith')
-
-      assert_response :ok
-      assert_equal '', @response.body
-    end
-    member = Member.find(2)
-    assert_equal [1,2], member.role_ids.sort
-  end
-
-  test "PUT /memberships/:id.xml with invalid parameters should return errors" do
-    put '/memberships/2.xml', {:membership => {:user_id => 3, :role_ids => [99]}}, credentials('jsmith')
-
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'errors', :child => {:tag => 'error', :content => /member_roles is invalid/}
-  end
-
-  test "DELETE /memberships/:id.xml should destroy the membership" do
-    assert_difference 'Member.count', -1 do
-      delete '/memberships/2.xml', {}, credentials('jsmith')
-
-      assert_response :ok
-      assert_equal '', @response.body
-    end
-    assert_nil Member.find_by_id(2)
-  end
-
-  test "DELETE /memberships/:id.xml should respond with 422 on failure" do
-    assert_no_difference 'Member.count' do
-      # A membership with an inherited role can't be deleted
-      Member.find(2).member_roles.first.update_attribute :inherited_from, 99
-      delete '/memberships/2.xml', {}, credentials('jsmith')
-
-      assert_response :unprocessable_entity
-    end
-  end
-end
--- a/.svn/pristine/d3/d33d3be542af530a2b59368ea55c980fec7e5ab9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,230 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-
-# DO NOT MODIFY THIS FILE !!!
-# Settings can be defined through the application in Admin -> Settings
-
-app_title:
-  default: Redmine
-app_subtitle:
-  default: Project management
-welcome_text:
-  default:
-login_required:
-  default: 0
-self_registration:
-  default: '2'
-lost_password:
-  default: 1
-unsubscribe:
-  default: 1
-password_min_length:
-  format: int
-  default: 8
-# Maximum lifetime of user sessions in minutes
-session_lifetime:
-  format: int
-  default: 0
-# User session timeout in minutes
-session_timeout:
-  format: int
-  default: 0
-attachment_max_size:
-  format: int
-  default: 5120
-issues_export_limit:
-  format: int
-  default: 500
-activity_days_default:
-  format: int
-  default: 30
-per_page_options:
-  default: '25,50,100'
-mail_from:
-  default: redmine@example.net
-bcc_recipients:
-  default: 1
-plain_text_mail:
-  default: 0
-text_formatting:
-  default: textile
-cache_formatted_text:
-  default: 0
-wiki_compression:
-  default: ""
-default_language:
-  default: en
-host_name:
-  default: localhost:3000
-protocol:
-  default: http
-feeds_limit:
-  format: int
-  default: 15
-gantt_items_limit:
-  format: int
-  default: 500
-# Maximum size of files that can be displayed
-# inline through the file viewer (in KB)
-file_max_size_displayed:
-  format: int
-  default: 512
-diff_max_lines_displayed:
-  format: int
-  default: 1500
-enabled_scm:
-  serialized: true
-  default:
-  - Subversion
-  - Darcs
-  - Mercurial
-  - Cvs
-  - Bazaar
-  - Git
-autofetch_changesets:
-  default: 1
-sys_api_enabled:
-  default: 0
-sys_api_key:
-  default: ''
-commit_cross_project_ref:
-  default: 0
-commit_ref_keywords:
-  default: 'refs,references,IssueID'
-commit_update_keywords:
-  serialized: true
-  default: []
-commit_logtime_enabled:
-  default: 0
-commit_logtime_activity_id:
-  format: int
-  default: 0
-# autologin duration in days
-# 0 means autologin is disabled
-autologin:
-  format: int
-  default: 0
-# date format
-date_format:
-  default: ''
-time_format:
-  default: ''
-user_format:
-  default: :firstname_lastname
-  format: symbol
-cross_project_issue_relations:
-  default: 0
-# Enables subtasks to be in other projects
-cross_project_subtasks:
-  default: 'tree'
-issue_group_assignment:
-  default: 0
-default_issue_start_date_to_creation_date:
-  default: 1
-notified_events:
-  serialized: true
-  default:
-  - issue_added
-  - issue_updated
-mail_handler_body_delimiters:
-  default: ''
-mail_handler_excluded_filenames:
-  default: ''
-mail_handler_api_enabled:
-  default: 0
-mail_handler_api_key:
-  default:
-issue_list_default_columns:
-  serialized: true
-  default:
-  - tracker
-  - status
-  - priority
-  - subject
-  - assigned_to
-  - updated_on
-display_subprojects_issues:
-  default: 1
-issue_done_ratio:
-  default: 'issue_field'
-default_projects_public:
-  default: 1
-default_projects_modules:
-  serialized: true
-  default:
-  - issue_tracking
-  - time_tracking
-  - news
-  - documents
-  - files
-  - wiki
-  - repository
-  - boards
-  - calendar
-  - gantt
-default_projects_tracker_ids:
-  serialized: true
-  default: 
-# Role given to a non-admin user who creates a project
-new_project_user_role_id:
-  format: int
-  default: ''
-sequential_project_identifiers:
-  default: 0
-# encodings used to convert repository files content to UTF-8
-# multiple values accepted, comma separated
-repositories_encodings:
-  default: ''
-# encoding used to convert commit logs to UTF-8
-commit_logs_encoding:
-  default: 'UTF-8'
-repository_log_display_limit:
-  format: int
-  default: 100
-ui_theme:
-  default: ''
-emails_footer:
-  default: |-
-    You have received this notification because you have either subscribed to it, or are involved in it.
-    To change your notification preferences, please click here: http://hostname/my/account
-gravatar_enabled:
-  default: 0
-openid:
-  default: 0
-gravatar_default:
-  default: ''
-start_of_week:
-  default: ''
-rest_api_enabled:
-  default: 0
-jsonp_enabled:
-  default: 0
-default_notification_option:
-  default: 'only_my_events'
-emails_header:
-  default: ''
-thumbnails_enabled:
-  default: 0
-thumbnails_size:
-  format: int
-  default: 100
-non_working_week_days:
-  serialized: true
-  default:
-  - '6'
-  - '7'
--- a/.svn/pristine/d3/d36525152d9efe5f33a9df496757a5193831f75b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Role < ActiveRecord::Base
-  # Custom coder for the permissions attribute that should be an
-  # array of symbols. Rails 3 uses Psych which can be *unbelievably*
-  # slow on some platforms (eg. mingw32).
-  class PermissionsAttributeCoder
-    def self.load(str)
-      str.to_s.scan(/:([a-z0-9_]+)/).flatten.map(&:to_sym)
-    end
-
-    def self.dump(value)
-      YAML.dump(value)
-    end
-  end
-
-  # Built-in roles
-  BUILTIN_NON_MEMBER = 1
-  BUILTIN_ANONYMOUS  = 2
-
-  ISSUES_VISIBILITY_OPTIONS = [
-    ['all', :label_issues_visibility_all],
-    ['default', :label_issues_visibility_public],
-    ['own', :label_issues_visibility_own]
-  ]
-
-  scope :sorted, lambda { order("#{table_name}.builtin ASC, #{table_name}.position ASC") }
-  scope :givable, lambda { order("#{table_name}.position ASC").where(:builtin => 0) }
-  scope :builtin, lambda { |*args|
-    compare = (args.first == true ? 'not' : '')
-    where("#{compare} builtin = 0")
-  }
-
-  before_destroy :check_deletable
-  has_many :workflow_rules, :dependent => :delete_all do
-    def copy(source_role)
-      WorkflowRule.copy(nil, source_role, nil, proxy_association.owner)
-    end
-  end
-  has_and_belongs_to_many :custom_fields, :join_table => "#{table_name_prefix}custom_fields_roles#{table_name_suffix}", :foreign_key => "role_id"
-
-  has_many :member_roles, :dependent => :destroy
-  has_many :members, :through => :member_roles
-  acts_as_list
-
-  serialize :permissions, ::Role::PermissionsAttributeCoder
-  attr_protected :builtin
-
-  validates_presence_of :name
-  validates_uniqueness_of :name
-  validates_length_of :name, :maximum => 30
-  validates_inclusion_of :issues_visibility,
-    :in => ISSUES_VISIBILITY_OPTIONS.collect(&:first),
-    :if => lambda {|role| role.respond_to?(:issues_visibility)}
-
-  # Copies attributes from another role, arg can be an id or a Role
-  def copy_from(arg, options={})
-    return unless arg.present?
-    role = arg.is_a?(Role) ? arg : Role.find_by_id(arg.to_s)
-    self.attributes = role.attributes.dup.except("id", "name", "position", "builtin", "permissions")
-    self.permissions = role.permissions.dup
-    self
-  end
-
-  def permissions=(perms)
-    perms = perms.collect {|p| p.to_sym unless p.blank? }.compact.uniq if perms
-    write_attribute(:permissions, perms)
-  end
-
-  def add_permission!(*perms)
-    self.permissions = [] unless permissions.is_a?(Array)
-
-    permissions_will_change!
-    perms.each do |p|
-      p = p.to_sym
-      permissions << p unless permissions.include?(p)
-    end
-    save!
-  end
-
-  def remove_permission!(*perms)
-    return unless permissions.is_a?(Array)
-    permissions_will_change!
-    perms.each { |p| permissions.delete(p.to_sym) }
-    save!
-  end
-
-  # Returns true if the role has the given permission
-  def has_permission?(perm)
-    !permissions.nil? && permissions.include?(perm.to_sym)
-  end
-
-  def <=>(role)
-    if role
-      if builtin == role.builtin
-        position <=> role.position
-      else
-        builtin <=> role.builtin
-      end
-    else
-      -1
-    end
-  end
-
-  def to_s
-    name
-  end
-
-  def name
-    case builtin
-    when 1; l(:label_role_non_member, :default => read_attribute(:name))
-    when 2; l(:label_role_anonymous,  :default => read_attribute(:name))
-    else; read_attribute(:name)
-    end
-  end
-
-  # Return true if the role is a builtin role
-  def builtin?
-    self.builtin != 0
-  end
-
-  # Return true if the role is the anonymous role
-  def anonymous?
-    builtin == 2
-  end
-
-  # Return true if the role is a project member role
-  def member?
-    !self.builtin?
-  end
-
-  # Return true if role is allowed to do the specified action
-  # action can be:
-  # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
-  # * a permission Symbol (eg. :edit_project)
-  def allowed_to?(action)
-    if action.is_a? Hash
-      allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
-    else
-      allowed_permissions.include? action
-    end
-  end
-
-  # Return all the permissions that can be given to the role
-  def setable_permissions
-    setable_permissions = Redmine::AccessControl.permissions - Redmine::AccessControl.public_permissions
-    setable_permissions -= Redmine::AccessControl.members_only_permissions if self.builtin == BUILTIN_NON_MEMBER
-    setable_permissions -= Redmine::AccessControl.loggedin_only_permissions if self.builtin == BUILTIN_ANONYMOUS
-    setable_permissions
-  end
-
-  # Find all the roles that can be given to a project member
-  def self.find_all_givable
-    Role.givable.all
-  end
-
-  # Return the builtin 'non member' role.  If the role doesn't exist,
-  # it will be created on the fly.
-  def self.non_member
-    find_or_create_system_role(BUILTIN_NON_MEMBER, 'Non member')
-  end
-
-  # Return the builtin 'anonymous' role.  If the role doesn't exist,
-  # it will be created on the fly.
-  def self.anonymous
-    find_or_create_system_role(BUILTIN_ANONYMOUS, 'Anonymous')
-  end
-
-private
-
-  def allowed_permissions
-    @allowed_permissions ||= permissions + Redmine::AccessControl.public_permissions.collect {|p| p.name}
-  end
-
-  def allowed_actions
-    @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
-  end
-
-  def check_deletable
-    raise "Can't delete role" if members.any?
-    raise "Can't delete builtin role" if builtin?
-  end
-
-  def self.find_or_create_system_role(builtin, name)
-    role = where(:builtin => builtin).first
-    if role.nil?
-      role = create(:name => name, :position => 0) do |r|
-        r.builtin = builtin
-      end
-      raise "Unable to create the #{name} role." if role.new_record?
-    end
-    role
-  end
-end
--- a/.svn/pristine/d5/d50fa731af4ebca2aab740b7c23ce3cd606c5836.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,536 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class MailHandler < ActionMailer::Base
-  include ActionView::Helpers::SanitizeHelper
-  include Redmine::I18n
-
-  class UnauthorizedAction < StandardError; end
-  class MissingInformation < StandardError; end
-
-  attr_reader :email, :user
-
-  def self.receive(email, options={})
-    @@handler_options = options.dup
-
-    @@handler_options[:issue] ||= {}
-
-    if @@handler_options[:allow_override].is_a?(String)
-      @@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip)
-    end
-    @@handler_options[:allow_override] ||= []
-    # Project needs to be overridable if not specified
-    @@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project)
-    # Status overridable by default
-    @@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
-
-    @@handler_options[:no_account_notice] = (@@handler_options[:no_account_notice].to_s == '1')
-    @@handler_options[:no_notification] = (@@handler_options[:no_notification].to_s == '1')
-    @@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1')
-
-    email.force_encoding('ASCII-8BIT') if email.respond_to?(:force_encoding)
-    super(email)
-  end
-
-  # Extracts MailHandler options from environment variables
-  # Use when receiving emails with rake tasks
-  def self.extract_options_from_env(env)
-    options = {:issue => {}}
-    %w(project status tracker category priority).each do |option|
-      options[:issue][option.to_sym] = env[option] if env[option]
-    end
-    %w(allow_override unknown_user no_permission_check no_account_notice default_group).each do |option|
-      options[option.to_sym] = env[option] if env[option]
-    end
-    options
-  end
-
-  def logger
-    Rails.logger
-  end
-
-  cattr_accessor :ignored_emails_headers
-  @@ignored_emails_headers = {
-    'X-Auto-Response-Suppress' => 'oof',
-    'Auto-Submitted' => /^auto-/
-  }
-
-  # Processes incoming emails
-  # Returns the created object (eg. an issue, a message) or false
-  def receive(email)
-    @email = email
-    sender_email = email.from.to_a.first.to_s.strip
-    # Ignore emails received from the application emission address to avoid hell cycles
-    if sender_email.downcase == Setting.mail_from.to_s.strip.downcase
-      if logger
-        logger.info  "MailHandler: ignoring email from Redmine emission address [#{sender_email}]"
-      end
-      return false
-    end
-    # Ignore auto generated emails
-    self.class.ignored_emails_headers.each do |key, ignored_value|
-      value = email.header[key]
-      if value
-        value = value.to_s.downcase
-        if (ignored_value.is_a?(Regexp) && value.match(ignored_value)) || value == ignored_value
-          if logger
-            logger.info "MailHandler: ignoring email with #{key}:#{value} header"
-          end
-          return false
-        end
-      end
-    end
-    @user = User.find_by_mail(sender_email) if sender_email.present?
-    if @user && !@user.active?
-      if logger
-        logger.info  "MailHandler: ignoring email from non-active user [#{@user.login}]"
-      end
-      return false
-    end
-    if @user.nil?
-      # Email was submitted by an unknown user
-      case @@handler_options[:unknown_user]
-      when 'accept'
-        @user = User.anonymous
-      when 'create'
-        @user = create_user_from_email
-        if @user
-          if logger
-            logger.info "MailHandler: [#{@user.login}] account created"
-          end
-          add_user_to_group(@@handler_options[:default_group])
-          unless @@handler_options[:no_account_notice]
-            Mailer.account_information(@user, @user.password).deliver
-          end
-        else
-          if logger
-            logger.error "MailHandler: could not create account for [#{sender_email}]"
-          end
-          return false
-        end
-      else
-        # Default behaviour, emails from unknown users are ignored
-        if logger
-          logger.info  "MailHandler: ignoring email from unknown user [#{sender_email}]"
-        end
-        return false
-      end
-    end
-    User.current = @user
-    dispatch
-  end
-
-  private
-
-  MESSAGE_ID_RE = %r{^<?redmine\.([a-z0-9_]+)\-(\d+)\.\d+(\.[a-f0-9]+)?@}
-  ISSUE_REPLY_SUBJECT_RE = %r{\[[^\]]*#(\d+)\]}
-  MESSAGE_REPLY_SUBJECT_RE = %r{\[[^\]]*msg(\d+)\]}
-
-  def dispatch
-    headers = [email.in_reply_to, email.references].flatten.compact
-    subject = email.subject.to_s
-    if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE}
-      klass, object_id = $1, $2.to_i
-      method_name = "receive_#{klass}_reply"
-      if self.class.private_instance_methods.collect(&:to_s).include?(method_name)
-        send method_name, object_id
-      else
-        # ignoring it
-      end
-    elsif m = subject.match(ISSUE_REPLY_SUBJECT_RE)
-      receive_issue_reply(m[1].to_i)
-    elsif m = subject.match(MESSAGE_REPLY_SUBJECT_RE)
-      receive_message_reply(m[1].to_i)
-    else
-      dispatch_to_default
-    end
-  rescue ActiveRecord::RecordInvalid => e
-    # TODO: send a email to the user
-    logger.error e.message if logger
-    false
-  rescue MissingInformation => e
-    logger.error "MailHandler: missing information from #{user}: #{e.message}" if logger
-    false
-  rescue UnauthorizedAction => e
-    logger.error "MailHandler: unauthorized attempt from #{user}" if logger
-    false
-  end
-
-  def dispatch_to_default
-    receive_issue
-  end
-
-  # Creates a new issue
-  def receive_issue
-    project = target_project
-    # check permission
-    unless @@handler_options[:no_permission_check]
-      raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
-    end
-
-    issue = Issue.new(:author => user, :project => project)
-    issue.safe_attributes = issue_attributes_from_keywords(issue)
-    issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
-    issue.subject = cleaned_up_subject
-    if issue.subject.blank?
-      issue.subject = '(no subject)'
-    end
-    issue.description = cleaned_up_text_body
-
-    # add To and Cc as watchers before saving so the watchers can reply to Redmine
-    add_watchers(issue)
-    issue.save!
-    add_attachments(issue)
-    logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger
-    issue
-  end
-
-  # Adds a note to an existing issue
-  def receive_issue_reply(issue_id, from_journal=nil)
-    issue = Issue.find_by_id(issue_id)
-    return unless issue
-    # check permission
-    unless @@handler_options[:no_permission_check]
-      unless user.allowed_to?(:add_issue_notes, issue.project) ||
-               user.allowed_to?(:edit_issues, issue.project)
-        raise UnauthorizedAction
-      end
-    end
-
-    # ignore CLI-supplied defaults for new issues
-    @@handler_options[:issue].clear
-
-    journal = issue.init_journal(user)
-    if from_journal && from_journal.private_notes?
-      # If the received email was a reply to a private note, make the added note private
-      issue.private_notes = true
-    end
-    issue.safe_attributes = issue_attributes_from_keywords(issue)
-    issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
-    journal.notes = cleaned_up_text_body
-    add_attachments(issue)
-    issue.save!
-    if logger
-      logger.info "MailHandler: issue ##{issue.id} updated by #{user}"
-    end
-    journal
-  end
-
-  # Reply will be added to the issue
-  def receive_journal_reply(journal_id)
-    journal = Journal.find_by_id(journal_id)
-    if journal && journal.journalized_type == 'Issue'
-      receive_issue_reply(journal.journalized_id, journal)
-    end
-  end
-
-  # Receives a reply to a forum message
-  def receive_message_reply(message_id)
-    message = Message.find_by_id(message_id)
-    if message
-      message = message.root
-
-      unless @@handler_options[:no_permission_check]
-        raise UnauthorizedAction unless user.allowed_to?(:add_messages, message.project)
-      end
-
-      if !message.locked?
-        reply = Message.new(:subject => cleaned_up_subject.gsub(%r{^.*msg\d+\]}, '').strip,
-                            :content => cleaned_up_text_body)
-        reply.author = user
-        reply.board = message.board
-        message.children << reply
-        add_attachments(reply)
-        reply
-      else
-        if logger
-          logger.info "MailHandler: ignoring reply from [#{sender_email}] to a locked topic"
-        end
-      end
-    end
-  end
-
-  def add_attachments(obj)
-    if email.attachments && email.attachments.any?
-      email.attachments.each do |attachment|
-        next unless accept_attachment?(attachment)
-        obj.attachments << Attachment.create(:container => obj,
-                          :file => attachment.decoded,
-                          :filename => attachment.filename,
-                          :author => user,
-                          :content_type => attachment.mime_type)
-      end
-    end
-  end
-
-  # Returns false if the +attachment+ of the incoming email should be ignored
-  def accept_attachment?(attachment)
-    @excluded ||= Setting.mail_handler_excluded_filenames.to_s.split(',').map(&:strip).reject(&:blank?)
-    @excluded.each do |pattern|
-      regexp = %r{\A#{Regexp.escape(pattern).gsub("\\*", ".*")}\z}i
-      if attachment.filename.to_s =~ regexp
-        logger.info "MailHandler: ignoring attachment #{attachment.filename} matching #{pattern}"
-        return false
-      end
-    end
-    true
-  end
-
-  # Adds To and Cc as watchers of the given object if the sender has the
-  # appropriate permission
-  def add_watchers(obj)
-    if user.allowed_to?("add_#{obj.class.name.underscore}_watchers".to_sym, obj.project)
-      addresses = [email.to, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}
-      unless addresses.empty?
-        watchers = User.active.where('LOWER(mail) IN (?)', addresses).all
-        watchers.each {|w| obj.add_watcher(w)}
-      end
-    end
-  end
-
-  def get_keyword(attr, options={})
-    @keywords ||= {}
-    if @keywords.has_key?(attr)
-      @keywords[attr]
-    else
-      @keywords[attr] = begin
-        if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) &&
-              (v = extract_keyword!(plain_text_body, attr, options[:format]))
-          v
-        elsif !@@handler_options[:issue][attr].blank?
-          @@handler_options[:issue][attr]
-        end
-      end
-    end
-  end
-
-  # Destructively extracts the value for +attr+ in +text+
-  # Returns nil if no matching keyword found
-  def extract_keyword!(text, attr, format=nil)
-    keys = [attr.to_s.humanize]
-    if attr.is_a?(Symbol)
-      if user && user.language.present?
-        keys << l("field_#{attr}", :default => '', :locale =>  user.language)
-      end
-      if Setting.default_language.present?
-        keys << l("field_#{attr}", :default => '', :locale =>  Setting.default_language)
-      end
-    end
-    keys.reject! {|k| k.blank?}
-    keys.collect! {|k| Regexp.escape(k)}
-    format ||= '.+'
-    keyword = nil
-    regexp = /^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i
-    if m = text.match(regexp)
-      keyword = m[2].strip
-      text.gsub!(regexp, '')
-    end
-    keyword
-  end
-
-  def target_project
-    # TODO: other ways to specify project:
-    # * parse the email To field
-    # * specific project (eg. Setting.mail_handler_target_project)
-    target = Project.find_by_identifier(get_keyword(:project))
-    if target.nil?
-      # Invalid project keyword, use the project specified as the default one
-      default_project = @@handler_options[:issue][:project]
-      if default_project.present?
-        target = Project.find_by_identifier(default_project)
-      end
-    end
-    raise MissingInformation.new('Unable to determine target project') if target.nil?
-    target
-  end
-
-  # Returns a Hash of issue attributes extracted from keywords in the email body
-  def issue_attributes_from_keywords(issue)
-    assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_assignee_from_keyword(k, issue)
-
-    attrs = {
-      'tracker_id' => (k = get_keyword(:tracker)) && issue.project.trackers.named(k).first.try(:id),
-      'status_id' =>  (k = get_keyword(:status)) && IssueStatus.named(k).first.try(:id),
-      'priority_id' => (k = get_keyword(:priority)) && IssuePriority.named(k).first.try(:id),
-      'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.named(k).first.try(:id),
-      'assigned_to_id' => assigned_to.try(:id),
-      'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) &&
-                                issue.project.shared_versions.named(k).first.try(:id),
-      'start_date' => get_keyword(:start_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
-      'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
-      'estimated_hours' => get_keyword(:estimated_hours, :override => true),
-      'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0')
-    }.delete_if {|k, v| v.blank? }
-
-    if issue.new_record? && attrs['tracker_id'].nil?
-      attrs['tracker_id'] = issue.project.trackers.first.try(:id)
-    end
-
-    attrs
-  end
-
-  # Returns a Hash of issue custom field values extracted from keywords in the email body
-  def custom_field_values_from_keywords(customized)
-    customized.custom_field_values.inject({}) do |h, v|
-      if keyword = get_keyword(v.custom_field.name, :override => true)
-        h[v.custom_field.id.to_s] = v.custom_field.value_from_keyword(keyword, customized)
-      end
-      h
-    end
-  end
-
-  # Returns the text/plain part of the email
-  # If not found (eg. HTML-only email), returns the body with tags removed
-  def plain_text_body
-    return @plain_text_body unless @plain_text_body.nil?
-
-    parts = if (text_parts = email.all_parts.select {|p| p.mime_type == 'text/plain'}).present?
-              text_parts
-            elsif (html_parts = email.all_parts.select {|p| p.mime_type == 'text/html'}).present?
-              html_parts
-            else
-              [email]
-            end
-
-    parts.reject! do |part|
-      part.header[:content_disposition].try(:disposition_type) == 'attachment'
-    end
-
-    @plain_text_body = parts.map {|p| Redmine::CodesetUtil.to_utf8(p.body.decoded, p.charset)}.join("\r\n")
-
-    # strip html tags and remove doctype directive
-    if parts.any? {|p| p.mime_type == 'text/html'}
-      @plain_text_body = strip_tags(@plain_text_body.strip)
-      @plain_text_body.sub! %r{^<!DOCTYPE .*$}, ''
-    end
-
-    @plain_text_body
-  end
-
-  def cleaned_up_text_body
-    cleanup_body(plain_text_body)
-  end
-
-  def cleaned_up_subject
-    subject = email.subject.to_s
-    subject.strip[0,255]
-  end
-
-  def self.full_sanitizer
-    @full_sanitizer ||= HTML::FullSanitizer.new
-  end
-
-  def self.assign_string_attribute_with_limit(object, attribute, value, limit=nil)
-    limit ||= object.class.columns_hash[attribute.to_s].limit || 255
-    value = value.to_s.slice(0, limit)
-    object.send("#{attribute}=", value)
-  end
-
-  # Returns a User from an email address and a full name
-  def self.new_user_from_attributes(email_address, fullname=nil)
-    user = User.new
-
-    # Truncating the email address would result in an invalid format
-    user.mail = email_address
-    assign_string_attribute_with_limit(user, 'login', email_address, User::LOGIN_LENGTH_LIMIT)
-
-    names = fullname.blank? ? email_address.gsub(/@.*$/, '').split('.') : fullname.split
-    assign_string_attribute_with_limit(user, 'firstname', names.shift, 30)
-    assign_string_attribute_with_limit(user, 'lastname', names.join(' '), 30)
-    user.lastname = '-' if user.lastname.blank?
-    user.language = Setting.default_language
-    user.generate_password = true
-    user.mail_notification = 'only_my_events'
-
-    unless user.valid?
-      user.login = "user#{Redmine::Utils.random_hex(6)}" unless user.errors[:login].blank?
-      user.firstname = "-" unless user.errors[:firstname].blank?
-      (puts user.errors[:lastname];user.lastname  = "-") unless user.errors[:lastname].blank?
-    end
-
-    user
-  end
-
-  # Creates a User for the +email+ sender
-  # Returns the user or nil if it could not be created
-  def create_user_from_email
-    from = email.header['from'].to_s
-    addr, name = from, nil
-    if m = from.match(/^"?(.+?)"?\s+<(.+@.+)>$/)
-      addr, name = m[2], m[1]
-    end
-    if addr.present?
-      user = self.class.new_user_from_attributes(addr, name)
-      if @@handler_options[:no_notification]
-        user.mail_notification = 'none'
-      end
-      if user.save
-        user
-      else
-        logger.error "MailHandler: failed to create User: #{user.errors.full_messages}" if logger
-        nil
-      end
-    else
-      logger.error "MailHandler: failed to create User: no FROM address found" if logger
-      nil
-    end
-  end
-
-  # Adds the newly created user to default group
-  def add_user_to_group(default_group)
-    if default_group.present?
-      default_group.split(',').each do |group_name|
-        if group = Group.named(group_name).first
-          group.users << @user
-        elsif logger
-          logger.warn "MailHandler: could not add user to [#{group_name}], group not found"
-        end
-      end
-    end
-  end
-
-  # Removes the email body of text after the truncation configurations.
-  def cleanup_body(body)
-    delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)}
-    unless delimiters.empty?
-      regex = Regexp.new("^[> ]*(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE)
-      body = body.gsub(regex, '')
-    end
-    body.strip
-  end
-
-  def find_assignee_from_keyword(keyword, issue)
-    keyword = keyword.to_s.downcase
-    assignable = issue.assignable_users
-    assignee = nil
-    assignee ||= assignable.detect {|a|
-                   a.mail.to_s.downcase == keyword ||
-                     a.login.to_s.downcase == keyword
-                 }
-    if assignee.nil? && keyword.match(/ /)
-      firstname, lastname = *(keyword.split) # "First Last Throwaway"
-      assignee ||= assignable.detect {|a|
-                     a.is_a?(User) && a.firstname.to_s.downcase == firstname &&
-                       a.lastname.to_s.downcase == lastname
-                   }
-    end
-    if assignee.nil?
-      assignee ||= assignable.detect {|a| a.name.downcase == keyword}
-    end
-    assignee
-  end
-end
--- a/.svn/pristine/d5/d56bb30205e35d46995a303698017ed24f7ce040.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class MessagesControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles, :boards, :messages, :enabled_modules
-
-  def setup
-    User.current = nil
-  end
-
-  def test_show
-    get :show, :board_id => 1, :id => 1
-    assert_response :success
-    assert_template 'show'
-    assert_not_nil assigns(:board)
-    assert_not_nil assigns(:project)
-    assert_not_nil assigns(:topic)
-  end
-  
-  def test_show_should_contain_reply_field_tags_for_quoting
-    @request.session[:user_id] = 2
-    get :show, :board_id => 1, :id => 1
-    assert_response :success
-
-    # tags required by MessagesController#quote
-    assert_tag 'input', :attributes => {:id => 'message_subject'}
-    assert_tag 'textarea', :attributes => {:id => 'message_content'}
-    assert_tag 'div', :attributes => {:id => 'reply'}
-  end
-
-  def test_show_with_pagination
-    message = Message.find(1)
-    assert_difference 'Message.count', 30 do
-      30.times do
-        message.children << Message.new(:subject => 'Reply', :content => 'Reply body', :author_id => 2, :board_id => 1)
-      end
-    end
-    get :show, :board_id => 1, :id => 1, :r => message.children.last(:order => 'id').id
-    assert_response :success
-    assert_template 'show'
-    replies = assigns(:replies)
-    assert_not_nil replies
-    assert !replies.include?(message.children.first(:order => 'id'))
-    assert replies.include?(message.children.last(:order => 'id'))
-  end
-
-  def test_show_with_reply_permission
-    @request.session[:user_id] = 2
-    get :show, :board_id => 1, :id => 1
-    assert_response :success
-    assert_template 'show'
-    assert_tag :div, :attributes => { :id => 'reply' },
-                     :descendant => { :tag => 'textarea', :attributes => { :id => 'message_content' } }
-  end
-
-  def test_show_message_not_found
-    get :show, :board_id => 1, :id => 99999
-    assert_response 404
-  end
-
-  def test_show_message_from_invalid_board_should_respond_with_404
-    get :show, :board_id => 999, :id => 1
-    assert_response 404
-  end
-
-  def test_get_new
-    @request.session[:user_id] = 2
-    get :new, :board_id => 1
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_get_new_with_invalid_board
-    @request.session[:user_id] = 2
-    get :new, :board_id => 99
-    assert_response 404
-  end
-
-  def test_post_new
-    @request.session[:user_id] = 2
-    ActionMailer::Base.deliveries.clear
-
-    with_settings :notified_events => %w(message_posted) do
-      post :new, :board_id => 1,
-               :message => { :subject => 'Test created message',
-                             :content => 'Message body'}
-    end
-    message = Message.find_by_subject('Test created message')
-    assert_not_nil message
-    assert_redirected_to "/boards/1/topics/#{message.to_param}"
-    assert_equal 'Message body', message.content
-    assert_equal 2, message.author_id
-    assert_equal 1, message.board_id
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert_equal "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] Test created message", mail.subject
-    assert_mail_body_match 'Message body', mail
-    # author
-    assert mail.bcc.include?('jsmith@somenet.foo')
-    # project member
-    assert mail.bcc.include?('dlopper@somenet.foo')
-  end
-
-  def test_get_edit
-    @request.session[:user_id] = 2
-    get :edit, :board_id => 1, :id => 1
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_post_edit
-    @request.session[:user_id] = 2
-    post :edit, :board_id => 1, :id => 1,
-                :message => { :subject => 'New subject',
-                              :content => 'New body'}
-    assert_redirected_to '/boards/1/topics/1'
-    message = Message.find(1)
-    assert_equal 'New subject', message.subject
-    assert_equal 'New body', message.content
-  end
-
-  def test_post_edit_sticky_and_locked
-    @request.session[:user_id] = 2
-    post :edit, :board_id => 1, :id => 1,
-                :message => { :subject => 'New subject',
-                              :content => 'New body',
-                              :locked => '1',
-                              :sticky => '1'}
-    assert_redirected_to '/boards/1/topics/1'
-    message = Message.find(1)
-    assert_equal true, message.sticky?
-    assert_equal true, message.locked?
-  end
-
-  def test_post_edit_should_allow_to_change_board
-    @request.session[:user_id] = 2
-    post :edit, :board_id => 1, :id => 1,
-                :message => { :subject => 'New subject',
-                              :content => 'New body',
-                              :board_id => 2}
-    assert_redirected_to '/boards/2/topics/1'
-    message = Message.find(1)
-    assert_equal Board.find(2), message.board
-  end
-
-  def test_reply
-    @request.session[:user_id] = 2
-    post :reply, :board_id => 1, :id => 1, :reply => { :content => 'This is a test reply', :subject => 'Test reply' }
-    reply = Message.order('id DESC').first
-    assert_redirected_to "/boards/1/topics/1?r=#{reply.id}"
-    assert Message.find_by_subject('Test reply')
-  end
-
-  def test_destroy_topic
-    @request.session[:user_id] = 2
-    assert_difference 'Message.count', -3 do
-      post :destroy, :board_id => 1, :id => 1
-    end
-    assert_redirected_to '/projects/ecookbook/boards/1'
-    assert_nil Message.find_by_id(1)
-  end
-
-  def test_destroy_reply
-    @request.session[:user_id] = 2
-    assert_difference 'Message.count', -1 do
-      post :destroy, :board_id => 1, :id => 2
-    end
-    assert_redirected_to '/boards/1/topics/1?r=2'
-    assert_nil Message.find_by_id(2)
-  end
-
-  def test_quote
-    @request.session[:user_id] = 2
-    xhr :get, :quote, :board_id => 1, :id => 3
-    assert_response :success
-    assert_equal 'text/javascript', response.content_type
-    assert_template 'quote'
-    assert_include 'RE: First post', response.body
-    assert_include '> An other reply', response.body
-  end
-
-  def test_preview_new
-    @request.session[:user_id] = 2
-    post :preview,
-      :board_id => 1,
-      :message => {:subject => "", :content => "Previewed text"}
-    assert_response :success
-    assert_template 'common/_preview'
-  end
-
-  def test_preview_edit
-    @request.session[:user_id] = 2
-    post :preview,
-      :id => 4,
-      :board_id => 1,
-      :message => {:subject => "", :content => "Previewed text"}
-    assert_response :success
-    assert_template 'common/_preview'
-  end
-end
--- a/.svn/pristine/d5/d5c99af330410b19fab22c939293b2b8a8b960e8.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesGitTest < ActionController::IntegrationTest
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :repositories, :enabled_modules
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
-  REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
-  PRJ_ID     = 3
-
-  def setup
-    User.current = nil
-    @project    = Project.find(PRJ_ID)
-    @repository = Repository::Git.create(
-                      :project       => @project,
-                      :url           => REPOSITORY_PATH,
-                      :path_encoding => 'ISO-8859-1'
-                      )
-    assert @repository
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    def test_index
-      get '/projects/subproject1/repository/'
-      assert_response :success
-    end
-
-    def test_diff_two_revs
-      get '/projects/subproject1/repository/diff?rev=61b685fbe&rev_to=2f9c0091'
-      assert_response :success
-    end
-  end
-end
--- a/.svn/pristine/d6/d6dba1cf7d52d25c0fa5bfc624e064b5ba2087ba.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class TimelogCustomFieldsVisibilityTest < ActionController::TestCase
-  tests TimelogController
-  fixtures :projects,
-           :users,
-           :roles,
-           :members,
-           :member_roles,
-           :issue_statuses,
-           :trackers,
-           :projects_trackers,
-           :enabled_modules,
-           :enumerations,
-           :workflows
-
-  def setup
-    field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :trackers => Tracker.all}
-    @fields = []
-    @fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true)))
-    @fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2])))
-    @fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3])))
-    @issue = Issue.generate!(
-      :author_id => 1,
-      :project_id => 1,
-      :tracker_id => 1,
-      :custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'}
-    )
-    TimeEntry.generate!(:issue => @issue)
-
-    @user_with_role_on_other_project = User.generate!
-    User.add_to_project(@user_with_role_on_other_project, Project.find(2), Role.find(3))
-
-    @users_to_test = {
-      User.find(1) => [@field1, @field2, @field3],
-      User.find(3) => [@field1, @field2],
-      @user_with_role_on_other_project => [@field1], # should see field1 only on Project 1
-      User.generate! => [@field1],
-      User.anonymous => [@field1]
-    }
-
-    Member.where(:project_id => 1).each do |member|
-      member.destroy unless @users_to_test.keys.include?(member.principal)
-    end
-  end
-
-  def test_index_should_show_visible_custom_fields_only
-    @users_to_test.each do |user, fields|
-      @request.session[:user_id] = user.id
-      get :index, :project_id => 1, :issue_id => @issue.id, :c => (['hours'] + @fields.map{|f| "issue.cf_#{f.id}"})
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_select 'td', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}"
-        else
-          assert_select 'td', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}"
-        end
-      end
-    end
-  end
-
-  def test_index_as_csv_should_show_visible_custom_fields_only
-    @users_to_test.each do |user, fields|
-      @request.session[:user_id] = user.id
-      get :index, :project_id => 1, :issue_id => @issue.id, :c => (['hours'] + @fields.map{|f| "issue.cf_#{f.id}"}), :format => 'csv'
-      @fields.each_with_index do |field, i|
-        if fields.include?(field)
-          assert_include "Value#{i}", response.body, "User #{user.id} was not able to view #{field.name} in CSV"
-        else
-          assert_not_include "Value#{i}", response.body, "User #{user.id} was able to view #{field.name} in CSV"
-        end
-      end
-    end
-  end
-
-  def test_index_with_partial_custom_field_visibility_should_show_visible_custom_fields_only
-    Issue.delete_all
-    TimeEntry.delete_all
-    p1 = Project.generate!
-    p2 = Project.generate!
-    user = User.generate!
-    User.add_to_project(user, p1, Role.find_all_by_id(1,3))
-    User.add_to_project(user, p2, Role.find_all_by_id(3))
-    TimeEntry.generate!(:issue => Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueA'}))
-    TimeEntry.generate!(:issue => Issue.generate!(:project => p2, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueB'}))
-    TimeEntry.generate!(:issue => Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueC'}))
-
-    @request.session[:user_id] = user.id
-    get :index, :c => ["hours", "issue.cf_#{@field2.id}"]
-    assert_select 'td', :text => 'ValueA'
-    assert_select 'td', :text => 'ValueB', :count => 0
-    assert_select 'td', :text => 'ValueC'
-
-    get :index, :set_filter => '1', "issue.cf_#{@field2.id}" => '*'
-    assert_equal %w(ValueA ValueC), assigns(:entries).map{|i| i.issue.custom_field_value(@field2)}.sort
-  end
-end
--- a/.svn/pristine/d7/d70fd8a8adbbd6e7c06cc19c2775e3cc0289e1f1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class CalendarTest < ActiveSupport::TestCase
-
-  def test_monthly
-    c = Redmine::Helpers::Calendar.new(Date.today, :fr, :month)
-    assert_equal [1, 7], [c.startdt.cwday, c.enddt.cwday]
-
-    c = Redmine::Helpers::Calendar.new('2007-07-14'.to_date, :fr, :month)
-    assert_equal ['2007-06-25'.to_date, '2007-08-05'.to_date], [c.startdt, c.enddt]
-
-    c = Redmine::Helpers::Calendar.new(Date.today, :en, :month)
-    assert_equal [7, 6], [c.startdt.cwday, c.enddt.cwday]
-  end
-
-  def test_weekly
-    c = Redmine::Helpers::Calendar.new(Date.today, :fr, :week)
-    assert_equal [1, 7], [c.startdt.cwday, c.enddt.cwday]
-
-    c = Redmine::Helpers::Calendar.new('2007-07-14'.to_date, :fr, :week)
-    assert_equal ['2007-07-09'.to_date, '2007-07-15'.to_date], [c.startdt, c.enddt]
-
-    c = Redmine::Helpers::Calendar.new(Date.today, :en, :week)
-    assert_equal [7, 6], [c.startdt.cwday, c.enddt.cwday]
-  end
-
-  def test_monthly_start_day
-    [1, 6, 7].each do |day|
-      with_settings :start_of_week => day do
-        c = Redmine::Helpers::Calendar.new(Date.today, :en, :month)
-        assert_equal day , c.startdt.cwday
-        assert_equal (day + 5) % 7 + 1, c.enddt.cwday
-      end
-    end
-  end
-
-  def test_weekly_start_day
-    [1, 6, 7].each do |day|
-      with_settings :start_of_week => day do
-        c = Redmine::Helpers::Calendar.new(Date.today, :en, :week)
-        assert_equal day, c.startdt.cwday
-        assert_equal (day + 5) % 7 + 1, c.enddt.cwday
-      end
-    end
-  end
-end
--- a/.svn/pristine/d7/d7610ec8c096fad5d592071757d4c3415e6a2e6a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-== Redmine installation
-
-Redmine - project management software
-Copyright (C) 2006-2013  Jean-Philippe Lang
-http://www.redmine.org/
-
-
-== Requirements
-
-* Ruby 1.8.7, 1.9.2, 1.9.3 or 2.0.0
-* RubyGems
-* Bundler >= 1.0.21
-
-* A database:
-  * MySQL (tested with MySQL 5.1)
-  * PostgreSQL (tested with PostgreSQL 9.1)
-  * SQLite3 (tested with SQLite 3.7)
-  * SQLServer (tested with SQLServer 2012)
-
-Optional:
-* SCM binaries (e.g. svn, git...), for repository browsing (must be available in PATH)
-* ImageMagick (to enable Gantt export to png images)
-
-== Installation
-
-1. Uncompress the program archive
-
-2. Create an empty utf8 encoded database: "redmine" for example
-
-3. Configure the database parameters in config/database.yml
-   for the "production" environment (default database is MySQL and ruby1.9)
-
-   If you're running Redmine with MySQL and ruby1.8, replace the adapter name
-   with `mysql`
-
-4. Install the required gems by running:
-     bundle install --without development test
-
-   If ImageMagick is not installed on your system, you should skip the installation
-   of the rmagick gem using:
-     bundle install --without development test rmagick
-
-   Only the gems that are needed by the adapters you've specified in your database
-   configuration file are actually installed (eg. if your config/database.yml
-   uses the 'mysql2' adapter, then only the mysql2 gem will be installed). Don't
-   forget to re-run `bundle install` when you change config/database.yml for using
-   other database adapters.
-
-   If you need to load some gems that are not required by Redmine core (eg. fcgi),
-   you can create a file named Gemfile.local at the root of your redmine directory.
-   It will be loaded automatically when running `bundle install`.
-
-5. Generate a session store secret
-   
-   Redmine stores session data in cookies by default, which requires
-   a secret to be generated. Under the application main directory run:
-     rake generate_secret_token
-
-6. Create the database structure
-   
-   Under the application main directory run:
-     rake db:migrate RAILS_ENV="production"
-   
-   It will create all the tables and an administrator account.
-
-7. Setting up permissions (Windows users have to skip this section)
-   
-   The user who runs Redmine must have write permission on the following
-   subdirectories: files, log, tmp & public/plugin_assets.
-   
-   Assuming you run Redmine with a user named "redmine":
-     sudo chown -R redmine:redmine files log tmp public/plugin_assets
-     sudo chmod -R 755 files log tmp public/plugin_assets
-
-8. Test the installation by running the WEBrick web server
-   
-   Under the main application directory run:
-     ruby script/rails server -e production
-   
-   Once WEBrick has started, point your browser to http://localhost:3000/
-   You should now see the application welcome page.
-
-9. Use the default administrator account to log in:
-   login: admin
-   password: admin
-   
-   Go to "Administration" to load the default configuration data (roles,
-   trackers, statuses, workflow) and to adjust the application settings
-
-== SMTP server Configuration
-
-Copy config/configuration.yml.example to config/configuration.yml and
-edit this file to adjust your SMTP settings.
-Do not forget to restart the application after any change to this file.
-
-Please do not enter your SMTP settings in environment.rb.
-
-== References
-
-* http://www.redmine.org/wiki/redmine/RedmineInstall
-* http://www.redmine.org/wiki/redmine/EmailConfiguration
-* http://www.redmine.org/wiki/redmine/RedmineSettings
-* http://www.redmine.org/wiki/redmine/RedmineRepositories
-* http://www.redmine.org/wiki/redmine/RedmineReceivingEmails
-* http://www.redmine.org/wiki/redmine/RedmineReminderEmails
-* http://www.redmine.org/wiki/redmine/RedmineLDAP
--- a/.svn/pristine/d7/d7993eab0e03bf713eaae4e70ad89bacc08a8657.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingPreviewsTest < ActionController::IntegrationTest
-  def test_previews
-    ["get", "post", "put"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/issues/preview/new/123" },
-          { :controller => 'previews', :action => 'issue', :project_id => '123' }
-        )
-      assert_routing(
-          { :method => method, :path => "/issues/preview/edit/321" },
-          { :controller => 'previews', :action => 'issue', :id => '321' }
-        )
-    end
-    assert_routing(
-        { :method => 'get', :path => "/news/preview" },
-        { :controller => 'previews', :action => 'news' }
-      )
-  end
-end
--- a/.svn/pristine/d8/d8da15b6a8a2fb05e57342be295616d42903caef.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'fileutils'
-
-module Redmine
-  module Thumbnail
-    extend Redmine::Utils::Shell
-
-    CONVERT_BIN = (Redmine::Configuration['imagemagick_convert_command'] || 'convert').freeze
-
-    # Generates a thumbnail for the source image to target
-    def self.generate(source, target, size)
-      return nil unless convert_available?
-      unless File.exists?(target)
-        directory = File.dirname(target)
-        unless File.exists?(directory)
-          FileUtils.mkdir_p directory
-        end
-        size_option = "#{size}x#{size}>"
-        cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -thumbnail #{shell_quote size_option} #{shell_quote target}"
-        unless system(cmd)
-          logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}")
-          return nil
-        end
-      end
-      target
-    end
-
-    def self.convert_available?
-      return @convert_available if defined?(@convert_available)
-      @convert_available = system("#{shell_quote CONVERT_BIN} -version") rescue false
-      logger.warn("Imagemagick's convert binary (#{CONVERT_BIN}) not available") unless @convert_available
-      @convert_available
-    end
-
-    def self.logger
-      Rails.logger
-    end
-  end
-end
--- a/.svn/pristine/d9/d9247e732a56dd9b3466a2d481b475b595b379f2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,183 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class ProjectNestedSetTest < ActiveSupport::TestCase
-
-  def setup
-    Project.delete_all
-
-    @a = Project.create!(:name => 'A', :identifier => 'projecta')
-    @a1 = Project.create!(:name => 'A1', :identifier => 'projecta1')
-    @a1.set_parent!(@a)
-    @a2 = Project.create!(:name => 'A2', :identifier => 'projecta2')
-    @a2.set_parent!(@a)
-
-    @c = Project.create!(:name => 'C', :identifier => 'projectc')
-    @c1 = Project.create!(:name => 'C1', :identifier => 'projectc1')
-    @c1.set_parent!(@c)
-
-    @b = Project.create!(:name => 'B', :identifier => 'projectb')
-    @b2 = Project.create!(:name => 'B2', :identifier => 'projectb2')
-    @b2.set_parent!(@b)
-    @b1 = Project.create!(:name => 'B1', :identifier => 'projectb1')
-    @b1.set_parent!(@b)
-    @b11 = Project.create!(:name => 'B11', :identifier => 'projectb11')
-    @b11.set_parent!(@b1)
-
-    @a, @a1, @a2, @b, @b1, @b11, @b2, @c, @c1 = *(Project.all.sort_by(&:name))
-  end
-
-  def test_valid_tree
-    assert_valid_nested_set
-  end
-
-  def test_rebuild_should_build_valid_tree
-    Project.update_all "lft = NULL, rgt = NULL"
-
-    Project.rebuild!
-    assert_valid_nested_set
-  end
-
-  def test_rebuild_tree_should_build_valid_tree_even_with_valid_lft_rgt_values
-    Project.update_all "name = 'YY'", {:id => @a.id }
-    # lft and rgt values are still valid (Project.rebuild! would not update anything)
-    # but projects are not ordered properly (YY is in the first place)
-
-    Project.rebuild_tree!
-    assert_valid_nested_set
-  end
-
-  def test_moving_a_child_to_a_different_parent_should_keep_valid_tree
-    assert_no_difference 'Project.count' do
-      Project.find_by_name('B1').set_parent!(Project.find_by_name('A2'))
-    end
-    assert_valid_nested_set
-  end
-
-  def test_renaming_a_root_to_first_position_should_update_nested_set_order
-    @c.name = '1'
-    @c.save!
-    assert_valid_nested_set
-  end
-
-  def test_renaming_a_root_to_middle_position_should_update_nested_set_order
-    @a.name = 'BA'
-    @a.save!
-    assert_valid_nested_set
-  end
-
-  def test_renaming_a_root_to_last_position_should_update_nested_set_order
-    @a.name = 'D'
-    @a.save!
-    assert_valid_nested_set
-  end
-
-  def test_renaming_a_root_to_same_position_should_update_nested_set_order
-    @c.name = 'D'
-    @c.save!
-    assert_valid_nested_set
-  end
-
-  def test_renaming_a_child_should_update_nested_set_order
-    @a1.name = 'A3'
-    @a1.save!
-    assert_valid_nested_set
-  end
-
-  def test_renaming_a_child_with_child_should_update_nested_set_order
-    @b1.name = 'B3'
-    @b1.save!
-    assert_valid_nested_set
-  end
-
-  def test_adding_a_root_to_first_position_should_update_nested_set_order
-    project = Project.create!(:name => '1', :identifier => 'projectba')
-    assert_valid_nested_set
-  end
-
-  def test_adding_a_root_to_middle_position_should_update_nested_set_order
-    project = Project.create!(:name => 'BA', :identifier => 'projectba')
-    assert_valid_nested_set
-  end
-
-  def test_adding_a_root_to_last_position_should_update_nested_set_order
-    project = Project.create!(:name => 'Z', :identifier => 'projectba')
-    assert_valid_nested_set
-  end
-
-  def test_destroying_a_root_with_children_should_keep_valid_tree
-    assert_difference 'Project.count', -4 do
-      Project.find_by_name('B').destroy
-    end
-    assert_valid_nested_set
-  end
-
-  def test_destroying_a_child_with_children_should_keep_valid_tree
-    assert_difference 'Project.count', -2 do
-      Project.find_by_name('B1').destroy
-    end
-    assert_valid_nested_set
-  end
-
-  private
-
-  def assert_nested_set_values(h)
-    assert Project.valid?
-    h.each do |project, expected|
-      project.reload
-      assert_equal expected, [project.parent_id, project.lft, project.rgt], "Unexpected nested set values for #{project.name}"
-    end
-  end
-
-  def assert_valid_nested_set
-    projects = Project.all
-    lft_rgt = projects.map {|p| [p.lft, p.rgt]}.flatten
-    assert_equal projects.size * 2, lft_rgt.uniq.size
-    assert_equal 1, lft_rgt.min
-    assert_equal projects.size * 2, lft_rgt.max
-
-    projects.each do |project|
-      # lft should always be < rgt
-      assert project.lft < project.rgt, "lft=#{project.lft} was not < rgt=#{project.rgt} for project #{project.name}"
-      if project.parent_id
-        # child lft/rgt values must be greater/lower
-        assert_not_nil project.parent, "parent was nil for project #{project.name}"
-        assert project.lft > project.parent.lft, "lft=#{project.lft} was not > parent.lft=#{project.parent.lft} for project #{project.name}"
-        assert project.rgt < project.parent.rgt, "rgt=#{project.rgt} was not < parent.rgt=#{project.parent.rgt} for project #{project.name}"
-      end
-      # no overlapping lft/rgt values
-      overlapping = projects.detect {|other| 
-        other != project && (
-          (other.lft > project.lft && other.lft < project.rgt && other.rgt > project.rgt) ||
-          (other.rgt > project.lft && other.rgt < project.rgt && other.lft < project.lft)
-        )
-      }
-      assert_nil overlapping, (overlapping && "Project #{overlapping.name} (#{overlapping.lft}/#{overlapping.rgt}) overlapped #{project.name} (#{project.lft}/#{project.rgt})")
-    end
-
-    # root projects sorted alphabetically
-    assert_equal Project.roots.map(&:name).sort, Project.roots.sort_by(&:lft).map(&:name), "Root projects were not properly sorted"
-    projects.each do |project|
-      if project.children.any?
-        # sibling projects sorted alphabetically
-        assert_equal project.children.map(&:name).sort, project.children.order('lft').map(&:name), "Project #{project.name}'s children were not properly sorted"
-      end
-    end
-  end
-end
--- a/.svn/pristine/d9/d98764f99d236520bd5f6ca42381f61878a79847.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingWikiTest < ActionController::IntegrationTest
-  def test_wiki_matching
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/wiki" },
-        { :controller => 'wiki', :action => 'show', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/wiki/lalala" },
-        { :controller => 'wiki', :action => 'show', :project_id => '567',
-          :id => 'lalala' }
-        )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/wiki/lalala.pdf" },
-        { :controller => 'wiki', :action => 'show', :project_id => '567',
-          :id => 'lalala', :format => 'pdf' }
-        )
-    assert_routing(
-         { :method => 'get', :path => "/projects/1/wiki/CookBook_documentation/diff" },
-         { :controller => 'wiki', :action => 'diff', :project_id => '1',
-           :id => 'CookBook_documentation' }
-       )
-    assert_routing(
-         { :method => 'get', :path => "/projects/1/wiki/CookBook_documentation/2" },
-         { :controller => 'wiki', :action => 'show', :project_id => '1',
-           :id => 'CookBook_documentation', :version => '2' }
-       )
-    assert_routing(
-         { :method => 'get', :path => "/projects/1/wiki/CookBook_documentation/2/diff" },
-         { :controller => 'wiki', :action => 'diff', :project_id => '1',
-           :id => 'CookBook_documentation', :version => '2' }
-       )
-    assert_routing(
-         { :method => 'get', :path => "/projects/1/wiki/CookBook_documentation/2/annotate" },
-         { :controller => 'wiki', :action => 'annotate', :project_id => '1',
-           :id => 'CookBook_documentation', :version => '2' }
-       )
-    # Make sure we don't route wiki page sub-uris to let plugins handle them
-    assert_raise(ActionController::RoutingError) do
-      assert_recognizes({}, {:method => 'get', :path => "/projects/1/wiki/CookBook_documentation/whatever"})
-    end
-  end
-
-  def test_wiki_misc
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/wiki/date_index" },
-        { :controller => 'wiki', :action => 'date_index', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/wiki/export" },
-        { :controller => 'wiki', :action => 'export', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/wiki/export.pdf" },
-        { :controller => 'wiki', :action => 'export', :project_id => '567', :format => 'pdf' }
-      )
-    assert_routing(
-         { :method => 'get', :path => "/projects/567/wiki/index" },
-         { :controller => 'wiki', :action => 'index', :project_id => '567' }
-       )
-  end
-
-  def test_wiki_resources
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/wiki/my_page/edit" },
-        { :controller => 'wiki', :action => 'edit', :project_id => '567',
-          :id => 'my_page' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/1/wiki/CookBook_documentation/history" },
-        { :controller => 'wiki', :action => 'history', :project_id => '1',
-          :id => 'CookBook_documentation' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/22/wiki/ladida/rename" },
-        { :controller => 'wiki', :action => 'rename', :project_id => '22',
-          :id => 'ladida' }
-      )
-    ["post", "put"].each do |method|
-      assert_routing(
-          { :method => method, :path => "/projects/567/wiki/CookBook_documentation/preview" },
-          { :controller => 'wiki', :action => 'preview', :project_id => '567',
-            :id => 'CookBook_documentation' }
-        )
-    end
-    assert_routing(
-        { :method => 'post', :path => "/projects/22/wiki/ladida/rename" },
-        { :controller => 'wiki', :action => 'rename', :project_id => '22',
-          :id => 'ladida' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/22/wiki/ladida/protect" },
-        { :controller => 'wiki', :action => 'protect', :project_id => '22',
-          :id => 'ladida' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/22/wiki/ladida/add_attachment" },
-        { :controller => 'wiki', :action => 'add_attachment', :project_id => '22',
-          :id => 'ladida' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/projects/567/wiki/my_page" },
-        { :controller => 'wiki', :action => 'update', :project_id => '567',
-          :id => 'my_page' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/projects/22/wiki/ladida" },
-        { :controller => 'wiki', :action => 'destroy', :project_id => '22',
-          :id => 'ladida' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/projects/22/wiki/ladida/3" },
-        { :controller => 'wiki', :action => 'destroy_version', :project_id => '22',
-          :id => 'ladida', :version => '3' }
-      )
-  end
-
-  def test_api
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/wiki/my_page.xml" },
-        { :controller => 'wiki', :action => 'show', :project_id => '567',
-          :id => 'my_page', :format => 'xml' }
-        )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/wiki/my_page.json" },
-        { :controller => 'wiki', :action => 'show', :project_id => '567',
-          :id => 'my_page', :format => 'json' }
-        )
-    assert_routing(
-         { :method => 'get', :path => "/projects/1/wiki/CookBook_documentation/2.xml" },
-         { :controller => 'wiki', :action => 'show', :project_id => '1',
-           :id => 'CookBook_documentation', :version => '2', :format => 'xml' }
-       )
-    assert_routing(
-         { :method => 'get', :path => "/projects/1/wiki/CookBook_documentation/2.json" },
-         { :controller => 'wiki', :action => 'show', :project_id => '1',
-           :id => 'CookBook_documentation', :version => '2', :format => 'json' }
-       )
-    assert_routing(
-         { :method => 'get', :path => "/projects/567/wiki/index.xml" },
-         { :controller => 'wiki', :action => 'index', :project_id => '567', :format => 'xml' }
-       )
-    assert_routing(
-         { :method => 'get', :path => "/projects/567/wiki/index.json" },
-         { :controller => 'wiki', :action => 'index', :project_id => '567', :format => 'json' }
-       )
-    assert_routing(
-        { :method => 'put', :path => "/projects/567/wiki/my_page.xml" },
-        { :controller => 'wiki', :action => 'update', :project_id => '567',
-          :id => 'my_page', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/projects/567/wiki/my_page.json" },
-        { :controller => 'wiki', :action => 'update', :project_id => '567',
-          :id => 'my_page', :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/projects/567/wiki/my_page.xml" },
-        { :controller => 'wiki', :action => 'destroy', :project_id => '567',
-          :id => 'my_page', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/projects/567/wiki/my_page.json" },
-        { :controller => 'wiki', :action => 'destroy', :project_id => '567',
-          :id => 'my_page', :format => 'json' }
-      )
-  end
-end
--- a/.svn/pristine/d9/d9ae3cb5600a5eb2525edf835bf114f2fc4ccc54.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,291 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/abstract_adapter'
-require 'uri'
-
-module Redmine
-  module Scm
-    module Adapters
-      class SubversionAdapter < AbstractAdapter
-
-        # SVN executable name
-        SVN_BIN = Redmine::Configuration['scm_subversion_command'] || "svn"
-
-        class << self
-          def client_command
-            @@bin    ||= SVN_BIN
-          end
-
-          def sq_bin
-            @@sq_bin ||= shell_quote_command
-          end
-
-          def client_version
-            @@client_version ||= (svn_binary_version || [])
-          end
-
-          def client_available
-            # --xml options are introduced in 1.3.
-            # http://subversion.apache.org/docs/release-notes/1.3.html
-            client_version_above?([1, 3])
-          end
-
-          def svn_binary_version
-            scm_version = scm_version_from_command_line.dup
-            if scm_version.respond_to?(:force_encoding)
-              scm_version.force_encoding('ASCII-8BIT')
-            end
-            if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
-              m[2].scan(%r{\d+}).collect(&:to_i)
-            end
-          end
-
-          def scm_version_from_command_line
-            shellout("#{sq_bin} --version") { |io| io.read }.to_s
-          end
-        end
-
-        # Get info about the svn repository
-        def info
-          cmd = "#{self.class.sq_bin} info --xml #{target}"
-          cmd << credentials_string
-          info = nil
-          shellout(cmd) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
-            begin
-              doc = parse_xml(output)
-              # root_url = doc.elements["info/entry/repository/root"].text
-              info = Info.new({:root_url => doc['info']['entry']['repository']['root']['__content__'],
-                               :lastrev => Revision.new({
-                                 :identifier => doc['info']['entry']['commit']['revision'],
-                                 :time => Time.parse(doc['info']['entry']['commit']['date']['__content__']).localtime,
-                                 :author => (doc['info']['entry']['commit']['author'] ? doc['info']['entry']['commit']['author']['__content__'] : "")
-                               })
-                             })
-            rescue
-            end
-          end
-          return nil if $? && $?.exitstatus != 0
-          info
-        rescue CommandFailed
-          return nil
-        end
-
-        # Returns an Entries collection
-        # or nil if the given path doesn't exist in the repository
-        def entries(path=nil, identifier=nil, options={})
-          path ||= ''
-          identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
-          entries = Entries.new
-          cmd = "#{self.class.sq_bin} list --xml #{target(path)}@#{identifier}"
-          cmd << credentials_string
-          shellout(cmd) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
-            begin
-              doc = parse_xml(output)
-              each_xml_element(doc['lists']['list'], 'entry') do |entry|
-                commit = entry['commit']
-                commit_date = commit['date']
-                # Skip directory if there is no commit date (usually that
-                # means that we don't have read access to it)
-                next if entry['kind'] == 'dir' && commit_date.nil?
-                name = entry['name']['__content__']
-                entries << Entry.new({:name => URI.unescape(name),
-                            :path => ((path.empty? ? "" : "#{path}/") + name),
-                            :kind => entry['kind'],
-                            :size => ((s = entry['size']) ? s['__content__'].to_i : nil),
-                            :lastrev => Revision.new({
-                              :identifier => commit['revision'],
-                              :time => Time.parse(commit_date['__content__'].to_s).localtime,
-                              :author => ((a = commit['author']) ? a['__content__'] : nil)
-                              })
-                            })
-              end
-            rescue Exception => e
-              logger.error("Error parsing svn output: #{e.message}")
-              logger.error("Output was:\n #{output}")
-            end
-          end
-          return nil if $? && $?.exitstatus != 0
-          logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug?
-          entries.sort_by_name
-        end
-
-        def properties(path, identifier=nil)
-          # proplist xml output supported in svn 1.5.0 and higher
-          return nil unless self.class.client_version_above?([1, 5, 0])
-
-          identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
-          cmd = "#{self.class.sq_bin} proplist --verbose --xml #{target(path)}@#{identifier}"
-          cmd << credentials_string
-          properties = {}
-          shellout(cmd) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
-            begin
-              doc = parse_xml(output)
-              each_xml_element(doc['properties']['target'], 'property') do |property|
-                properties[ property['name'] ] = property['__content__'].to_s
-              end
-            rescue
-            end
-          end
-          return nil if $? && $?.exitstatus != 0
-          properties
-        end
-
-        def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
-          path ||= ''
-          identifier_from = (identifier_from && identifier_from.to_i > 0) ? identifier_from.to_i : "HEAD"
-          identifier_to = (identifier_to && identifier_to.to_i > 0) ? identifier_to.to_i : 1
-          revisions = Revisions.new
-          cmd = "#{self.class.sq_bin} log --xml -r #{identifier_from}:#{identifier_to}"
-          cmd << credentials_string
-          cmd << " --verbose " if  options[:with_paths]
-          cmd << " --limit #{options[:limit].to_i}" if options[:limit]
-          cmd << ' ' + target(path)
-          shellout(cmd) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
-            begin
-              doc = parse_xml(output)
-              each_xml_element(doc['log'], 'logentry') do |logentry|
-                paths = []
-                each_xml_element(logentry['paths'], 'path') do |path|
-                  paths << {:action => path['action'],
-                            :path => path['__content__'],
-                            :from_path => path['copyfrom-path'],
-                            :from_revision => path['copyfrom-rev']
-                            }
-                end if logentry['paths'] && logentry['paths']['path']
-                paths.sort! { |x,y| x[:path] <=> y[:path] }
-
-                revisions << Revision.new({:identifier => logentry['revision'],
-                              :author => (logentry['author'] ? logentry['author']['__content__'] : ""),
-                              :time => Time.parse(logentry['date']['__content__'].to_s).localtime,
-                              :message => logentry['msg']['__content__'],
-                              :paths => paths
-                            })
-              end
-            rescue
-            end
-          end
-          return nil if $? && $?.exitstatus != 0
-          revisions
-        end
-
-        def diff(path, identifier_from, identifier_to=nil)
-          path ||= ''
-          identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : ''
-
-          identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : (identifier_from.to_i - 1)
-
-          cmd = "#{self.class.sq_bin} diff -r "
-          cmd << "#{identifier_to}:"
-          cmd << "#{identifier_from}"
-          cmd << " #{target(path)}@#{identifier_from}"
-          cmd << credentials_string
-          diff = []
-          shellout(cmd) do |io|
-            io.each_line do |line|
-              diff << line
-            end
-          end
-          return nil if $? && $?.exitstatus != 0
-          diff
-        end
-
-        def cat(path, identifier=nil)
-          identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
-          cmd = "#{self.class.sq_bin} cat #{target(path)}@#{identifier}"
-          cmd << credentials_string
-          cat = nil
-          shellout(cmd) do |io|
-            io.binmode
-            cat = io.read
-          end
-          return nil if $? && $?.exitstatus != 0
-          cat
-        end
-
-        def annotate(path, identifier=nil)
-          identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
-          cmd = "#{self.class.sq_bin} blame #{target(path)}@#{identifier}"
-          cmd << credentials_string
-          blame = Annotate.new
-          shellout(cmd) do |io|
-            io.each_line do |line|
-              next unless line =~ %r{^\s*(\d+)\s*(\S+)\s(.*)$}
-              rev = $1
-              blame.add_line($3.rstrip,
-                   Revision.new(
-                      :identifier => rev,
-                      :revision   => rev,
-                      :author     => $2.strip
-                      ))
-            end
-          end
-          return nil if $? && $?.exitstatus != 0
-          blame
-        end
-
-        private
-
-        def credentials_string
-          str = ''
-          str << " --username #{shell_quote(@login)}" unless @login.blank?
-          str << " --password #{shell_quote(@password)}" unless @login.blank? || @password.blank?
-          str << " --no-auth-cache --non-interactive"
-          str
-        end
-
-        # Helper that iterates over the child elements of a xml node
-        # MiniXml returns a hash when a single child is found
-        # or an array of hashes for multiple children
-        def each_xml_element(node, name)
-          if node && node[name]
-            if node[name].is_a?(Hash)
-              yield node[name]
-            else
-              node[name].each do |element|
-                yield element
-              end
-            end
-          end
-        end
-
-        def target(path = '')
-          base = path.match(/^\//) ? root_url : url
-          uri = "#{base}/#{path}"
-          uri = URI.escape(URI.escape(uri), '[]')
-          shell_quote(uri.gsub(/[?<>\*]/, ''))
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/da/da12c9756273b44fbd8170e245294f84a463055c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class SessionStartTest < ActionController::TestCase
-  tests AccountController
-
-  fixtures :users
-
-  def test_login_should_set_session_timestamps
-    post :login, :username => 'jsmith', :password => 'jsmith'
-    assert_response 302
-    assert_equal 2, session[:user_id]
-    assert_not_nil session[:ctime]
-    assert_not_nil session[:atime]
-  end
-end
-
-class SessionsTest < ActionController::TestCase
-  tests WelcomeController
-
-  fixtures :users
-
-  def test_atime_from_user_session_should_be_updated
-    created = 2.hours.ago.utc.to_i
-    get :index, {}, {:user_id => 2, :ctime => created, :atime => created}
-    assert_response :success
-    assert_equal created, session[:ctime]
-    assert_not_equal created, session[:atime]
-    assert session[:atime] > created
-  end
-
-  def test_user_session_should_not_be_reset_if_lifetime_and_timeout_disabled
-    with_settings :session_lifetime => '0', :session_timeout => '0' do
-      get :index, {}, {:user_id => 2}
-      assert_response :success
-    end
-  end
-
-  def test_user_session_without_ctime_should_be_reset_if_lifetime_enabled
-    with_settings :session_lifetime => '720' do
-      get :index, {}, {:user_id => 2}
-      assert_redirected_to '/login'
-    end
-  end
-
-  def test_user_session_with_expired_ctime_should_be_reset_if_lifetime_enabled
-    with_settings :session_timeout => '720' do
-      get :index, {}, {:user_id => 2, :atime => 2.days.ago.utc.to_i}
-      assert_redirected_to '/login'
-    end
-  end
-
-  def test_user_session_with_valid_ctime_should_not_be_reset_if_lifetime_enabled
-    with_settings :session_timeout => '720' do
-      get :index, {}, {:user_id => 2, :atime => 3.hours.ago.utc.to_i}
-      assert_response :success
-    end
-  end
-
-  def test_user_session_without_atime_should_be_reset_if_timeout_enabled
-    with_settings :session_timeout => '60' do
-      get :index, {}, {:user_id => 2}
-      assert_redirected_to '/login'
-    end
-  end
-
-  def test_user_session_with_expired_atime_should_be_reset_if_timeout_enabled
-    with_settings :session_timeout => '60' do
-      get :index, {}, {:user_id => 2, :atime => 4.hours.ago.utc.to_i}
-      assert_redirected_to '/login'
-    end
-  end
-
-  def test_user_session_with_valid_atime_should_not_be_reset_if_timeout_enabled
-    with_settings :session_timeout => '60' do
-      get :index, {}, {:user_id => 2, :atime => 10.minutes.ago.utc.to_i}
-      assert_response :success
-    end
-  end
-
-  def test_expired_user_session_should_be_restarted_if_autologin
-    with_settings :session_lifetime => '720', :session_timeout => '60', :autologin => 7 do
-      token = Token.create!(:user_id => 2, :action => 'autologin', :created_on => 1.day.ago)
-      @request.cookies['autologin'] = token.value
-      created = 2.hours.ago.utc.to_i
-
-      get :index, {}, {:user_id => 2, :ctime => created, :atime => created}
-      assert_equal 2, session[:user_id]
-      assert_response :success
-      assert_not_equal created, session[:ctime]
-      assert session[:ctime] >= created
-    end
-  end
-
-  def test_anonymous_session_should_not_be_reset
-    with_settings :session_lifetime => '720', :session_timeout => '60' do
-      get :index
-      assert_response :success
-    end
-  end
-end
--- a/.svn/pristine/da/da391cc28994d066c2bbb55ae6f4853a48f37175.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class GroupsControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles, :groups_users
-
-  def setup
-    @request.session[:user_id] = 1
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-  end
-
-  def test_show
-    get :show, :id => 10
-    assert_response :success
-    assert_template 'show'
-  end
-
-  def test_show_invalid_should_return_404
-    get :show, :id => 99
-    assert_response 404
-  end
-
-  def test_new
-    get :new
-    assert_response :success
-    assert_template 'new'
-    assert_select 'input[name=?]', 'group[name]'
-  end
-
-  def test_create
-    assert_difference 'Group.count' do
-      post :create, :group => {:name => 'New group'}
-    end
-    assert_redirected_to '/groups'
-    group = Group.first(:order => 'id DESC')
-    assert_equal 'New group', group.name
-    assert_equal [], group.users
-  end
-
-  def test_create_and_continue
-    assert_difference 'Group.count' do
-      post :create, :group => {:name => 'New group'}, :continue => 'Create and continue'
-    end
-    assert_redirected_to '/groups/new'
-    group = Group.first(:order => 'id DESC')
-    assert_equal 'New group', group.name
-  end
-
-  def test_create_with_failure
-    assert_no_difference 'Group.count' do
-      post :create, :group => {:name => ''}
-    end
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_edit
-    get :edit, :id => 10
-    assert_response :success
-    assert_template 'edit'
-
-    assert_select 'div#tab-content-users'
-    assert_select 'div#tab-content-memberships' do
-      assert_select 'a', :text => 'Private child of eCookbook'
-    end
-  end
-
-  def test_update
-    new_name = 'New name'
-    put :update, :id => 10, :group => {:name => new_name}
-    assert_redirected_to '/groups'
-    group = Group.find(10)
-    assert_equal new_name, group.name
-  end
-
-  def test_update_with_failure
-    put :update, :id => 10, :group => {:name => ''}
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_destroy
-    assert_difference 'Group.count', -1 do
-      post :destroy, :id => 10
-    end
-    assert_redirected_to '/groups'
-  end
-
-  def test_add_users
-    assert_difference 'Group.find(10).users.count', 2 do
-      post :add_users, :id => 10, :user_ids => ['2', '3']
-    end
-  end
-
-  def test_xhr_add_users
-    assert_difference 'Group.find(10).users.count', 2 do
-      xhr :post, :add_users, :id => 10, :user_ids => ['2', '3']
-      assert_response :success
-      assert_template 'add_users'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_match /John Smith/, response.body
-  end
-
-  def test_remove_user
-    assert_difference 'Group.find(10).users.count', -1 do
-      delete :remove_user, :id => 10, :user_id => '8'
-    end
-  end
-
-  def test_xhr_remove_user
-    assert_difference 'Group.find(10).users.count', -1 do
-      xhr :delete, :remove_user, :id => 10, :user_id => '8'
-      assert_response :success
-      assert_template 'remove_user'
-      assert_equal 'text/javascript', response.content_type
-    end
-  end
-
-  def test_new_membership
-    assert_difference 'Group.find(10).members.count' do
-      post :edit_membership, :id => 10, :membership => { :project_id => 2, :role_ids => ['1', '2']}
-    end
-  end
-
-  def test_xhr_new_membership
-    assert_difference 'Group.find(10).members.count' do
-      xhr :post, :edit_membership, :id => 10, :membership => { :project_id => 2, :role_ids => ['1', '2']}
-      assert_response :success
-      assert_template 'edit_membership'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_match /OnlineStore/, response.body
-  end
-
-  def test_xhr_new_membership_with_failure
-    assert_no_difference 'Group.find(10).members.count' do
-      xhr :post, :edit_membership, :id => 10, :membership => { :project_id => 999, :role_ids => ['1', '2']}
-      assert_response :success
-      assert_template 'edit_membership'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_match /alert/, response.body, "Alert message not sent"
-  end
-
-  def test_edit_membership
-    assert_no_difference 'Group.find(10).members.count' do
-      post :edit_membership, :id => 10, :membership_id => 6, :membership => { :role_ids => ['1', '3']}
-    end
-  end
-
-  def test_xhr_edit_membership
-    assert_no_difference 'Group.find(10).members.count' do
-      xhr :post, :edit_membership, :id => 10, :membership_id => 6, :membership => { :role_ids => ['1', '3']}
-      assert_response :success
-      assert_template 'edit_membership'
-      assert_equal 'text/javascript', response.content_type
-    end
-  end
-
-  def test_destroy_membership
-    assert_difference 'Group.find(10).members.count', -1 do
-      post :destroy_membership, :id => 10, :membership_id => 6
-    end
-  end
-
-  def test_xhr_destroy_membership
-    assert_difference 'Group.find(10).members.count', -1 do
-      xhr :post, :destroy_membership, :id => 10, :membership_id => 6
-      assert_response :success
-      assert_template 'destroy_membership'
-      assert_equal 'text/javascript', response.content_type
-    end
-  end
-
-  def test_autocomplete_for_user
-    get :autocomplete_for_user, :id => 10, :q => 'smi', :format => 'js'
-    assert_response :success
-    assert_include 'John Smith', response.body
-  end
-end
--- a/.svn/pristine/da/dabffc2fc4a60cc2c87340311e04fc75053c2695.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module GanttHelper
-
-  def gantt_zoom_link(gantt, in_or_out)
-    case in_or_out
-    when :in
-      if gantt.zoom < 4
-        link_to_content_update l(:text_zoom_in),
-          params.merge(gantt.params.merge(:zoom => (gantt.zoom + 1))),
-          :class => 'icon icon-zoom-in'
-      else
-        content_tag(:span, l(:text_zoom_in), :class => 'icon icon-zoom-in').html_safe
-      end
-
-    when :out
-      if gantt.zoom > 1
-        link_to_content_update l(:text_zoom_out),
-          params.merge(gantt.params.merge(:zoom => (gantt.zoom - 1))),
-          :class => 'icon icon-zoom-out'
-      else
-        content_tag(:span, l(:text_zoom_out), :class => 'icon icon-zoom-out').html_safe
-      end
-    end
-  end
-end
--- a/.svn/pristine/da/dad3a3fd832f92aba5ee807842c8f128fb126df0.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::ThemesTest < ActiveSupport::TestCase
-
-  def test_themes
-    themes = Redmine::Themes.themes
-    assert_kind_of Array, themes
-    assert_kind_of Redmine::Themes::Theme, themes.first
-  end
-
-  def test_rescan
-    Redmine::Themes.themes.pop
-
-    assert_difference 'Redmine::Themes.themes.size' do
-      Redmine::Themes.rescan
-    end
-  end
-
-  def test_theme_loaded
-    theme = Redmine::Themes.themes.last
-
-    assert_equal theme, Redmine::Themes.theme(theme.id)
-  end
-
-  def test_theme_loaded_without_rescan
-    theme = Redmine::Themes.themes.last
-
-    assert_equal theme, Redmine::Themes.theme(theme.id, :rescan => false)
-  end
-
-  def test_theme_not_loaded
-    theme = Redmine::Themes.themes.pop
-
-    assert_equal theme, Redmine::Themes.theme(theme.id)
-  end
-
-  def test_theme_not_loaded_without_rescan
-    theme = Redmine::Themes.themes.pop
-
-    assert_nil Redmine::Themes.theme(theme.id, :rescan => false)
-  end
-end
--- a/.svn/pristine/db/db3e656f6a1b8b9454d5de84d641938d6207efc9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class RolesController < ApplicationController
-  layout 'admin'
-
-  before_filter :require_admin, :except => [:index, :show]
-  before_filter :require_admin_or_api_request, :only => [:index, :show]
-  before_filter :find_role, :only => [:show, :edit, :update, :destroy]
-  accept_api_auth :index, :show
-
-  def index
-    respond_to do |format|
-      format.html {
-        @role_pages, @roles = paginate Role.sorted, :per_page => 25
-        render :action => "index", :layout => false if request.xhr?
-      }
-      format.api {
-        @roles = Role.givable.all
-      }
-    end
-  end
-
-  def show
-    respond_to do |format|
-      format.api
-    end
-  end
-
-  def new
-    # Prefills the form with 'Non member' role permissions by default
-    @role = Role.new(params[:role] || {:permissions => Role.non_member.permissions})
-    if params[:copy].present? && @copy_from = Role.find_by_id(params[:copy])
-      @role.copy_from(@copy_from)
-    end
-    @roles = Role.sorted.all
-  end
-
-  def create
-    @role = Role.new(params[:role])
-    if request.post? && @role.save
-      # workflow copy
-      if !params[:copy_workflow_from].blank? && (copy_from = Role.find_by_id(params[:copy_workflow_from]))
-        @role.workflow_rules.copy(copy_from)
-      end
-      flash[:notice] = l(:notice_successful_create)
-      redirect_to roles_path
-    else
-      @roles = Role.sorted.all
-      render :action => 'new'
-    end
-  end
-
-  def edit
-  end
-
-  def update
-    if request.put? and @role.update_attributes(params[:role])
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to roles_path
-    else
-      render :action => 'edit'
-    end
-  end
-
-  def destroy
-    @role.destroy
-    redirect_to roles_path
-  rescue
-    flash[:error] =  l(:error_can_not_remove_role)
-    redirect_to roles_path
-  end
-
-  def permissions
-    @roles = Role.sorted.all
-    @permissions = Redmine::AccessControl.permissions.select { |p| !p.public? }
-    if request.post?
-      @roles.each do |role|
-        role.permissions = params[:permissions][role.id.to_s]
-        role.save
-      end
-      flash[:notice] = l(:notice_successful_update)
-      redirect_to roles_path
-    end
-  end
-
-  private
-
-  def find_role
-    @role = Role.find(params[:id])
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/db/dbc74bfb5d695fe0fd5ec63c1a42442c480292e2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AuthSourcesControllerTest < ActionController::TestCase
-  fixtures :users, :auth_sources
-
-  def setup
-    @request.session[:user_id] = 1
-  end
-
-  def test_index
-    get :index
-
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:auth_sources)
-  end
-
-  def test_new
-    get :new
-
-    assert_response :success
-    assert_template 'new'
-
-    source = assigns(:auth_source)
-    assert_equal AuthSourceLdap, source.class
-    assert source.new_record?
-
-    assert_select 'form#auth_source_form' do
-      assert_select 'input[name=type][value=AuthSourceLdap]'
-      assert_select 'input[name=?]', 'auth_source[host]'
-    end
-  end
-
-  def test_new_with_invalid_type_should_respond_with_404
-    get :new, :type => 'foo'
-    assert_response 404
-  end
-
-  def test_create
-    assert_difference 'AuthSourceLdap.count' do
-      post :create, :type => 'AuthSourceLdap', :auth_source => {:name => 'Test', :host => '127.0.0.1', :port => '389', :attr_login => 'cn'}
-      assert_redirected_to '/auth_sources'
-    end
-
-    source = AuthSourceLdap.order('id DESC').first
-    assert_equal 'Test', source.name
-    assert_equal '127.0.0.1', source.host
-    assert_equal 389, source.port
-    assert_equal 'cn', source.attr_login
-  end
-
-  def test_create_with_failure
-    assert_no_difference 'AuthSourceLdap.count' do
-      post :create, :type => 'AuthSourceLdap', :auth_source => {:name => 'Test', :host => '', :port => '389', :attr_login => 'cn'}
-      assert_response :success
-      assert_template 'new'
-    end
-    assert_error_tag :content => /host can&#x27;t be blank/i
-  end
-
-  def test_edit
-    get :edit, :id => 1
-
-    assert_response :success
-    assert_template 'edit'
-
-    assert_select 'form#auth_source_form' do
-      assert_select 'input[name=?]', 'auth_source[host]'
-    end
-  end
-
-  def test_edit_should_not_contain_password
-    AuthSource.find(1).update_column :account_password, 'secret'
-
-    get :edit, :id => 1
-    assert_response :success
-    assert_select 'input[value=secret]', 0
-    assert_select 'input[name=dummy_password][value=?]', /x+/
-  end
-
-  def test_edit_invalid_should_respond_with_404
-    get :edit, :id => 99
-    assert_response 404
-  end
-
-  def test_update
-    put :update, :id => 1, :auth_source => {:name => 'Renamed', :host => '192.168.0.10', :port => '389', :attr_login => 'uid'}
-    assert_redirected_to '/auth_sources'
-
-    source = AuthSourceLdap.find(1)
-    assert_equal 'Renamed', source.name
-    assert_equal '192.168.0.10', source.host
-  end
-
-  def test_update_with_failure
-    put :update, :id => 1, :auth_source => {:name => 'Renamed', :host => '', :port => '389', :attr_login => 'uid'}
-    assert_response :success
-    assert_template 'edit'
-    assert_error_tag :content => /host can&#x27;t be blank/i
-  end
-
-  def test_destroy
-    assert_difference 'AuthSourceLdap.count', -1 do
-      delete :destroy, :id => 1
-      assert_redirected_to '/auth_sources'
-    end
-  end
-
-  def test_destroy_auth_source_in_use
-    User.find(2).update_attribute :auth_source_id, 1
-
-    assert_no_difference 'AuthSourceLdap.count' do
-      delete :destroy, :id => 1
-      assert_redirected_to '/auth_sources'
-    end
-  end
-
-  def test_test_connection
-    AuthSourceLdap.any_instance.stubs(:test_connection).returns(true)
-
-    get :test_connection, :id => 1
-    assert_redirected_to '/auth_sources'
-    assert_not_nil flash[:notice]
-    assert_match /successful/i, flash[:notice]
-  end
-
-  def test_test_connection_with_failure
-    AuthSourceLdap.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError.new("Something went wrong"))
-
-    get :test_connection, :id => 1
-    assert_redirected_to '/auth_sources'
-    assert_not_nil flash[:error]
-    assert_include 'Something went wrong', flash[:error]
-  end
-
-  def test_autocomplete_for_new_user
-    AuthSource.expects(:search).with('foo').returns([
-      {:login => 'foo1', :firstname => 'John', :lastname => 'Smith', :mail => 'foo1@example.net', :auth_source_id => 1},
-      {:login => 'Smith', :firstname => 'John', :lastname => 'Doe', :mail => 'foo2@example.net', :auth_source_id => 1}
-    ])
-
-    get :autocomplete_for_new_user, :term => 'foo'
-    assert_response :success
-    assert_equal 'application/json', response.content_type
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Array, json
-    assert_equal 2, json.size
-    assert_equal 'foo1', json.first['value']
-    assert_equal 'foo1 (John Smith)', json.first['label']
-  end
-end
--- a/.svn/pristine/dc/dc4a8b889fb60778bdec8c2aea4b6206a1ffbc41.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoryFilesystemTest < ActiveSupport::TestCase
-  fixtures :projects
-
-  include Redmine::I18n
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s
-
-  def setup
-    @project = Project.find(3)
-    Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem')
-    @repository = Repository::Filesystem.create(
-                               :project => @project,
-                               :url     => REPOSITORY_PATH
-                                 )
-    assert @repository
-  end
-
-  def test_blank_root_directory_error_message
-    set_language_if_valid 'en'
-    repo = Repository::Filesystem.new(
-                          :project      => @project,
-                          :identifier   => 'test'
-                        )
-    assert !repo.save
-    assert_include "Root directory can't be blank",
-                   repo.errors.full_messages
-  end
-
-  def test_blank_root_directory_error_message_fr
-    set_language_if_valid 'fr'
-    str = "R\xc3\xa9pertoire racine doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    repo = Repository::Filesystem.new(
-                          :project      => @project,
-                          :url          => "",
-                          :identifier   => 'test',
-                          :path_encoding => ''
-                        )
-    assert !repo.save
-    assert_include str, repo.errors.full_messages
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    def test_fetch_changesets
-      assert_equal 0, @repository.changesets.count
-      assert_equal 0, @repository.filechanges.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal 0, @repository.changesets.count
-      assert_equal 0, @repository.filechanges.count
-    end
-
-    def test_entries
-      entries = @repository.entries("", 2)
-      assert_kind_of Redmine::Scm::Adapters::Entries, entries
-      assert_equal 3, entries.size
-    end
-
-    def test_entries_in_directory
-      assert_equal 2, @repository.entries("dir", 3).size
-    end
-
-    def test_cat
-      assert_equal "TEST CAT\n", @repository.scm.cat("test")
-    end
-  else
-    puts "Filesystem test repository NOT FOUND. Skipping unit tests !!! See doc/RUNNING_TESTS."
-    def test_fake; assert true end
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/dc/dcee2e5e783bd2604aa1b1acc0ba9ac27223687a.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,92 @@
+desc "Run the Continuous Integration tests for Redmine"
+task :ci do
+  # RAILS_ENV and ENV[] can diverge so force them both to test
+  ENV['RAILS_ENV'] = 'test'
+  RAILS_ENV = 'test'
+  Rake::Task["ci:setup"].invoke
+  Rake::Task["ci:build"].invoke
+  Rake::Task["ci:teardown"].invoke
+end
+
+namespace :ci do
+  desc "Setup Redmine for a new build"
+  task :setup do
+    Rake::Task["tmp:clear"].invoke
+    Rake::Task["log:clear"].invoke
+    Rake::Task["db:create:all"].invoke
+    Rake::Task["db:migrate"].invoke
+    Rake::Task["db:schema:dump"].invoke
+    if scms = ENV['SCMS']
+      scms.split(',').each do |scm|
+        Rake::Task["test:scm:setup:#{scm}"].invoke
+      end
+    else
+      Rake::Task["test:scm:setup:all"].invoke
+    end
+    Rake::Task["test:scm:update"].invoke
+  end
+
+  desc "Build Redmine"
+  task :build do
+    if test_suite = ENV['TEST_SUITE']
+      Rake::Task["test:#{test_suite}"].invoke
+    else
+      Rake::Task["test"].invoke
+    end
+    # Rake::Task["test:ui"].invoke if RUBY_VERSION >= '1.9.3'
+  end
+
+  desc "Finish the build"
+  task :teardown do
+  end
+end
+
+desc "Creates database.yml for the CI server"
+file 'config/database.yml' do
+  require 'yaml'
+  database = ENV['DATABASE_ADAPTER']
+  ruby = ENV['RUBY_VER'].gsub('.', '').gsub('-', '')
+  branch = ENV['BRANCH'].gsub('.', '').gsub('-', '')
+  dev_db_name = "ci_#{branch}_#{ruby}_dev"
+  test_db_name = "ci_#{branch}_#{ruby}_test"
+
+  case database
+  when 'mysql'
+    dev_conf =  {'adapter' => (RUBY_VERSION >= '1.9' ? 'mysql2' : 'mysql'),
+                 'database' => dev_db_name, 'host' => 'localhost',
+                 'encoding' => 'utf8'}
+    if ENV['RUN_ON_NOT_OFFICIAL']
+      dev_conf['username'] = 'root'
+    else
+      dev_conf['username'] = 'jenkins'
+      dev_conf['password'] = 'jenkins'
+    end
+    test_conf = dev_conf.merge('database' => test_db_name)
+  when 'postgresql'
+    dev_conf =  {'adapter' => 'postgresql', 'database' => dev_db_name,
+                 'host' => 'localhost'}
+    if ENV['RUN_ON_NOT_OFFICIAL']
+      dev_conf['username'] = 'postgres'
+    else
+      dev_conf['username'] = 'jenkins'
+      dev_conf['password'] = 'jenkins'
+    end
+    test_conf = dev_conf.merge('database' => test_db_name)
+  when /sqlite3/
+    dev_conf =  {'adapter' => (Object.const_defined?(:JRUBY_VERSION) ?
+                                 'jdbcsqlite3' : 'sqlite3'),
+                 'database' => "db/#{dev_db_name}.sqlite3"}
+    test_conf = dev_conf.merge('database' => "db/#{test_db_name}.sqlite3")
+  when 'sqlserver'
+    dev_conf =  {'adapter' => 'sqlserver', 'database' => dev_db_name,
+                 'host' => 'mssqlserver', 'port' => 1433,
+                 'username' => 'jenkins', 'password' => 'jenkins'}
+    test_conf = dev_conf.merge('database' => test_db_name)
+  else
+    abort "Unknown database"
+  end
+
+  File.open('config/database.yml', 'w') do |f|
+    f.write YAML.dump({'development' => dev_conf, 'test' => test_conf})
+  end
+end
--- a/.svn/pristine/dc/dcf80e81fd95a42105f66a0a6dd9f6b600306b78.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,757 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class MailerTest < ActiveSupport::TestCase
-  include Redmine::I18n
-  include ActionDispatch::Assertions::SelectorAssertions
-  fixtures :projects, :enabled_modules, :issues, :users, :members,
-           :member_roles, :roles, :documents, :attachments, :news,
-           :tokens, :journals, :journal_details, :changesets,
-           :trackers, :projects_trackers,
-           :issue_statuses, :enumerations, :messages, :boards, :repositories,
-           :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
-           :versions,
-           :comments
-
-  def setup
-    ActionMailer::Base.deliveries.clear
-    Setting.host_name = 'mydomain.foo'
-    Setting.protocol = 'http'
-    Setting.plain_text_mail = '0'
-  end
-
-  def test_generated_links_in_emails
-    Setting.default_language = 'en'
-    Setting.host_name = 'mydomain.foo'
-    Setting.protocol = 'https'
-
-    journal = Journal.find(3)
-    assert Mailer.deliver_issue_edit(journal)
-
-    mail = last_email
-    assert_not_nil mail
-
-    assert_select_email do
-      # link to the main ticket
-      assert_select 'a[href=?]',
-                    'https://mydomain.foo/issues/2#change-3',
-                    :text => 'Feature request #2: Add ingredients categories'
-      # link to a referenced ticket
-      assert_select 'a[href=?][title=?]',
-                    'https://mydomain.foo/issues/1',
-                    'Can&#x27;t print recipes (New)',
-                    :text => '#1'
-      # link to a changeset
-      assert_select 'a[href=?][title=?]',
-                    'https://mydomain.foo/projects/ecookbook/repository/revisions/2',
-                    'This commit fixes #1, #2 and references #1 &amp; #3',
-                    :text => 'r2'
-      # link to a description diff
-      assert_select 'a[href=?][title=?]',
-                    'https://mydomain.foo/journals/diff/3?detail_id=4',
-                    'View differences',
-                    :text => 'diff'
-      # link to an attachment
-      assert_select 'a[href=?]',
-                    'https://mydomain.foo/attachments/download/4/source.rb',
-                    :text => 'source.rb'
-    end
-  end
-
-  def test_generated_links_with_prefix
-    Setting.default_language = 'en'
-    relative_url_root = Redmine::Utils.relative_url_root
-    Setting.host_name = 'mydomain.foo/rdm'
-    Setting.protocol = 'http'
-
-    journal = Journal.find(3)
-    assert Mailer.deliver_issue_edit(journal)
-
-    mail = last_email
-    assert_not_nil mail
-
-    assert_select_email do
-      # link to the main ticket
-      assert_select 'a[href=?]',
-                    'http://mydomain.foo/rdm/issues/2#change-3',
-                    :text => 'Feature request #2: Add ingredients categories'
-      # link to a referenced ticket
-      assert_select 'a[href=?][title=?]',
-                    'http://mydomain.foo/rdm/issues/1',
-                    'Can&#x27;t print recipes (New)',
-                    :text => '#1'
-      # link to a changeset
-      assert_select 'a[href=?][title=?]',
-                    'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
-                    'This commit fixes #1, #2 and references #1 &amp; #3',
-                    :text => 'r2'
-      # link to a description diff
-      assert_select 'a[href=?][title=?]',
-                    'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
-                    'View differences',
-                    :text => 'diff'
-      # link to an attachment
-      assert_select 'a[href=?]',
-                    'http://mydomain.foo/rdm/attachments/download/4/source.rb',
-                    :text => 'source.rb'
-    end
-  end
-
-  def test_issue_edit_should_generate_url_with_hostname_for_relations
-    journal = Journal.new(:journalized => Issue.find(1), :user => User.find(1), :created_on => Time.now)
-    journal.details << JournalDetail.new(:property => 'relation', :prop_key => 'label_relates_to', :value => 2)
-    Mailer.deliver_issue_edit(journal)
-    assert_not_nil last_email
-    assert_select_email do
-      assert_select 'a[href=?]', 'http://mydomain.foo/issues/2', :text => 'Feature request #2'
-    end
-  end
-
-  def test_generated_links_with_prefix_and_no_relative_url_root
-    Setting.default_language = 'en'
-    relative_url_root = Redmine::Utils.relative_url_root
-    Setting.host_name = 'mydomain.foo/rdm'
-    Setting.protocol = 'http'
-    Redmine::Utils.relative_url_root = nil
-
-    journal = Journal.find(3)
-    assert Mailer.deliver_issue_edit(journal)
-
-    mail = last_email
-    assert_not_nil mail
-
-    assert_select_email do
-      # link to the main ticket
-      assert_select 'a[href=?]',
-                    'http://mydomain.foo/rdm/issues/2#change-3',
-                    :text => 'Feature request #2: Add ingredients categories'
-      # link to a referenced ticket
-      assert_select 'a[href=?][title=?]',
-                    'http://mydomain.foo/rdm/issues/1',
-                    'Can&#x27;t print recipes (New)',
-                    :text => '#1'
-      # link to a changeset
-      assert_select 'a[href=?][title=?]',
-                    'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
-                    'This commit fixes #1, #2 and references #1 &amp; #3',
-                    :text => 'r2'
-      # link to a description diff
-      assert_select 'a[href=?][title=?]',
-                    'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
-                    'View differences',
-                    :text => 'diff'
-      # link to an attachment
-      assert_select 'a[href=?]',
-                    'http://mydomain.foo/rdm/attachments/download/4/source.rb',
-                    :text => 'source.rb'
-    end
-  ensure
-    # restore it
-    Redmine::Utils.relative_url_root = relative_url_root
-  end
-
-  def test_email_headers
-    issue = Issue.find(1)
-    Mailer.deliver_issue_add(issue)
-    mail = last_email
-    assert_not_nil mail
-    assert_equal 'OOF', mail.header['X-Auto-Response-Suppress'].to_s
-    assert_equal 'auto-generated', mail.header['Auto-Submitted'].to_s
-    assert_equal '<redmine.example.net>', mail.header['List-Id'].to_s
-  end
-
-  def test_email_headers_should_include_sender
-    issue = Issue.find(1)
-    Mailer.deliver_issue_add(issue)
-    mail = last_email
-    assert_equal issue.author.login, mail.header['X-Redmine-Sender'].to_s
-  end
-
-  def test_plain_text_mail
-    Setting.plain_text_mail = 1
-    journal = Journal.find(2)
-    Mailer.deliver_issue_edit(journal)
-    mail = last_email
-    assert_equal "text/plain; charset=UTF-8", mail.content_type
-    assert_equal 0, mail.parts.size
-    assert !mail.encoded.include?('href')
-  end
-
-  def test_html_mail
-    Setting.plain_text_mail = 0
-    journal = Journal.find(2)
-    Mailer.deliver_issue_edit(journal)
-    mail = last_email
-    assert_equal 2, mail.parts.size
-    assert mail.encoded.include?('href')
-  end
-
-  def test_from_header
-    with_settings :mail_from => 'redmine@example.net' do
-      Mailer.test_email(User.find(1)).deliver
-    end
-    mail = last_email
-    assert_equal 'redmine@example.net', mail.from_addrs.first
-  end
-
-  def test_from_header_with_phrase
-    with_settings :mail_from => 'Redmine app <redmine@example.net>' do
-      Mailer.test_email(User.find(1)).deliver
-    end
-    mail = last_email
-    assert_equal 'redmine@example.net', mail.from_addrs.first
-    assert_equal 'Redmine app <redmine@example.net>', mail.header['From'].to_s
-  end
-
-  def test_should_not_send_email_without_recipient
-    news = News.first
-    user = news.author
-    # Remove members except news author
-    news.project.memberships.each {|m| m.destroy unless m.user == user}
-
-    user.pref.no_self_notified = false
-    user.pref.save
-    User.current = user
-    Mailer.news_added(news.reload).deliver
-    assert_equal 1, last_email.bcc.size
-
-    # nobody to notify
-    user.pref.no_self_notified = true
-    user.pref.save
-    User.current = user
-    ActionMailer::Base.deliveries.clear
-    Mailer.news_added(news.reload).deliver
-    assert ActionMailer::Base.deliveries.empty?
-  end
-
-  def test_issue_add_message_id
-    issue = Issue.find(2)
-    Mailer.deliver_issue_add(issue)
-    mail = last_email
-    assert_match /^redmine\.issue-2\.20060719190421\.[a-f0-9]+@example\.net/, mail.message_id
-    assert_include "redmine.issue-2.20060719190421@example.net", mail.references
-  end
-
-  def test_issue_edit_message_id
-    journal = Journal.find(3)
-    journal.issue = Issue.find(2)
-
-    Mailer.deliver_issue_edit(journal)
-    mail = last_email
-    assert_match /^redmine\.journal-3\.\d+\.[a-f0-9]+@example\.net/, mail.message_id
-    assert_include "redmine.issue-2.20060719190421@example.net", mail.references
-    assert_select_email do
-      # link to the update
-      assert_select "a[href=?]",
-                    "http://mydomain.foo/issues/#{journal.journalized_id}#change-#{journal.id}"
-    end
-  end
-
-  def test_message_posted_message_id
-    message = Message.find(1)
-    Mailer.message_posted(message).deliver
-    mail = last_email
-    assert_match /^redmine\.message-1\.\d+\.[a-f0-9]+@example\.net/, mail.message_id
-    assert_include "redmine.message-1.20070512151532@example.net", mail.references
-    assert_select_email do
-      # link to the message
-      assert_select "a[href=?]",
-                    "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.id}",
-                    :text => message.subject
-    end
-  end
-
-  def test_reply_posted_message_id
-    message = Message.find(3)
-    Mailer.message_posted(message).deliver
-    mail = last_email
-    assert_match /^redmine\.message-3\.\d+\.[a-f0-9]+@example\.net/, mail.message_id
-    assert_include "redmine.message-1.20070512151532@example.net", mail.references
-    assert_select_email do
-      # link to the reply
-      assert_select "a[href=?]",
-                    "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.root.id}?r=#{message.id}#message-#{message.id}",
-                    :text => message.subject
-    end
-  end
-
-  test "#issue_add should notify project members" do
-    issue = Issue.find(1)
-    assert Mailer.deliver_issue_add(issue)
-    assert last_email.bcc.include?('dlopper@somenet.foo')
-  end
-
-  test "#issue_add should not notify project members that are not allow to view the issue" do
-    issue = Issue.find(1)
-    Role.find(2).remove_permission!(:view_issues)
-    assert Mailer.deliver_issue_add(issue)
-    assert !last_email.bcc.include?('dlopper@somenet.foo')
-  end
-
-  test "#issue_add should notify issue watchers" do
-    issue = Issue.find(1)
-    user = User.find(9)
-    # minimal email notification options
-    user.pref.no_self_notified = '1'
-    user.pref.save
-    user.mail_notification = false
-    user.save
-
-    Watcher.create!(:watchable => issue, :user => user)
-    assert Mailer.deliver_issue_add(issue)
-    assert last_email.bcc.include?(user.mail)
-  end
-
-  test "#issue_add should not notify watchers not allowed to view the issue" do
-    issue = Issue.find(1)
-    user = User.find(9)
-    Watcher.create!(:watchable => issue, :user => user)
-    Role.non_member.remove_permission!(:view_issues)
-    assert Mailer.deliver_issue_add(issue)
-    assert !last_email.bcc.include?(user.mail)
-  end
-
-  def test_issue_add_should_include_enabled_fields
-    Setting.default_language = 'en'
-    issue = Issue.find(2)
-    assert Mailer.deliver_issue_add(issue)
-    assert_mail_body_match '* Target version: 1.0', last_email
-    assert_select_email do
-      assert_select 'li', :text => 'Target version: 1.0'
-    end
-  end
-
-  def test_issue_add_should_not_include_disabled_fields
-    Setting.default_language = 'en'
-    issue = Issue.find(2)
-    tracker = issue.tracker
-    tracker.core_fields -= ['fixed_version_id']
-    tracker.save!
-    assert Mailer.deliver_issue_add(issue)
-    assert_mail_body_no_match 'Target version', last_email
-    assert_select_email do
-      assert_select 'li', :text => /Target version/, :count => 0
-    end
-  end
-
-  # test mailer methods for each language
-  def test_issue_add
-    issue = Issue.find(1)
-    valid_languages.each do |lang|
-      Setting.default_language = lang.to_s
-      assert Mailer.deliver_issue_add(issue)
-    end
-  end
-
-  def test_issue_edit
-    journal = Journal.find(1)
-    valid_languages.each do |lang|
-      Setting.default_language = lang.to_s
-      assert Mailer.deliver_issue_edit(journal)
-    end
-  end
-
-  def test_issue_edit_should_send_private_notes_to_users_with_permission_only
-    journal = Journal.find(1)
-    journal.private_notes = true
-    journal.save!
-
-    Role.find(2).add_permission! :view_private_notes
-    Mailer.deliver_issue_edit(journal)
-    assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
-
-    Role.find(2).remove_permission! :view_private_notes
-    Mailer.deliver_issue_edit(journal)
-    assert_equal %w(jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
-  end
-
-  def test_issue_edit_should_send_private_notes_to_watchers_with_permission_only
-    Issue.find(1).set_watcher(User.find_by_login('someone'))
-    journal = Journal.find(1)
-    journal.private_notes = true
-    journal.save!
-
-    Role.non_member.add_permission! :view_private_notes
-    Mailer.deliver_issue_edit(journal)
-    assert_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
-
-    Role.non_member.remove_permission! :view_private_notes
-    Mailer.deliver_issue_edit(journal)
-    assert_not_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
-  end
-
-  def test_issue_edit_should_mark_private_notes
-    journal = Journal.find(2)
-    journal.private_notes = true
-    journal.save!
-
-    with_settings :default_language => 'en' do
-      Mailer.deliver_issue_edit(journal)
-    end
-    assert_mail_body_match '(Private notes)', last_email
-  end
-
-  def test_issue_edit_with_relation_should_notify_users_who_can_see_the_related_issue
-    issue = Issue.generate!
-    private_issue = Issue.generate!(:is_private => true)
-    IssueRelation.create!(:issue_from => issue, :issue_to => private_issue, :relation_type => 'relates')
-    issue.reload
-    assert_equal 1, issue.journals.size
-    journal = issue.journals.first
-    ActionMailer::Base.deliveries.clear
-
-    Mailer.deliver_issue_edit(journal)
-    last_email.bcc.each do |email|
-      user = User.find_by_mail(email)
-      assert private_issue.visible?(user), "Issue was not visible to #{user}"
-    end
-  end
-
-  def test_document_added
-    document = Document.find(1)
-    valid_languages.each do |lang|
-      Setting.default_language = lang.to_s
-      assert Mailer.document_added(document).deliver
-    end
-  end
-
-  def test_attachments_added
-    attachements = [ Attachment.find_by_container_type('Document') ]
-    valid_languages.each do |lang|
-      Setting.default_language = lang.to_s
-      assert Mailer.attachments_added(attachements).deliver
-    end
-  end
-
-  def test_version_file_added
-    attachements = [ Attachment.find_by_container_type('Version') ]
-    assert Mailer.attachments_added(attachements).deliver
-    assert_not_nil last_email.bcc
-    assert last_email.bcc.any?
-    assert_select_email do
-      assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
-    end
-  end
-
-  def test_project_file_added
-    attachements = [ Attachment.find_by_container_type('Project') ]
-    assert Mailer.attachments_added(attachements).deliver
-    assert_not_nil last_email.bcc
-    assert last_email.bcc.any?
-    assert_select_email do
-      assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
-    end
-  end
-
-  def test_news_added
-    news = News.first
-    valid_languages.each do |lang|
-      Setting.default_language = lang.to_s
-      assert Mailer.news_added(news).deliver
-    end
-  end
-
-  def test_news_comment_added
-    comment = Comment.find(2)
-    valid_languages.each do |lang|
-      Setting.default_language = lang.to_s
-      assert Mailer.news_comment_added(comment).deliver
-    end
-  end
-
-  def test_message_posted
-    message = Message.first
-    recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
-    recipients = recipients.compact.uniq
-    valid_languages.each do |lang|
-      Setting.default_language = lang.to_s
-      assert Mailer.message_posted(message).deliver
-    end
-  end
-
-  def test_wiki_content_added
-    content = WikiContent.find(1)
-    valid_languages.each do |lang|
-      Setting.default_language = lang.to_s
-      assert_difference 'ActionMailer::Base.deliveries.size' do
-        assert Mailer.wiki_content_added(content).deliver
-        assert_select_email do
-          assert_select 'a[href=?]',
-            'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
-            :text => 'CookBook documentation'
-        end
-      end
-    end
-  end
-
-  def test_wiki_content_updated
-    content = WikiContent.find(1)
-    valid_languages.each do |lang|
-      Setting.default_language = lang.to_s
-      assert_difference 'ActionMailer::Base.deliveries.size' do
-        assert Mailer.wiki_content_updated(content).deliver
-        assert_select_email do
-          assert_select 'a[href=?]',
-            'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
-            :text => 'CookBook documentation'
-        end
-      end
-    end
-  end
-
-  def test_account_information
-    user = User.find(2)
-    valid_languages.each do |lang|
-      user.update_attribute :language, lang.to_s
-      user.reload
-      assert Mailer.account_information(user, 'pAsswORd').deliver
-    end
-  end
-
-  def test_lost_password
-    token = Token.find(2)
-    valid_languages.each do |lang|
-      token.user.update_attribute :language, lang.to_s
-      token.reload
-      assert Mailer.lost_password(token).deliver
-    end
-  end
-
-  def test_register
-    token = Token.find(1)
-    Setting.host_name = 'redmine.foo'
-    Setting.protocol = 'https'
-
-    valid_languages.each do |lang|
-      token.user.update_attribute :language, lang.to_s
-      token.reload
-      ActionMailer::Base.deliveries.clear
-      assert Mailer.register(token).deliver
-      mail = last_email
-      assert_select_email do
-        assert_select "a[href=?]",
-                      "https://redmine.foo/account/activate?token=#{token.value}",
-                      :text => "https://redmine.foo/account/activate?token=#{token.value}"
-      end
-    end
-  end
-
-  def test_test
-    user = User.find(1)
-    valid_languages.each do |lang|
-      user.update_attribute :language, lang.to_s
-      assert Mailer.test_email(user).deliver
-    end
-  end
-
-  def test_reminders
-    Mailer.reminders(:days => 42)
-    assert_equal 1, ActionMailer::Base.deliveries.size
-    mail = last_email
-    assert mail.bcc.include?('dlopper@somenet.foo')
-    assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
-    assert_equal '1 issue(s) due in the next 42 days', mail.subject
-  end
-
-  def test_reminders_should_not_include_closed_issues
-    with_settings :default_language => 'en' do
-      Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5,
-                      :subject => 'Closed issue', :assigned_to_id => 3,
-                      :due_date => 5.days.from_now,
-                      :author_id => 2)
-      ActionMailer::Base.deliveries.clear
-
-      Mailer.reminders(:days => 42)
-      assert_equal 1, ActionMailer::Base.deliveries.size
-      mail = last_email
-      assert mail.bcc.include?('dlopper@somenet.foo')
-      assert_mail_body_no_match 'Closed issue', mail
-    end
-  end
-
-  def test_reminders_for_users
-    Mailer.reminders(:days => 42, :users => ['5'])
-    assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
-    Mailer.reminders(:days => 42, :users => ['3'])
-    assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
-    mail = last_email
-    assert mail.bcc.include?('dlopper@somenet.foo')
-    assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
-  end
-
-  def test_reminder_should_include_issues_assigned_to_groups
-    with_settings :default_language => 'en' do
-      group = Group.generate!
-      group.users << User.find(2)
-      group.users << User.find(3)
-
-      Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
-                      :subject => 'Assigned to group', :assigned_to => group,
-                      :due_date => 5.days.from_now,
-                      :author_id => 2)
-      ActionMailer::Base.deliveries.clear
-
-      Mailer.reminders(:days => 7)
-      assert_equal 2, ActionMailer::Base.deliveries.size
-      assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.map(&:bcc).flatten.sort
-      ActionMailer::Base.deliveries.each do |mail|
-        assert_mail_body_match 'Assigned to group', mail
-      end
-    end
-  end
-
-  def test_mailer_should_not_change_locale
-    Setting.default_language = 'en'
-    # Set current language to italian
-    set_language_if_valid 'it'
-    # Send an email to a french user
-    user = User.find(1)
-    user.language = 'fr'
-    Mailer.account_activated(user).deliver
-    mail = last_email
-    assert_mail_body_match 'Votre compte', mail
-
-    assert_equal :it, current_language
-  end
-
-  def test_with_deliveries_off
-    Mailer.with_deliveries false do
-      Mailer.test_email(User.find(1)).deliver
-    end
-    assert ActionMailer::Base.deliveries.empty?
-    # should restore perform_deliveries
-    assert ActionMailer::Base.perform_deliveries
-  end
-
-  def test_layout_should_include_the_emails_header
-    with_settings :emails_header => "*Header content*" do
-      with_settings :plain_text_mail => 0 do
-        assert Mailer.test_email(User.find(1)).deliver
-        assert_select_email do
-          assert_select ".header" do
-            assert_select "strong", :text => "Header content"
-          end
-        end
-      end
-      with_settings :plain_text_mail => 1 do
-        assert Mailer.test_email(User.find(1)).deliver
-        mail = last_email
-        assert_not_nil mail
-        assert_include "*Header content*", mail.body.decoded
-      end
-    end
-  end
-
-  def test_layout_should_not_include_empty_emails_header
-    with_settings :emails_header => "", :plain_text_mail => 0 do
-      assert Mailer.test_email(User.find(1)).deliver
-      assert_select_email do
-        assert_select ".header", false
-      end
-    end
-  end
-
-  def test_layout_should_include_the_emails_footer
-    with_settings :emails_footer => "*Footer content*" do
-      with_settings :plain_text_mail => 0 do
-        assert Mailer.test_email(User.find(1)).deliver
-        assert_select_email do
-          assert_select ".footer" do
-            assert_select "strong", :text => "Footer content"
-          end
-        end
-      end
-      with_settings :plain_text_mail => 1 do
-        assert Mailer.test_email(User.find(1)).deliver
-        mail = last_email
-        assert_not_nil mail
-        assert_include "\n-- \n", mail.body.decoded
-        assert_include "*Footer content*", mail.body.decoded
-      end
-    end
-  end
-
-  def test_layout_should_not_include_empty_emails_footer
-    with_settings :emails_footer => "" do
-      with_settings :plain_text_mail => 0 do
-        assert Mailer.test_email(User.find(1)).deliver
-        assert_select_email do
-          assert_select ".footer", false
-        end
-      end
-      with_settings :plain_text_mail => 1 do
-        assert Mailer.test_email(User.find(1)).deliver
-        mail = last_email
-        assert_not_nil mail
-        assert_not_include "\n-- \n", mail.body.decoded
-      end
-    end
-  end
-
-  def test_should_escape_html_templates_only
-    Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Subject with a <tag>')
-    mail = last_email
-    assert_equal 2, mail.parts.size
-    assert_include '<tag>', text_part.body.encoded
-    assert_include '&lt;tag&gt;', html_part.body.encoded
-  end
-
-  def test_should_raise_delivery_errors_when_raise_delivery_errors_is_true
-    mail = Mailer.test_email(User.find(1))
-    mail.delivery_method.stubs(:deliver!).raises(Exception.new("delivery error"))
-
-    ActionMailer::Base.raise_delivery_errors = true
-    assert_raise Exception, "delivery error" do
-      mail.deliver
-    end
-  ensure
-    ActionMailer::Base.raise_delivery_errors = false
-  end
-
-  def test_should_log_delivery_errors_when_raise_delivery_errors_is_false
-    mail = Mailer.test_email(User.find(1))
-    mail.delivery_method.stubs(:deliver!).raises(Exception.new("delivery error"))
-
-    Rails.logger.expects(:error).with("Email delivery error: delivery error")
-    ActionMailer::Base.raise_delivery_errors = false
-    assert_nothing_raised do
-      mail.deliver
-    end
-  end
-
-  def test_mail_should_return_a_mail_message
-    assert_kind_of ::Mail::Message, Mailer.test_email(User.find(1))
-  end
-
-  private
-
-  def last_email
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    mail
-  end
-
-  def text_part
-    last_email.parts.detect {|part| part.content_type.include?('text/plain')}
-  end
-
-  def html_part
-    last_email.parts.detect {|part| part.content_type.include?('text/html')}
-  end
-end
--- a/.svn/pristine/dd/dd03dd82c04080c4766fa34cc74013a6e6a961c3.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::QueriesTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :queries
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /queries.xml should return queries" do
-    get '/queries.xml'
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'queries',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'query',
-        :child => {
-          :tag => 'id',
-          :content => '4',
-          :sibling => {
-            :tag => 'name',
-            :content => 'Public query for all projects'
-          }
-        }
-      }
-  end
-end
--- a/.svn/pristine/dd/dd4d40b7c92af3319303c89259cc7a21a900ab6b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class ApplicationHelperTest < ActionView::TestCase
-  include Redmine::Pagination::Helper
-
-  def test_per_page_options_should_return_usefull_values
-    with_settings :per_page_options => '10, 25, 50, 100' do
-      assert_equal [], per_page_options(10, 3)
-      assert_equal [], per_page_options(25, 3)
-      assert_equal [10, 25], per_page_options(10, 22)
-      assert_equal [10, 25], per_page_options(25, 22)
-      assert_equal [10, 25, 50], per_page_options(50, 22)
-      assert_equal [10, 25, 50], per_page_options(25, 26)
-      assert_equal [10, 25, 50, 100], per_page_options(25, 120)
-    end
-  end
-end
--- a/.svn/pristine/dd/dd9453d0bf7ef7086f723475ae286725a241d719.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-= Redmine
-
-Redmine is a flexible project management web application written using Ruby on Rails framework.
-
-More details can be found at http://www.redmine.org
-
-= License
-
-Copyright (C) 2006-2013  Jean-Philippe Lang
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-Icons credits:
-
-* Mark James (Silk Icons) licensed under a Creative Commons Attribution 2.5 License.
-* Yusuke Kamiyamane (Fugue Icons) licensed under a Creative Commons Attribution 3.0 License.
--- a/.svn/pristine/de/de33a6eb951226489a34da09937a4a47913b07fb.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class NewsControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :news, :comments
-
-  def setup
-    User.current = nil
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:newss)
-    assert_nil assigns(:project)
-  end
-
-  def test_index_with_project
-    get :index, :project_id => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:newss)
-  end
-
-  def test_index_with_invalid_project_should_respond_with_404
-    get :index, :project_id => 999
-    assert_response 404
-  end
-
-  def test_show
-    get :show, :id => 1
-    assert_response :success
-    assert_template 'show'
-    assert_tag :tag => 'h2', :content => /eCookbook first release/
-  end
-
-  def test_show_should_show_attachments
-    attachment = Attachment.first
-    attachment.container = News.find(1)
-    attachment.save!
-
-    get :show, :id => 1
-    assert_response :success
-    assert_tag 'a', :content => attachment.filename
-  end
-
-  def test_show_not_found
-    get :show, :id => 999
-    assert_response 404
-  end
-
-  def test_get_new
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_post_create
-    ActionMailer::Base.deliveries.clear
-    @request.session[:user_id] = 2
-
-    with_settings :notified_events => %w(news_added) do
-      post :create, :project_id => 1, :news => { :title => 'NewsControllerTest',
-                                            :description => 'This is the description',
-                                            :summary => '' }
-    end
-    assert_redirected_to '/projects/ecookbook/news'
-
-    news = News.find_by_title('NewsControllerTest')
-    assert_not_nil news
-    assert_equal 'This is the description', news.description
-    assert_equal User.find(2), news.author
-    assert_equal Project.find(1), news.project
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_post_create_with_attachment
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-    assert_difference 'News.count' do
-      assert_difference 'Attachment.count' do
-        post :create, :project_id => 1,
-          :news => { :title => 'Test', :description => 'This is the description' },
-          :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
-      end
-    end
-    attachment = Attachment.first(:order => 'id DESC')
-    news = News.first(:order => 'id DESC')
-    assert_equal news, attachment.container
-  end
-
-  def test_post_create_with_validation_failure
-    @request.session[:user_id] = 2
-    post :create, :project_id => 1, :news => { :title => '',
-                                            :description => 'This is the description',
-                                            :summary => '' }
-    assert_response :success
-    assert_template 'new'
-    assert_not_nil assigns(:news)
-    assert assigns(:news).new_record?
-    assert_error_tag :content => /title can&#x27;t be blank/i
-  end
-
-  def test_get_edit
-    @request.session[:user_id] = 2
-    get :edit, :id => 1
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_put_update
-    @request.session[:user_id] = 2
-    put :update, :id => 1, :news => { :description => 'Description changed by test_post_edit' }
-    assert_redirected_to '/news/1'
-    news = News.find(1)
-    assert_equal 'Description changed by test_post_edit', news.description
-  end
-
-  def test_put_update_with_attachment
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-    assert_no_difference 'News.count' do
-      assert_difference 'Attachment.count' do
-        put :update, :id => 1,
-          :news => { :description => 'This is the description' },
-          :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
-      end
-    end
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_equal News.find(1), attachment.container
-  end
-
-  def test_update_with_failure
-    @request.session[:user_id] = 2
-    put :update, :id => 1, :news => { :description => '' }
-    assert_response :success
-    assert_template 'edit'
-    assert_error_tag :content => /description can&#x27;t be blank/i
-  end
-
-  def test_destroy
-    @request.session[:user_id] = 2
-    delete :destroy, :id => 1
-    assert_redirected_to '/projects/ecookbook/news'
-    assert_nil News.find_by_id(1)
-  end
-end
--- a/.svn/pristine/df/df9bbf954b4f906004aaa967b48274754ad6dcd0.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'net/ldap'
-require 'net/ldap/dn'
-require 'timeout'
-
-class AuthSourceLdap < AuthSource
-  validates_presence_of :host, :port, :attr_login
-  validates_length_of :name, :host, :maximum => 60, :allow_nil => true
-  validates_length_of :account, :account_password, :base_dn, :filter, :maximum => 255, :allow_blank => true
-  validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
-  validates_numericality_of :port, :only_integer => true
-  validates_numericality_of :timeout, :only_integer => true, :allow_blank => true
-  validate :validate_filter
-
-  before_validation :strip_ldap_attributes
-
-  def initialize(attributes=nil, *args)
-    super
-    self.port = 389 if self.port == 0
-  end
-
-  def authenticate(login, password)
-    return nil if login.blank? || password.blank?
-
-    with_timeout do
-      attrs = get_user_dn(login, password)
-      if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password)
-        logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
-        return attrs.except(:dn)
-      end
-    end
-  rescue Net::LDAP::LdapError => e
-    raise AuthSourceException.new(e.message)
-  end
-
-  # test the connection to the LDAP
-  def test_connection
-    with_timeout do
-      ldap_con = initialize_ldap_con(self.account, self.account_password)
-      ldap_con.open { }
-    end
-  rescue Net::LDAP::LdapError => e
-    raise AuthSourceException.new(e.message)
-  end
-
-  def auth_method_name
-    "LDAP"
-  end
-
-  # Returns true if this source can be searched for users
-  def searchable?
-    !account.to_s.include?("$login") && %w(login firstname lastname mail).all? {|a| send("attr_#{a}?")}
-  end
-
-  # Searches the source for users and returns an array of results
-  def search(q)
-    q = q.to_s.strip
-    return [] unless searchable? && q.present?
-
-    results = []
-    search_filter = base_filter & Net::LDAP::Filter.begins(self.attr_login, q)
-    ldap_con = initialize_ldap_con(self.account, self.account_password)
-    ldap_con.search(:base => self.base_dn,
-                    :filter => search_filter,
-                    :attributes => ['dn', self.attr_login, self.attr_firstname, self.attr_lastname, self.attr_mail],
-                    :size => 10) do |entry|
-      attrs = get_user_attributes_from_ldap_entry(entry)
-      attrs[:login] = AuthSourceLdap.get_attr(entry, self.attr_login)
-      results << attrs
-    end
-    results
-  rescue Net::LDAP::LdapError => e
-    raise AuthSourceException.new(e.message)
-  end
-
-  private
-
-  def with_timeout(&block)
-    timeout = self.timeout
-    timeout = 20 unless timeout && timeout > 0
-    Timeout.timeout(timeout) do
-      return yield
-    end
-  rescue Timeout::Error => e
-    raise AuthSourceTimeoutException.new(e.message)
-  end
-
-  def ldap_filter
-    if filter.present?
-      Net::LDAP::Filter.construct(filter)
-    end
-  rescue Net::LDAP::LdapError
-    nil
-  end
-
-  def base_filter
-    filter = Net::LDAP::Filter.eq("objectClass", "*")
-    if f = ldap_filter
-      filter = filter & f
-    end
-    filter
-  end
-
-  def validate_filter
-    if filter.present? && ldap_filter.nil?
-      errors.add(:filter, :invalid)
-    end
-  end
-
-  def strip_ldap_attributes
-    [:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr|
-      write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil?
-    end
-  end
-
-  def initialize_ldap_con(ldap_user, ldap_password)
-    options = { :host => self.host,
-                :port => self.port,
-                :encryption => (self.tls ? :simple_tls : nil)
-              }
-    options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
-    Net::LDAP.new options
-  end
-
-  def get_user_attributes_from_ldap_entry(entry)
-    {
-     :dn => entry.dn,
-     :firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
-     :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
-     :mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
-     :auth_source_id => self.id
-    }
-  end
-
-  # Return the attributes needed for the LDAP search.  It will only
-  # include the user attributes if on-the-fly registration is enabled
-  def search_attributes
-    if onthefly_register?
-      ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]
-    else
-      ['dn']
-    end
-  end
-
-  # Check if a DN (user record) authenticates with the password
-  def authenticate_dn(dn, password)
-    if dn.present? && password.present?
-      initialize_ldap_con(dn, password).bind
-    end
-  end
-
-  # Get the user's dn and any attributes for them, given their login
-  def get_user_dn(login, password)
-    ldap_con = nil
-    if self.account && self.account.include?("$login")
-      ldap_con = initialize_ldap_con(self.account.sub("$login", Net::LDAP::DN.escape(login)), password)
-    else
-      ldap_con = initialize_ldap_con(self.account, self.account_password)
-    end
-    attrs = {}
-    search_filter = base_filter & Net::LDAP::Filter.eq(self.attr_login, login)
-
-    ldap_con.search( :base => self.base_dn,
-                     :filter => search_filter,
-                     :attributes=> search_attributes) do |entry|
-
-      if onthefly_register?
-        attrs = get_user_attributes_from_ldap_entry(entry)
-      else
-        attrs = {:dn => entry.dn}
-      end
-
-      logger.debug "DN found for #{login}: #{attrs[:dn]}" if logger && logger.debug?
-    end
-
-    attrs
-  end
-
-  def self.get_attr(entry, attr_name)
-    if !attr_name.blank?
-      entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
-    end
-  end
-end
--- a/.svn/pristine/df/dfa4eb7ba7d6caceff9151c99aedb512ffa84738.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class EnabledModule < ActiveRecord::Base
-  belongs_to :project
-
-  validates_presence_of :name
-  validates_uniqueness_of :name, :scope => :project_id
-
-  after_create :module_enabled
-
-  private
-
-  # after_create callback used to do things when a module is enabled
-  def module_enabled
-    case name
-    when 'wiki'
-      # Create a wiki with a default start page
-      if project && project.wiki.nil?
-        Wiki.create(:project => project, :start_page => 'Wiki')
-      end
-    end
-  end
-end
--- a/.svn/pristine/e0/e0146f52672bac410fabc231692b8f39edc8e101.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/scm/adapters/mercurial_adapter'
-
-class Repository::Mercurial < Repository
-  # sort changesets by revision number
-  has_many :changesets,
-           :order       => "#{Changeset.table_name}.id DESC",
-           :foreign_key => 'repository_id'
-
-  attr_protected        :root_url
-  validates_presence_of :url
-
-  # number of changesets to fetch at once
-  FETCH_AT_ONCE = 100
-
-  def self.human_attribute_name(attribute_key_name, *args)
-    attr_name = attribute_key_name.to_s
-    if attr_name == "url"
-      attr_name = "path_to_repository"
-    end
-    super(attr_name, *args)
-  end
-
-  def self.scm_adapter_class
-    Redmine::Scm::Adapters::MercurialAdapter
-  end
-
-  def self.scm_name
-    'Mercurial'
-  end
-
-  def supports_directory_revisions?
-    true
-  end
-
-  def supports_revision_graph?
-    true
-  end
-
-  def repo_log_encoding
-    'UTF-8'
-  end
-
-  # Returns the readable identifier for the given mercurial changeset
-  def self.format_changeset_identifier(changeset)
-    "#{changeset.revision}:#{changeset.scmid}"
-  end
-
-  # Returns the identifier for the given Mercurial changeset
-  def self.changeset_identifier(changeset)
-    changeset.scmid
-  end
-
-  def diff_format_revisions(cs, cs_to, sep=':')
-    super(cs, cs_to, ' ')
-  end
-
-  # Finds and returns a revision with a number or the beginning of a hash
-  def find_changeset_by_name(name)
-    return nil if name.blank?
-    s = name.to_s
-    if /[^\d]/ =~ s or s.size > 8
-      cs = changesets.where(:scmid => s).first
-    else
-      cs = changesets.where(:revision => s).first
-    end
-    return cs if cs
-    changesets.where('scmid LIKE ?', "#{s}%").first
-  end
-
-  # Returns the latest changesets for +path+; sorted by revision number
-  #
-  # Because :order => 'id DESC' is defined at 'has_many',
-  # there is no need to set 'order'.
-  # But, MySQL test fails.
-  # Sqlite3 and PostgreSQL pass.
-  # Is this MySQL bug?
-  def latest_changesets(path, rev, limit=10)
-    changesets.
-      includes(:user).
-      where(latest_changesets_cond(path, rev, limit)).
-      limit(limit).
-      order("#{Changeset.table_name}.id DESC").
-      all
-  end
-
-  def latest_changesets_cond(path, rev, limit)
-    cond, args = [], []
-    if scm.branchmap.member? rev
-      # Mercurial named branch is *stable* in each revision.
-      # So, named branch can be stored in database.
-      # Mercurial provides *bookmark* which is equivalent with git branch.
-      # But, bookmark is not implemented.
-      cond << "#{Changeset.table_name}.scmid IN (?)"
-      # Revisions in root directory and sub directory are not equal.
-      # So, in order to get correct limit, we need to get all revisions.
-      # But, it is very heavy.
-      # Mercurial does not treat direcotry.
-      # So, "hg log DIR" is very heavy.
-      branch_limit = path.blank? ? limit : ( limit * 5 )
-      args << scm.nodes_in_branch(rev, :limit => branch_limit)
-    elsif last = rev ? find_changeset_by_name(scm.tagmap[rev] || rev) : nil
-      cond << "#{Changeset.table_name}.id <= ?"
-      args << last.id
-    end
-    unless path.blank?
-      cond << "EXISTS (SELECT * FROM #{Change.table_name}
-                 WHERE #{Change.table_name}.changeset_id = #{Changeset.table_name}.id
-                 AND (#{Change.table_name}.path = ?
-                       OR #{Change.table_name}.path LIKE ? ESCAPE ?))"
-      args << path.with_leading_slash
-      args << "#{path.with_leading_slash.gsub(%r{[%_\\]}) { |s| "\\#{s}" }}/%" << '\\'
-    end
-    [cond.join(' AND '), *args] unless cond.empty?
-  end
-  private :latest_changesets_cond
-
-  def fetch_changesets
-    return if scm.info.nil?
-    scm_rev = scm.info.lastrev.revision.to_i
-    db_rev  = latest_changeset ? latest_changeset.revision.to_i : -1
-    return unless db_rev < scm_rev  # already up-to-date
-
-    logger.debug "Fetching changesets for repository #{url}" if logger
-    (db_rev + 1).step(scm_rev, FETCH_AT_ONCE) do |i|
-      scm.each_revision('', i, [i + FETCH_AT_ONCE - 1, scm_rev].min) do |re|
-        transaction do
-          parents = (re.parents || []).collect{|rp| find_changeset_by_name(rp)}.compact
-          cs = Changeset.create(:repository   => self,
-                                :revision     => re.revision,
-                                :scmid        => re.scmid,
-                                :committer    => re.author,
-                                :committed_on => re.time,
-                                :comments     => re.message,
-                                :parents      => parents)
-          unless cs.new_record?
-            re.paths.each { |e| cs.create_change(e) }
-          end
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/e0/e08b9f438981155ffc0c3a70e9b878dc891b06d2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingIssueCategoriesTest < ActionController::IntegrationTest
-  def test_issue_categories_scoped_under_project
-    assert_routing(
-        { :method => 'get', :path => "/projects/foo/issue_categories" },
-        { :controller => 'issue_categories', :action => 'index',
-          :project_id => 'foo' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/foo/issue_categories.xml" },
-        { :controller => 'issue_categories', :action => 'index',
-          :project_id => 'foo', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/foo/issue_categories.json" },
-        { :controller => 'issue_categories', :action => 'index',
-          :project_id => 'foo', :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/foo/issue_categories/new" },
-        { :controller => 'issue_categories', :action => 'new',
-          :project_id => 'foo' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/foo/issue_categories" },
-        { :controller => 'issue_categories', :action => 'create',
-          :project_id => 'foo' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/foo/issue_categories.xml" },
-        { :controller => 'issue_categories', :action => 'create',
-          :project_id => 'foo', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/foo/issue_categories.json" },
-        { :controller => 'issue_categories', :action => 'create',
-          :project_id => 'foo', :format => 'json' }
-      )
-  end
-
-  def test_issue_categories
-    assert_routing(
-        { :method => 'get', :path => "/issue_categories/1" },
-        { :controller => 'issue_categories', :action => 'show', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issue_categories/1.xml" },
-        { :controller => 'issue_categories', :action => 'show', :id => '1',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issue_categories/1.json" },
-        { :controller => 'issue_categories', :action => 'show', :id => '1',
-          :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issue_categories/1/edit" },
-        { :controller => 'issue_categories', :action => 'edit', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/issue_categories/1" },
-        { :controller => 'issue_categories', :action => 'update', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/issue_categories/1.xml" },
-        { :controller => 'issue_categories', :action => 'update', :id => '1',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/issue_categories/1.json" },
-        { :controller => 'issue_categories', :action => 'update', :id => '1',
-          :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/issue_categories/1" },
-        { :controller => 'issue_categories', :action => 'destroy', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/issue_categories/1.xml" },
-        { :controller => 'issue_categories', :action => 'destroy', :id => '1',
-          :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/issue_categories/1.json" },
-        { :controller => 'issue_categories', :action => 'destroy', :id => '1',
-          :format => 'json' }
-      )
-  end
-end
--- a/.svn/pristine/e0/e09af230a1244dd904e00eb402f9ad5ad77a9fd1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class HookTest < ActionController::IntegrationTest
-  fixtures :users, :roles, :projects, :members, :member_roles
-
-  # Hooks that are manually registered later
-  class ProjectBasedTemplate < Redmine::Hook::ViewListener
-    def view_layouts_base_html_head(context)
-      # Adds a project stylesheet
-      stylesheet_link_tag(context[:project].identifier) if context[:project]
-    end
-  end
-
-  class SidebarContent < Redmine::Hook::ViewListener
-    def view_layouts_base_sidebar(context)
-      content_tag('p', 'Sidebar hook')
-    end
-  end
-
-  class ContentForInsideHook < Redmine::Hook::ViewListener
-    render_on :view_welcome_index_left, :inline => <<-VIEW
-<% content_for :header_tags do %>
-  <%= javascript_include_tag 'test_plugin.js', :plugin => 'test_plugin' %>
-  <%= stylesheet_link_tag 'test_plugin.css', :plugin => 'test_plugin' %>
-<% end %>
-
-<p>ContentForInsideHook content</p>
-VIEW
-  end
-
-  def setup
-    Redmine::Hook.clear_listeners
-  end
-
-  def teardown
-    Redmine::Hook.clear_listeners
-  end
-
-  def test_html_head_hook_response
-    Redmine::Hook.add_listener(ProjectBasedTemplate)
-
-    get '/projects/ecookbook'
-    assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
-                               :parent => {:tag => 'head'}
-  end
-
-  def test_empty_sidebar_should_be_hidden
-    get '/'
-    assert_select 'div#main.nosidebar'
-  end
-
-  def test_sidebar_with_hook_content_should_not_be_hidden
-    Redmine::Hook.add_listener(SidebarContent)
-
-    get '/'
-    assert_select 'div#sidebar p', :text => 'Sidebar hook'
-    assert_select 'div#main'
-    assert_select 'div#main.nosidebar', 0
-  end
-
-  def test_hook_with_content_for_should_append_content
-    Redmine::Hook.add_listener(ContentForInsideHook)
-
-    get '/'
-    assert_response :success
-    assert_select 'p', :text => 'ContentForInsideHook content'
-    assert_select 'head' do
-      assert_select 'script[src=/plugin_assets/test_plugin/javascripts/test_plugin.js]'
-      assert_select 'link[href=/plugin_assets/test_plugin/stylesheets/test_plugin.css]'
-    end
-  end
-end
--- a/.svn/pristine/e1/e14ce008ab63fe1ed2c0583cdc8dd554192dcfe1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class AttachmentsController < ApplicationController
-  before_filter :find_project, :except => :upload
-  before_filter :file_readable, :read_authorize, :only => [:show, :download, :thumbnail]
-  before_filter :delete_authorize, :only => :destroy
-  before_filter :authorize_global, :only => :upload
-
-  accept_api_auth :show, :download, :upload
-
-  def show
-    respond_to do |format|
-      format.html {
-        if @attachment.is_diff?
-          @diff = File.new(@attachment.diskfile, "rb").read
-          @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
-          @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
-          # Save diff type as user preference
-          if User.current.logged? && @diff_type != User.current.pref[:diff_type]
-            User.current.pref[:diff_type] = @diff_type
-            User.current.preference.save
-          end
-          render :action => 'diff'
-        elsif @attachment.is_text? && @attachment.filesize <= Setting.file_max_size_displayed.to_i.kilobyte
-          @content = File.new(@attachment.diskfile, "rb").read
-          render :action => 'file'
-        else
-          download
-        end
-      }
-      format.api
-    end
-  end
-
-  def download
-    if @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project)
-      @attachment.increment_download
-    end
-
-    if stale?(:etag => @attachment.digest)
-      # images are sent inline
-      send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
-                                      :type => detect_content_type(@attachment),
-                                      :disposition => (@attachment.image? ? 'inline' : 'attachment')
-    end
-  end
-
-  def thumbnail
-    if @attachment.thumbnailable? && thumbnail = @attachment.thumbnail(:size => params[:size])
-      if stale?(:etag => thumbnail)
-        send_file thumbnail,
-          :filename => filename_for_content_disposition(@attachment.filename),
-          :type => detect_content_type(@attachment),
-          :disposition => 'inline'
-      end
-    else
-      # No thumbnail for the attachment or thumbnail could not be created
-      render :nothing => true, :status => 404
-    end
-  end
-
-  def upload
-    # Make sure that API users get used to set this content type
-    # as it won't trigger Rails' automatic parsing of the request body for parameters
-    unless request.content_type == 'application/octet-stream'
-      render :nothing => true, :status => 406
-      return
-    end
-
-    @attachment = Attachment.new(:file => request.raw_post)
-    @attachment.author = User.current
-    @attachment.filename = params[:filename].presence || Redmine::Utils.random_hex(16)
-    saved = @attachment.save
-
-    respond_to do |format|
-      format.js
-      format.api {
-        if saved
-          render :action => 'upload', :status => :created
-        else
-          render_validation_errors(@attachment)
-        end
-      }
-    end
-  end
-
-  def destroy
-    if @attachment.container.respond_to?(:init_journal)
-      @attachment.container.init_journal(User.current)
-    end
-    if @attachment.container
-      # Make sure association callbacks are called
-      @attachment.container.attachments.delete(@attachment)
-    else
-      @attachment.destroy
-    end
-
-    respond_to do |format|
-      format.html { redirect_to_referer_or project_path(@project) }
-      format.js
-    end
-  end
-
-private
-  def find_project
-    @attachment = Attachment.find(params[:id])
-    # Show 404 if the filename in the url is wrong
-    raise ActiveRecord::RecordNotFound if params[:filename] && params[:filename] != @attachment.filename
-    @project = @attachment.project
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  # Checks that the file exists and is readable
-  def file_readable
-    if @attachment.readable?
-      true
-    else
-      logger.error "Cannot send attachment, #{@attachment.diskfile} does not exist or is unreadable."
-      render_404
-    end
-  end
-
-  def read_authorize
-    @attachment.visible? ? true : deny_access
-  end
-
-  def delete_authorize
-    @attachment.deletable? ? true : deny_access
-  end
-
-  def detect_content_type(attachment)
-    content_type = attachment.content_type
-    if content_type.blank?
-      content_type = Redmine::MimeType.of(attachment.filename)
-    end
-    content_type.to_s
-  end
-end
--- a/.svn/pristine/e1/e170cc478b88d5ba7f1f49c3d7b9996c36309faf.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingAttachmentsTest < ActionController::IntegrationTest
-  def test_attachments
-    assert_routing(
-           { :method => 'get', :path => "/attachments/1" },
-           { :controller => 'attachments', :action => 'show', :id => '1' }
-         )
-    assert_routing(
-           { :method => 'get', :path => "/attachments/1.xml" },
-           { :controller => 'attachments', :action => 'show', :id => '1', :format => 'xml' }
-         )
-    assert_routing(
-           { :method => 'get', :path => "/attachments/1.json" },
-           { :controller => 'attachments', :action => 'show', :id => '1', :format => 'json' }
-         )
-    assert_routing(
-           { :method => 'get', :path => "/attachments/1/filename.ext" },
-           { :controller => 'attachments', :action => 'show', :id => '1',
-             :filename => 'filename.ext' }
-         )
-    assert_routing(
-           { :method => 'get', :path => "/attachments/download/1" },
-           { :controller => 'attachments', :action => 'download', :id => '1' }
-         )
-    assert_routing(
-           { :method => 'get', :path => "/attachments/download/1/filename.ext" },
-           { :controller => 'attachments', :action => 'download', :id => '1',
-             :filename => 'filename.ext' }
-         )
-    assert_routing(
-           { :method => 'get', :path => "/attachments/thumbnail/1" },
-           { :controller => 'attachments', :action => 'thumbnail', :id => '1' }
-         )
-    assert_routing(
-           { :method => 'get', :path => "/attachments/thumbnail/1/200" },
-           { :controller => 'attachments', :action => 'thumbnail', :id => '1', :size => '200' }
-         )
-    assert_routing(
-           { :method => 'delete', :path => "/attachments/1" },
-           { :controller => 'attachments', :action => 'destroy', :id => '1' }
-         )
-    assert_routing(
-           { :method => 'post', :path => '/uploads.xml' },
-           { :controller => 'attachments', :action => 'upload', :format => 'xml' }
-    )
-    assert_routing(
-           { :method => 'post', :path => '/uploads.json' },
-           { :controller => 'attachments', :action => 'upload', :format => 'json' }
-    )
-  end
-end
--- a/.svn/pristine/e1/e18719fcaad4f02ac25c73385c2559b70312719c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class TokenTest < ActiveSupport::TestCase
-  fixtures :tokens
-
-  def test_create
-    token = Token.new
-    token.save
-    assert_equal 40, token.value.length
-    assert !token.expired?
-  end
-
-  def test_create_should_remove_existing_tokens
-    user = User.find(1)
-    t1 = Token.create(:user => user, :action => 'autologin')
-    t2 = Token.create(:user => user, :action => 'autologin')
-    assert_not_equal t1.value, t2.value
-    assert !Token.exists?(t1.id)
-    assert  Token.exists?(t2.id)
-  end
-
-  def test_destroy_expired_should_not_destroy_feeds_and_api_tokens
-    Token.delete_all
-
-    Token.create!(:user_id => 1, :action => 'api', :created_on => 7.days.ago)
-    Token.create!(:user_id => 1, :action => 'feeds', :created_on => 7.days.ago)
-
-    assert_no_difference 'Token.count' do
-      assert_equal 0, Token.destroy_expired
-    end
-  end
-
-  def test_destroy_expired_should_destroy_expired_tokens
-    Token.delete_all
-
-    Token.create!(:user_id => 1, :action => 'autologin', :created_on => 7.days.ago)
-    Token.create!(:user_id => 2, :action => 'autologin', :created_on => 3.days.ago)
-    Token.create!(:user_id => 3, :action => 'autologin', :created_on => 1.hour.ago)
-
-    assert_difference 'Token.count', -2 do
-      assert_equal 2, Token.destroy_expired
-    end
-  end
-
-  def test_find_active_user_should_return_user
-    token = Token.create!(:user_id => 1, :action => 'api')
-    assert_equal User.find(1), Token.find_active_user('api', token.value)
-  end
-
-  def test_find_active_user_should_return_nil_for_locked_user
-    token = Token.create!(:user_id => 1, :action => 'api')
-    User.find(1).lock!
-    assert_nil Token.find_active_user('api', token.value)
-  end
-
-  def test_find_user_should_return_user
-    token = Token.create!(:user_id => 1, :action => 'api')
-    assert_equal User.find(1), Token.find_user('api', token.value)
-  end
-
-  def test_find_user_should_return_locked_user
-    token = Token.create!(:user_id => 1, :action => 'api')
-    User.find(1).lock!
-    assert_equal User.find(1), Token.find_user('api', token.value)
-  end
-
-  def test_find_token_should_return_the_token
-    token = Token.create!(:user_id => 1, :action => 'api')
-    assert_equal token, Token.find_token('api', token.value)
-  end
-
-  def test_find_token_should_return_the_token_with_validity
-    token = Token.create!(:user_id => 1, :action => 'api', :created_on => 1.hour.ago)
-    assert_equal token, Token.find_token('api', token.value, 1)
-  end
-
-  def test_find_token_should_return_nil_with_wrong_action
-    token = Token.create!(:user_id => 1, :action => 'feeds')
-    assert_nil Token.find_token('api', token.value)
-  end
-
-  def test_find_token_should_return_nil_without_user
-    token = Token.create!(:user_id => 999, :action => 'api')
-    assert_nil Token.find_token('api', token.value)
-  end
-
-  def test_find_token_should_return_nil_with_validity_expired
-    token = Token.create!(:user_id => 999, :action => 'api', :created_on => 2.days.ago)
-    assert_nil Token.find_token('api', token.value, 1)
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/e1/e1d5bd3125ea24fb621f2a1d0bb4c880e4a9ae17.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,100 @@
+source 'https://rubygems.org'
+
+gem "rails", "3.2.19"
+gem "rake", "~> 10.1.1"
+gem "jquery-rails", "~> 2.0.2"
+gem "coderay", "~> 1.1.0"
+gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
+gem "builder", "3.0.0"
+
+# Optional gem for LDAP authentication
+group :ldap do
+  gem "net-ldap", "~> 0.3.1"
+end
+
+# Optional gem for OpenID authentication
+group :openid do
+  gem "ruby-openid", "~> 2.3.0", :require => "openid"
+  gem "rack-openid"
+end
+
+# Optional gem for exporting the gantt to a PNG file, not supported with jruby
+platforms :mri, :mingw do
+  group :rmagick do
+    # RMagick 2 supports ruby 1.9
+    # RMagick 1 would be fine for ruby 1.8 but Bundler does not support
+    # different requirements for the same gem on different platforms
+    gem "rmagick", ">= 2.0.0"
+  end
+end
+
+platforms :jruby do
+  # jruby-openssl is bundled with JRuby 1.7.0
+  gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
+  gem "activerecord-jdbc-adapter", "~> 1.3.2"
+end
+
+# Include database gems for the adapters found in the database
+# configuration file
+require 'erb'
+require 'yaml'
+database_file = File.join(File.dirname(__FILE__), "config/database.yml")
+if File.exist?(database_file)
+  database_config = YAML::load(ERB.new(IO.read(database_file)).result)
+  adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
+  if adapters.any?
+    adapters.each do |adapter|
+      case adapter
+      when 'mysql2'
+        gem "mysql2", "~> 0.3.11", :platforms => [:mri, :mingw]
+        gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
+      when 'mysql'
+        gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw]
+        gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
+      when /postgresql/
+        gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw]
+        gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
+      when /sqlite3/
+        gem "sqlite3", :platforms => [:mri, :mingw]
+        gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
+      when /sqlserver/
+        gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw]
+        gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
+      else
+        warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
+      end
+    end
+  else
+    warn("No adapter found in config/database.yml, please configure it first")
+  end
+else
+  warn("Please configure your config/database.yml first")
+end
+
+group :development do
+  gem "rdoc", ">= 2.4.2"
+  gem "yard"
+end
+
+group :test do
+  gem "shoulda", "~> 3.3.2"
+  gem "mocha", "~> 1.0.0", :require => 'mocha/api'
+  if RUBY_VERSION >= '1.9.3'
+    gem "capybara", "~> 2.1.0"
+    gem "selenium-webdriver"
+    gem "database_cleaner"
+  end
+end
+
+local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
+if File.exists?(local_gemfile)
+  puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v`
+  instance_eval File.read(local_gemfile)
+end
+
+# Load plugins' Gemfiles
+Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
+  puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
+  #TODO: switch to "eval_gemfile file" when bundler >= 1.2.0 will be required (rails 4)
+  instance_eval File.read(file), file
+end
--- a/.svn/pristine/e2/e20c66ea78669a9f640a596d6292e35c469be33c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,739 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require "digest/sha1"
-
-class User < Principal
-  include Redmine::SafeAttributes
-
-  # Different ways of displaying/sorting users
-  USER_FORMATS = {
-    :firstname_lastname => {
-        :string => '#{firstname} #{lastname}',
-        :order => %w(firstname lastname id),
-        :setting_order => 1
-      },
-    :firstname_lastinitial => {
-        :string => '#{firstname} #{lastname.to_s.chars.first}.',
-        :order => %w(firstname lastname id),
-        :setting_order => 2
-      },
-    :firstname => {
-        :string => '#{firstname}',
-        :order => %w(firstname id),
-        :setting_order => 3
-      },
-    :lastname_firstname => {
-        :string => '#{lastname} #{firstname}',
-        :order => %w(lastname firstname id),
-        :setting_order => 4
-      },
-    :lastname_coma_firstname => {
-        :string => '#{lastname}, #{firstname}',
-        :order => %w(lastname firstname id),
-        :setting_order => 5
-      },
-    :lastname => {
-        :string => '#{lastname}',
-        :order => %w(lastname id),
-        :setting_order => 6
-      },
-    :username => {
-        :string => '#{login}',
-        :order => %w(login id),
-        :setting_order => 7
-      },
-  }
-
-  MAIL_NOTIFICATION_OPTIONS = [
-    ['all', :label_user_mail_option_all],
-    ['selected', :label_user_mail_option_selected],
-    ['only_my_events', :label_user_mail_option_only_my_events],
-    ['only_assigned', :label_user_mail_option_only_assigned],
-    ['only_owner', :label_user_mail_option_only_owner],
-    ['none', :label_user_mail_option_none]
-  ]
-
-  has_and_belongs_to_many :groups, :after_add => Proc.new {|user, group| group.user_added(user)},
-                                   :after_remove => Proc.new {|user, group| group.user_removed(user)}
-  has_many :changesets, :dependent => :nullify
-  has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
-  has_one :rss_token, :class_name => 'Token', :conditions => "action='feeds'"
-  has_one :api_token, :class_name => 'Token', :conditions => "action='api'"
-  belongs_to :auth_source
-
-  scope :logged, lambda { where("#{User.table_name}.status <> #{STATUS_ANONYMOUS}") }
-  scope :status, lambda {|arg| where(arg.blank? ? nil : {:status => arg.to_i}) }
-
-  acts_as_customizable
-
-  attr_accessor :password, :password_confirmation, :generate_password
-  attr_accessor :last_before_login_on
-  # Prevents unauthorized assignments
-  attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
-
-  LOGIN_LENGTH_LIMIT = 60
-  MAIL_LENGTH_LIMIT = 60
-
-  validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) }
-  validates_uniqueness_of :login, :if => Proc.new { |user| user.login_changed? && user.login.present? }, :case_sensitive => false
-  validates_uniqueness_of :mail, :if => Proc.new { |user| user.mail_changed? && user.mail.present? }, :case_sensitive => false
-  # Login must contain letters, numbers, underscores only
-  validates_format_of :login, :with => /\A[a-z0-9_\-@\.]*\z/i
-  validates_length_of :login, :maximum => LOGIN_LENGTH_LIMIT
-  validates_length_of :firstname, :lastname, :maximum => 30
-  validates_format_of :mail, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :allow_blank => true
-  validates_length_of :mail, :maximum => MAIL_LENGTH_LIMIT, :allow_nil => true
-  validates_confirmation_of :password, :allow_nil => true
-  validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true
-  validate :validate_password_length
-
-  before_create :set_mail_notification
-  before_save   :generate_password_if_needed, :update_hashed_password
-  before_destroy :remove_references_before_destroy
-  after_save :update_notified_project_ids
-
-  scope :in_group, lambda {|group|
-    group_id = group.is_a?(Group) ? group.id : group.to_i
-    where("#{User.table_name}.id IN (SELECT gu.user_id FROM #{table_name_prefix}groups_users#{table_name_suffix} gu WHERE gu.group_id = ?)", group_id)
-  }
-  scope :not_in_group, lambda {|group|
-    group_id = group.is_a?(Group) ? group.id : group.to_i
-    where("#{User.table_name}.id NOT IN (SELECT gu.user_id FROM #{table_name_prefix}groups_users#{table_name_suffix} gu WHERE gu.group_id = ?)", group_id)
-  }
-  scope :sorted, lambda { order(*User.fields_for_order_statement)}
-
-  def set_mail_notification
-    self.mail_notification = Setting.default_notification_option if self.mail_notification.blank?
-    true
-  end
-
-  def update_hashed_password
-    # update hashed_password if password was set
-    if self.password && self.auth_source_id.blank?
-      salt_password(password)
-    end
-  end
-
-  alias :base_reload :reload
-  def reload(*args)
-    @name = nil
-    @projects_by_role = nil
-    @membership_by_project_id = nil
-    @notified_projects_ids = nil
-    @notified_projects_ids_changed = false
-    @builtin_role = nil
-    base_reload(*args)
-  end
-
-  def mail=(arg)
-    write_attribute(:mail, arg.to_s.strip)
-  end
-
-  def identity_url=(url)
-    if url.blank?
-      write_attribute(:identity_url, '')
-    else
-      begin
-        write_attribute(:identity_url, OpenIdAuthentication.normalize_identifier(url))
-      rescue OpenIdAuthentication::InvalidOpenId
-        # Invalid url, don't save
-      end
-    end
-    self.read_attribute(:identity_url)
-  end
-
-  # Returns the user that matches provided login and password, or nil
-  def self.try_to_login(login, password, active_only=true)
-    login = login.to_s
-    password = password.to_s
-
-    # Make sure no one can sign in with an empty login or password
-    return nil if login.empty? || password.empty?
-    user = find_by_login(login)
-    if user
-      # user is already in local database
-      return nil unless user.check_password?(password)
-      return nil if !user.active? && active_only
-    else
-      # user is not yet registered, try to authenticate with available sources
-      attrs = AuthSource.authenticate(login, password)
-      if attrs
-        user = new(attrs)
-        user.login = login
-        user.language = Setting.default_language
-        if user.save
-          user.reload
-          logger.info("User '#{user.login}' created from external auth source: #{user.auth_source.type} - #{user.auth_source.name}") if logger && user.auth_source
-        end
-      end
-    end
-    user.update_column(:last_login_on, Time.now) if user && !user.new_record? && user.active?
-    user
-  rescue => text
-    raise text
-  end
-
-  # Returns the user who matches the given autologin +key+ or nil
-  def self.try_to_autologin(key)
-    user = Token.find_active_user('autologin', key, Setting.autologin.to_i)
-    if user
-      user.update_column(:last_login_on, Time.now)
-      user
-    end
-  end
-
-  def self.name_formatter(formatter = nil)
-    USER_FORMATS[formatter || Setting.user_format] || USER_FORMATS[:firstname_lastname]
-  end
-
-  # Returns an array of fields names than can be used to make an order statement for users
-  # according to how user names are displayed
-  # Examples:
-  #
-  #   User.fields_for_order_statement              => ['users.login', 'users.id']
-  #   User.fields_for_order_statement('authors')   => ['authors.login', 'authors.id']
-  def self.fields_for_order_statement(table=nil)
-    table ||= table_name
-    name_formatter[:order].map {|field| "#{table}.#{field}"}
-  end
-
-  # Return user's full name for display
-  def name(formatter = nil)
-    f = self.class.name_formatter(formatter)
-    if formatter
-      eval('"' + f[:string] + '"')
-    else
-      @name ||= eval('"' + f[:string] + '"')
-    end
-  end
-
-  def active?
-    self.status == STATUS_ACTIVE
-  end
-
-  def registered?
-    self.status == STATUS_REGISTERED
-  end
-
-  def locked?
-    self.status == STATUS_LOCKED
-  end
-
-  def activate
-    self.status = STATUS_ACTIVE
-  end
-
-  def register
-    self.status = STATUS_REGISTERED
-  end
-
-  def lock
-    self.status = STATUS_LOCKED
-  end
-
-  def activate!
-    update_attribute(:status, STATUS_ACTIVE)
-  end
-
-  def register!
-    update_attribute(:status, STATUS_REGISTERED)
-  end
-
-  def lock!
-    update_attribute(:status, STATUS_LOCKED)
-  end
-
-  # Returns true if +clear_password+ is the correct user's password, otherwise false
-  def check_password?(clear_password)
-    if auth_source_id.present?
-      auth_source.authenticate(self.login, clear_password)
-    else
-      User.hash_password("#{salt}#{User.hash_password clear_password}") == hashed_password
-    end
-  end
-
-  # Generates a random salt and computes hashed_password for +clear_password+
-  # The hashed password is stored in the following form: SHA1(salt + SHA1(password))
-  def salt_password(clear_password)
-    self.salt = User.generate_salt
-    self.hashed_password = User.hash_password("#{salt}#{User.hash_password clear_password}")
-  end
-
-  # Does the backend storage allow this user to change their password?
-  def change_password_allowed?
-    return true if auth_source.nil?
-    return auth_source.allow_password_changes?
-  end
-
-  def must_change_password?
-    must_change_passwd? && change_password_allowed?
-  end
-
-  def generate_password?
-    generate_password == '1' || generate_password == true
-  end
-
-  # Generate and set a random password on given length
-  def random_password(length=40)
-    chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
-    chars -= %w(0 O 1 l)
-    password = ''
-    length.times {|i| password << chars[SecureRandom.random_number(chars.size)] }
-    self.password = password
-    self.password_confirmation = password
-    self
-  end
-
-  def pref
-    self.preference ||= UserPreference.new(:user => self)
-  end
-
-  def time_zone
-    @time_zone ||= (self.pref.time_zone.blank? ? nil : ActiveSupport::TimeZone[self.pref.time_zone])
-  end
-
-  def wants_comments_in_reverse_order?
-    self.pref[:comments_sorting] == 'desc'
-  end
-
-  # Return user's RSS key (a 40 chars long string), used to access feeds
-  def rss_key
-    if rss_token.nil?
-      create_rss_token(:action => 'feeds')
-    end
-    rss_token.value
-  end
-
-  # Return user's API key (a 40 chars long string), used to access the API
-  def api_key
-    if api_token.nil?
-      create_api_token(:action => 'api')
-    end
-    api_token.value
-  end
-
-  # Return an array of project ids for which the user has explicitly turned mail notifications on
-  def notified_projects_ids
-    @notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id)
-  end
-
-  def notified_project_ids=(ids)
-    @notified_projects_ids_changed = true
-    @notified_projects_ids = ids
-  end
-
-  # Updates per project notifications (after_save callback)
-  def update_notified_project_ids
-    if @notified_projects_ids_changed
-      ids = (mail_notification == 'selected' ? Array.wrap(notified_projects_ids).reject(&:blank?) : [])
-      members.update_all(:mail_notification => false)
-      members.where(:project_id => ids).update_all(:mail_notification => true) if ids.any?
-    end
-  end
-  private :update_notified_project_ids
-
-  def valid_notification_options
-    self.class.valid_notification_options(self)
-  end
-
-  # Only users that belong to more than 1 project can select projects for which they are notified
-  def self.valid_notification_options(user=nil)
-    # Note that @user.membership.size would fail since AR ignores
-    # :include association option when doing a count
-    if user.nil? || user.memberships.length < 1
-      MAIL_NOTIFICATION_OPTIONS.reject {|option| option.first == 'selected'}
-    else
-      MAIL_NOTIFICATION_OPTIONS
-    end
-  end
-
-  # Find a user account by matching the exact login and then a case-insensitive
-  # version.  Exact matches will be given priority.
-  def self.find_by_login(login)
-    if login.present?
-      login = login.to_s
-      # First look for an exact match
-      user = where(:login => login).all.detect {|u| u.login == login}
-      unless user
-        # Fail over to case-insensitive if none was found
-        user = where("LOWER(login) = ?", login.downcase).first
-      end
-      user
-    end
-  end
-
-  def self.find_by_rss_key(key)
-    Token.find_active_user('feeds', key)
-  end
-
-  def self.find_by_api_key(key)
-    Token.find_active_user('api', key)
-  end
-
-  # Makes find_by_mail case-insensitive
-  def self.find_by_mail(mail)
-    where("LOWER(mail) = ?", mail.to_s.downcase).first
-  end
-
-  # Returns true if the default admin account can no longer be used
-  def self.default_admin_account_changed?
-    !User.active.find_by_login("admin").try(:check_password?, "admin")
-  end
-
-  def to_s
-    name
-  end
-
-  CSS_CLASS_BY_STATUS = {
-    STATUS_ANONYMOUS  => 'anon',
-    STATUS_ACTIVE     => 'active',
-    STATUS_REGISTERED => 'registered',
-    STATUS_LOCKED     => 'locked'
-  }
-
-  def css_classes
-    "user #{CSS_CLASS_BY_STATUS[status]}"
-  end
-
-  # Returns the current day according to user's time zone
-  def today
-    if time_zone.nil?
-      Date.today
-    else
-      Time.now.in_time_zone(time_zone).to_date
-    end
-  end
-
-  # Returns the day of +time+ according to user's time zone
-  def time_to_date(time)
-    if time_zone.nil?
-      time.to_date
-    else
-      time.in_time_zone(time_zone).to_date
-    end
-  end
-
-  def logged?
-    true
-  end
-
-  def anonymous?
-    !logged?
-  end
-
-  # Returns user's membership for the given project
-  # or nil if the user is not a member of project
-  def membership(project)
-    project_id = project.is_a?(Project) ? project.id : project
-
-    @membership_by_project_id ||= Hash.new {|h, project_id|
-      h[project_id] = memberships.where(:project_id => project_id).first
-    }
-    @membership_by_project_id[project_id]
-  end
-
-  # Returns the user's bult-in role
-  def builtin_role
-    @builtin_role ||= Role.non_member
-  end
-
-  # Return user's roles for project
-  def roles_for_project(project)
-    roles = []
-    # No role on archived projects
-    return roles if project.nil? || project.archived?
-    if membership = membership(project)
-      roles = membership.roles
-    else
-      roles << builtin_role
-    end
-    roles
-  end
-
-  # Return true if the user is a member of project
-  def member_of?(project)
-    projects.to_a.include?(project)
-  end
-
-  # Returns a hash of user's projects grouped by roles
-  def projects_by_role
-    return @projects_by_role if @projects_by_role
-
-    @projects_by_role = Hash.new([])
-    memberships.each do |membership|
-      if membership.project
-        membership.roles.each do |role|
-          @projects_by_role[role] = [] unless @projects_by_role.key?(role)
-          @projects_by_role[role] << membership.project
-        end
-      end
-    end
-    @projects_by_role.each do |role, projects|
-      projects.uniq!
-    end
-
-    @projects_by_role
-  end
-
-  # Returns true if user is arg or belongs to arg
-  def is_or_belongs_to?(arg)
-    if arg.is_a?(User)
-      self == arg
-    elsif arg.is_a?(Group)
-      arg.users.include?(self)
-    else
-      false
-    end
-  end
-
-  # Return true if the user is allowed to do the specified action on a specific context
-  # Action can be:
-  # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
-  # * a permission Symbol (eg. :edit_project)
-  # Context can be:
-  # * a project : returns true if user is allowed to do the specified action on this project
-  # * an array of projects : returns true if user is allowed on every project
-  # * nil with options[:global] set : check if user has at least one role allowed for this action,
-  #   or falls back to Non Member / Anonymous permissions depending if the user is logged
-  def allowed_to?(action, context, options={}, &block)
-    if context && context.is_a?(Project)
-      return false unless context.allows_to?(action)
-      # Admin users are authorized for anything else
-      return true if admin?
-
-      roles = roles_for_project(context)
-      return false unless roles
-      roles.any? {|role|
-        (context.is_public? || role.member?) &&
-        role.allowed_to?(action) &&
-        (block_given? ? yield(role, self) : true)
-      }
-    elsif context && context.is_a?(Array)
-      if context.empty?
-        false
-      else
-        # Authorize if user is authorized on every element of the array
-        context.map {|project| allowed_to?(action, project, options, &block)}.reduce(:&)
-      end
-    elsif options[:global]
-      # Admin users are always authorized
-      return true if admin?
-
-      # authorize if user has at least one role that has this permission
-      roles = memberships.collect {|m| m.roles}.flatten.uniq
-      roles << (self.logged? ? Role.non_member : Role.anonymous)
-      roles.any? {|role|
-        role.allowed_to?(action) &&
-        (block_given? ? yield(role, self) : true)
-      }
-    else
-      false
-    end
-  end
-
-  # Is the user allowed to do the specified action on any project?
-  # See allowed_to? for the actions and valid options.
-  def allowed_to_globally?(action, options, &block)
-    allowed_to?(action, nil, options.reverse_merge(:global => true), &block)
-  end
-
-  # Returns true if the user is allowed to delete the user's own account
-  def own_account_deletable?
-    Setting.unsubscribe? &&
-      (!admin? || User.active.where("admin = ? AND id <> ?", true, id).exists?)
-  end
-
-  safe_attributes 'login',
-    'firstname',
-    'lastname',
-    'mail',
-    'mail_notification',
-    'notified_project_ids',
-    'language',
-    'custom_field_values',
-    'custom_fields',
-    'identity_url'
-
-  safe_attributes 'status',
-    'auth_source_id',
-    'generate_password',
-    'must_change_passwd',
-    :if => lambda {|user, current_user| current_user.admin?}
-
-  safe_attributes 'group_ids',
-    :if => lambda {|user, current_user| current_user.admin? && !user.new_record?}
-
-  # Utility method to help check if a user should be notified about an
-  # event.
-  #
-  # TODO: only supports Issue events currently
-  def notify_about?(object)
-    if mail_notification == 'all'
-      true
-    elsif mail_notification.blank? || mail_notification == 'none'
-      false
-    else
-      case object
-      when Issue
-        case mail_notification
-        when 'selected', 'only_my_events'
-          # user receives notifications for created/assigned issues on unselected projects
-          object.author == self || is_or_belongs_to?(object.assigned_to) || is_or_belongs_to?(object.assigned_to_was)
-        when 'only_assigned'
-          is_or_belongs_to?(object.assigned_to) || is_or_belongs_to?(object.assigned_to_was)
-        when 'only_owner'
-          object.author == self
-        end
-      when News
-        # always send to project members except when mail_notification is set to 'none'
-        true
-      end
-    end
-  end
-
-  def self.current=(user)
-    Thread.current[:current_user] = user
-  end
-
-  def self.current
-    Thread.current[:current_user] ||= User.anonymous
-  end
-
-  # Returns the anonymous user.  If the anonymous user does not exist, it is created.  There can be only
-  # one anonymous user per database.
-  def self.anonymous
-    anonymous_user = AnonymousUser.first
-    if anonymous_user.nil?
-      anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :mail => '', :login => '', :status => 0)
-      raise 'Unable to create the anonymous user.' if anonymous_user.new_record?
-    end
-    anonymous_user
-  end
-
-  # Salts all existing unsalted passwords
-  # It changes password storage scheme from SHA1(password) to SHA1(salt + SHA1(password))
-  # This method is used in the SaltPasswords migration and is to be kept as is
-  def self.salt_unsalted_passwords!
-    transaction do
-      User.where("salt IS NULL OR salt = ''").find_each do |user|
-        next if user.hashed_password.blank?
-        salt = User.generate_salt
-        hashed_password = User.hash_password("#{salt}#{user.hashed_password}")
-        User.where(:id => user.id).update_all(:salt => salt, :hashed_password => hashed_password)
-      end
-    end
-  end
-
-  protected
-
-  def validate_password_length
-    return if password.blank? && generate_password?
-    # Password length validation based on setting
-    if !password.nil? && password.size < Setting.password_min_length.to_i
-      errors.add(:password, :too_short, :count => Setting.password_min_length.to_i)
-    end
-  end
-
-  private
-
-  def generate_password_if_needed
-    if generate_password? && auth_source.nil?
-      length = [Setting.password_min_length.to_i + 2, 10].max
-      random_password(length)
-    end
-  end
-
-  # Removes references that are not handled by associations
-  # Things that are not deleted are reassociated with the anonymous user
-  def remove_references_before_destroy
-    return if self.id.nil?
-
-    substitute = User.anonymous
-    Attachment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
-    Comment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
-    Issue.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
-    Issue.update_all 'assigned_to_id = NULL', ['assigned_to_id = ?', id]
-    Journal.update_all ['user_id = ?', substitute.id], ['user_id = ?', id]
-    JournalDetail.update_all ['old_value = ?', substitute.id.to_s], ["property = 'attr' AND prop_key = 'assigned_to_id' AND old_value = ?", id.to_s]
-    JournalDetail.update_all ['value = ?', substitute.id.to_s], ["property = 'attr' AND prop_key = 'assigned_to_id' AND value = ?", id.to_s]
-    Message.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
-    News.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
-    # Remove private queries and keep public ones
-    ::Query.delete_all ['user_id = ? AND visibility = ?', id, ::Query::VISIBILITY_PRIVATE]
-    ::Query.update_all ['user_id = ?', substitute.id], ['user_id = ?', id]
-    TimeEntry.update_all ['user_id = ?', substitute.id], ['user_id = ?', id]
-    Token.delete_all ['user_id = ?', id]
-    Watcher.delete_all ['user_id = ?', id]
-    WikiContent.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
-    WikiContent::Version.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
-  end
-
-  # Return password digest
-  def self.hash_password(clear_password)
-    Digest::SHA1.hexdigest(clear_password || "")
-  end
-
-  # Returns a 128bits random salt as a hex string (32 chars long)
-  def self.generate_salt
-    Redmine::Utils.random_hex(16)
-  end
-
-end
-
-class AnonymousUser < User
-  validate :validate_anonymous_uniqueness, :on => :create
-
-  def validate_anonymous_uniqueness
-    # There should be only one AnonymousUser in the database
-    errors.add :base, 'An anonymous user already exists.' if AnonymousUser.exists?
-  end
-
-  def available_custom_fields
-    []
-  end
-
-  # Overrides a few properties
-  def logged?; false end
-  def admin; false end
-  def name(*args); I18n.t(:label_user_anonymous) end
-  def mail; nil end
-  def time_zone; nil end
-  def rss_key; nil end
-
-  def pref
-    UserPreference.new(:user => self)
-  end
-
-  # Returns the user's bult-in role
-  def builtin_role
-    @builtin_role ||= Role.anonymous
-  end
-
-  def membership(*args)
-    nil
-  end
-
-  def member_of?(*args)
-    false
-  end
-
-  # Anonymous user can not be destroyed
-  def destroy
-    false
-  end
-end
--- a/.svn/pristine/e3/e3ea2cb6450687eb1d61c512debbaf9478178a88.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module ActiveRecord
-  module FinderMethods
-    def find_ids(*args)
-      find_ids_with_associations
-    end
-
-    private
-  
-    def find_ids_with_associations
-        join_dependency = construct_join_dependency_for_association_find
-        relation = construct_relation_for_association_find_ids(join_dependency)
-        rows = connection.select_all(relation, 'SQL', relation.bind_values)
-        rows.map {|row| row["id"].to_i}
-      rescue ThrowResult
-        []
-    end
-
-    def construct_relation_for_association_find_ids(join_dependency)
-      relation = except(:includes, :eager_load, :preload, :select).select("#{table_name}.id")
-      apply_join_dependency(relation, join_dependency)
-    end
-  end
-end
-
-class DateValidator < ActiveModel::EachValidator
-  def validate_each(record, attribute, value)
-    before_type_cast = record.attributes_before_type_cast[attribute.to_s]
-    if before_type_cast.is_a?(String) && before_type_cast.present?
-      # TODO: #*_date_before_type_cast returns a Mysql::Time with ruby1.8+mysql gem
-      unless before_type_cast =~ /\A\d{4}-\d{2}-\d{2}( 00:00:00)?\z/ && value
-        record.errors.add attribute, :not_a_date
-      end
-    end
-  end
-end
--- a/.svn/pristine/e4/e4897735528df3f63a14478e29488229fe020925.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Acts
-    module Event
-      def self.included(base)
-        base.extend ClassMethods
-      end
-
-      module ClassMethods
-        def acts_as_event(options = {})
-          return if self.included_modules.include?(Redmine::Acts::Event::InstanceMethods)
-          default_options = { :datetime => :created_on,
-                              :title => :title,
-                              :description => :description,
-                              :author => :author,
-                              :url => {:controller => 'welcome'},
-                              :type => self.name.underscore.dasherize }
-
-          cattr_accessor :event_options
-          self.event_options = default_options.merge(options)
-          send :include, Redmine::Acts::Event::InstanceMethods
-        end
-      end
-
-      module InstanceMethods
-        def self.included(base)
-          base.extend ClassMethods
-        end
-
-        %w(datetime title description author type).each do |attr|
-          src = <<-END_SRC
-            def event_#{attr}
-              option = event_options[:#{attr}]
-              if option.is_a?(Proc)
-                option.call(self)
-              elsif option.is_a?(Symbol)
-                send(option)
-              else
-                option
-              end
-            end
-          END_SRC
-          class_eval src, __FILE__, __LINE__
-        end
-
-        def event_date
-          event_datetime.to_date
-        end
-
-        def event_group
-          group = event_options[:group] ? send(event_options[:group]) : self
-          group || self
-        end
-
-        def event_url(options = {})
-          option = event_options[:url]
-          if option.is_a?(Proc)
-            option.call(self).merge(options)
-          elsif option.is_a?(Hash)
-            option.merge(options)
-          elsif option.is_a?(Symbol)
-            send(option).merge(options)
-          else
-            option
-          end
-        end
-
-        # Returns the mail adresses of users that should be notified
-        def recipients
-          notified = project.notified_users
-          notified.reject! {|user| !visible?(user)}
-          notified.collect(&:mail)
-        end
-
-        module ClassMethods
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/e4/e4ed3df6bca9bcd2f1e4eae777c4852f4adf1c6c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class TimelogHelperTest < ActionView::TestCase
-  include TimelogHelper
-  include Redmine::I18n
-  include ActionView::Helpers::TextHelper
-  include ActionView::Helpers::DateHelper
-  include ERB::Util
-
-  fixtures :projects, :roles, :enabled_modules, :users,
-                      :repositories, :changesets,
-                      :trackers, :issue_statuses, :issues, :versions, :documents,
-                      :wikis, :wiki_pages, :wiki_contents,
-                      :boards, :messages,
-                      :attachments,
-                      :enumerations
-
-  def setup
-    super
-  end
-
-  def test_activities_collection_for_select_options_should_return_array_of_activity_names_and_ids
-    activities = activity_collection_for_select_options
-    assert activities.include?(["Design", 9])
-    assert activities.include?(["Development", 10])
-  end
-
-  def test_activities_collection_for_select_options_should_not_include_inactive_activities
-    activities = activity_collection_for_select_options
-    assert !activities.include?(["Inactive Activity", 14])
-  end
-
-  def test_activities_collection_for_select_options_should_use_the_projects_override
-    project = Project.find(1)
-    override_activity = TimeEntryActivity.create!({:name => "Design override", :parent => TimeEntryActivity.find_by_name("Design"), :project => project})
-
-    activities = activity_collection_for_select_options(nil, project)
-    assert !activities.include?(["Design", 9]), "System activity found in: " + activities.inspect
-    assert activities.include?(["Design override", override_activity.id]), "Override activity not found in: " + activities.inspect
-  end
-end
--- a/.svn/pristine/e5/e57e448ff5e398f985d2656f35e0c4f0db003780.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingGroupsTest < ActionController::IntegrationTest
-  def test_groups_resources
-    assert_routing(
-        { :method => 'get', :path => "/groups" },
-        { :controller => 'groups', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/groups.xml" },
-        { :controller => 'groups', :action => 'index', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/groups" },
-        { :controller => 'groups', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/groups.xml" },
-        { :controller => 'groups', :action => 'create', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/groups/new" },
-        { :controller => 'groups', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/groups/1/edit" },
-        { :controller => 'groups', :action => 'edit', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/groups/1/autocomplete_for_user" },
-        { :controller => 'groups', :action => 'autocomplete_for_user', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/groups/1/autocomplete_for_user.js" },
-        { :controller => 'groups', :action => 'autocomplete_for_user', :id => '1', :format => 'js' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/groups/1" },
-        { :controller => 'groups', :action => 'show', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/groups/1.xml" },
-        { :controller => 'groups', :action => 'show', :id => '1', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/groups/1" },
-        { :controller => 'groups', :action => 'update', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/groups/1.xml" },
-        { :controller => 'groups', :action => 'update', :id => '1', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/groups/1" },
-        { :controller => 'groups', :action => 'destroy', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/groups/1.xml" },
-        { :controller => 'groups', :action => 'destroy', :id => '1', :format => 'xml' }
-      )
-  end
-
-  def test_groups
-    assert_routing(
-        { :method => 'post', :path => "/groups/567/users" },
-        { :controller => 'groups', :action => 'add_users', :id => '567' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/groups/567/users.xml" },
-        { :controller => 'groups', :action => 'add_users', :id => '567', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/groups/567/users/12" },
-        { :controller => 'groups', :action => 'remove_user', :id => '567', :user_id => '12' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/groups/567/users/12.xml" },
-        { :controller => 'groups', :action => 'remove_user', :id => '567', :user_id => '12', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/groups/destroy_membership/567" },
-        { :controller => 'groups', :action => 'destroy_membership', :id => '567' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/groups/edit_membership/567" },
-        { :controller => 'groups', :action => 'edit_membership', :id => '567' }
-      )
-  end
-end
--- a/.svn/pristine/e5/e58ec86b245f3ac57a759399f47d3d6b2bb03a42.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoryDarcsTest < ActiveSupport::TestCase
-  fixtures :projects
-
-  include Redmine::I18n
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s
-  NUM_REV = 6
-
-  def setup
-    @project = Project.find(3)
-    @repository = Repository::Darcs.create(
-                      :project      => @project,
-                      :url          => REPOSITORY_PATH,
-                      :log_encoding => 'UTF-8'
-                      )
-    assert @repository
-  end
-
-  def test_blank_path_to_repository_error_message
-    set_language_if_valid 'en'
-    repo = Repository::Darcs.new(
-                          :project      => @project,
-                          :identifier   => 'test',
-                          :log_encoding => 'UTF-8'
-                        )
-    assert !repo.save
-    assert_include "Path to repository can't be blank",
-                   repo.errors.full_messages
-  end
-
-  def test_blank_path_to_repository_error_message_fr
-    set_language_if_valid 'fr'
-    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    repo = Repository::Darcs.new(
-                          :project      => @project,
-                          :url          => "",
-                          :identifier   => 'test',
-                          :log_encoding => 'UTF-8'
-                        )
-    assert !repo.save
-    assert_include str, repo.errors.full_messages
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    def test_fetch_changesets_from_scratch
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_equal 13, @repository.filechanges.count
-      assert_equal "Initial commit.", @repository.changesets.find_by_revision('1').comments
-    end
-
-    def test_fetch_changesets_incremental
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      # Remove changesets with revision > 3
-      @repository.changesets.all.each {|c| c.destroy if c.revision.to_i > 3}
-      @project.reload
-      assert_equal 3, @repository.changesets.count
-
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-    end
-
-    def test_entries
-      entries = @repository.entries
-      assert_kind_of Redmine::Scm::Adapters::Entries, entries
-    end
-
-    def test_entries_invalid_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      assert_nil @repository.entries('', '123')
-    end
-
-    def test_deleted_files_should_not_be_listed
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      entries = @repository.entries('sources')
-      assert entries.detect {|e| e.name == 'watchers_controller.rb'}
-      assert_nil entries.detect {|e| e.name == 'welcome_controller.rb'}
-    end
-
-    def test_cat
-      if @repository.scm.supports_cat?
-        assert_equal 0, @repository.changesets.count
-        @repository.fetch_changesets
-        @project.reload
-        assert_equal NUM_REV, @repository.changesets.count
-        cat = @repository.cat("sources/welcome_controller.rb", 2)
-        assert_not_nil cat
-        assert cat.include?('class WelcomeController < ApplicationController')
-      end
-    end
-  else
-    puts "Darcs test repository NOT FOUND. Skipping unit tests !!!"
-    def test_fake; assert true end
-  end
-end
--- a/.svn/pristine/e5/e5e737cf1acef41f150245d1f3e14b3ec1313b84.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingGanttsTest < ActionController::IntegrationTest
-  def test_gantts
-    assert_routing(
-        { :method => 'get', :path => "/issues/gantt" },
-        { :controller => 'gantts', :action => 'show' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/gantt.pdf" },
-        { :controller => 'gantts', :action => 'show', :format => 'pdf' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/project-name/issues/gantt" },
-        { :controller => 'gantts', :action => 'show',
-          :project_id => 'project-name' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/project-name/issues/gantt.pdf" },
-        { :controller => 'gantts', :action => 'show',
-          :project_id => 'project-name', :format => 'pdf' }
-      )
-  end
-end
--- a/.svn/pristine/e6/e69e1b12c742c2fed3eb747a9348573816cd63d1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesCvsControllerTest < ActionController::TestCase
-  tests RepositoriesController
-
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :repositories, :enabled_modules
-
-  REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s
-  REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
-  # CVS module
-  MODULE_NAME = 'test'
-  PRJ_ID = 3
-  NUM_REV = 7
-
-  def setup
-    Setting.default_language = 'en'
-    User.current = nil
-
-    @project = Project.find(PRJ_ID)
-    @repository  = Repository::Cvs.create(:project      => Project.find(PRJ_ID),
-                                          :root_url     => REPOSITORY_PATH,
-                                          :url          => MODULE_NAME,
-                                          :log_encoding => 'UTF-8')
-    assert @repository
-  end
-
-  if File.directory?(REPOSITORY_PATH)
-    def test_get_new
-      @request.session[:user_id] = 1
-      @project.repository.destroy
-      get :new, :project_id => 'subproject1', :repository_scm => 'Cvs'
-      assert_response :success
-      assert_template 'new'
-      assert_kind_of Repository::Cvs, assigns(:repository)
-      assert assigns(:repository).new_record?
-    end
-
-    def test_browse_root
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal 3, assigns(:entries).size
-
-      entry = assigns(:entries).detect {|e| e.name == 'images'}
-      assert_equal 'dir', entry.kind
-
-      entry = assigns(:entries).detect {|e| e.name == 'README'}
-      assert_equal 'file', entry.kind
-
-      assert_not_nil assigns(:changesets)
-      assert assigns(:changesets).size > 0
-    end
-
-    def test_browse_directory
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['add.png', 'delete.png', 'edit.png'], assigns(:entries).collect(&:name)
-      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
-      assert_not_nil entry
-      assert_equal 'file', entry.kind
-      assert_equal 'images/edit.png', entry.path
-    end
-
-    def test_browse_at_given_revision
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
-          :rev => 1
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entries)
-      assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
-    end
-
-    def test_entry
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
-      assert_response :success
-      assert_template 'entry'
-      assert_no_tag :tag => 'td',
-                    :attributes => { :class => /line-code/},
-                    :content => /before_filter/
-    end
-
-    def test_entry_at_given_revision
-      # changesets must be loaded
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
-          :rev => 2
-      assert_response :success
-      assert_template 'entry'
-      # this line was removed in r3
-      assert_tag :tag => 'td',
-                 :attributes => { :class => /line-code/},
-                 :content => /before_filter/
-    end
-
-    def test_entry_not_found
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'zzz.c'])[:param]
-      assert_tag :tag => 'p',
-                 :attributes => { :id => /errorExplanation/ },
-                 :content => /The entry or revision was not found in the repository/
-    end
-
-    def test_entry_download
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
-          :format => 'raw'
-      assert_response :success
-    end
-
-    def test_directory_entry
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :entry, :id => PRJ_ID,
-          :path => repository_path_hash(['sources'])[:param]
-      assert_response :success
-      assert_template 'show'
-      assert_not_nil assigns(:entry)
-      assert_equal 'sources', assigns(:entry).name
-    end
-
-    def test_diff
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['inline', 'sbs'].each do |dt|
-        get :diff, :id => PRJ_ID, :rev => 3, :type => dt
-        assert_response :success
-        assert_template 'diff'
-        assert_tag :tag => 'td', :attributes => { :class => 'line-code diff_out' },
-                                 :content => /before_filter :require_login/
-        assert_tag :tag => 'td', :attributes => { :class => 'line-code diff_in' },
-                                 :content => /with one change/
-      end
-    end
-
-    def test_diff_new_files
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      ['inline', 'sbs'].each do |dt|
-        get :diff, :id => PRJ_ID, :rev => 1, :type => dt
-        assert_response :success
-        assert_template 'diff'
-        assert_tag :tag => 'td', :attributes => { :class => 'line-code diff_in' },
-                                 :content => /watched.remove_watcher/
-        assert_tag :tag => 'th', :attributes => { :class => 'filename' },
-                                 :content => /test\/README/
-        assert_tag :tag => 'th', :attributes => { :class => 'filename' },
-                                 :content => /test\/images\/delete.png	/
-        assert_tag :tag => 'th', :attributes => { :class => 'filename' },
-                                 :content => /test\/images\/edit.png/
-        assert_tag :tag => 'th', :attributes => { :class => 'filename' },
-                                 :content => /test\/sources\/watchers_controller.rb/
-      end
-    end
-
-    def test_annotate
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-      get :annotate, :id => PRJ_ID,
-          :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
-      assert_response :success
-      assert_template 'annotate'
-
-      # 1.1 line
-      assert_select 'tr' do
-        assert_select 'th.line-num', :text => '21'
-        assert_select 'td.revision', :text => /1.1/
-        assert_select 'td.author', :text => /LANG/
-      end
-      # 1.2 line
-      assert_select 'tr' do
-        assert_select 'th.line-num', :text => '32'
-        assert_select 'td.revision', :text => /1.2/
-        assert_select 'td.author', :text => /LANG/
-      end
-    end
-
-    def test_destroy_valid_repository
-      @request.session[:user_id] = 1 # admin
-      assert_equal 0, @repository.changesets.count
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal NUM_REV, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-
-    def test_destroy_invalid_repository
-      @request.session[:user_id] = 1 # admin
-      @project.repository.destroy
-      @repository  = Repository::Cvs.create!(
-                              :project      => Project.find(PRJ_ID),
-                              :root_url     => "/invalid",
-                              :url          => MODULE_NAME,
-                              :log_encoding => 'UTF-8'
-                              )
-      @repository.fetch_changesets
-      @project.reload
-      assert_equal 0, @repository.changesets.count
-
-      assert_difference 'Repository.count', -1 do
-        delete :destroy, :id => @repository.id
-      end
-      assert_response 302
-      @project.reload
-      assert_nil @project.repository
-    end
-  else
-    puts "CVS test repository NOT FOUND. Skipping functional tests !!!"
-    def test_fake; assert true end
-  end
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/e7/e77dfa369054aed2bdcad312e7a94ac301cf3c53.svn-base	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,210 @@
+# = Redmine configuration file
+#
+# Each environment has it's own configuration options.  If you are only
+# running in production, only the production block needs to be configured.
+# Environment specific configuration options override the default ones.
+#
+# Note that this file needs to be a valid YAML file.
+# DO NOT USE TABS! Use 2 spaces instead of tabs for identation.
+#
+# == Outgoing email settings (email_delivery setting)
+#
+# === Common configurations
+#
+# ==== Sendmail command
+#
+# production:
+#   email_delivery:
+#     delivery_method: :sendmail
+#
+# ==== Simple SMTP server at localhost
+#
+# production:
+#   email_delivery:
+#     delivery_method: :smtp
+#     smtp_settings:
+#       address: "localhost"
+#       port: 25
+#
+# ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com
+#
+# production:
+#   email_delivery:
+#     delivery_method: :smtp
+#     smtp_settings:
+#       address: "example.com"
+#       port: 25
+#       authentication: :login
+#       domain: 'foo.com'
+#       user_name: 'myaccount'
+#       password: 'password'
+#
+# ==== SMTP server at example.com using PLAIN authentication
+#
+# production:
+#   email_delivery:
+#     delivery_method: :smtp
+#     smtp_settings:
+#       address: "example.com"
+#       port: 25
+#       authentication: :plain
+#       domain: 'example.com'
+#       user_name: 'myaccount'
+#       password: 'password'
+#
+# ==== SMTP server at using TLS (GMail)
+#
+# This might require some additional configuration. See the guides at:
+# http://www.redmine.org/projects/redmine/wiki/EmailConfiguration
+#
+# production:
+#   email_delivery:
+#     delivery_method: :smtp
+#     smtp_settings:
+#       enable_starttls_auto: true
+#       address: "smtp.gmail.com"
+#       port: 587
+#       domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
+#       authentication: :plain
+#       user_name: "your_email@gmail.com"
+#       password: "your_password"
+#
+#
+# === More configuration options
+#
+# See following page:
+#
+# http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
+
+
+# default configuration options for all environments
+default:
+  # Outgoing emails configuration (see examples above)
+  email_delivery:
+    delivery_method: :smtp
+    smtp_settings:
+      address: smtp.example.net
+      port: 25
+      domain: example.net
+      authentication: :login
+      user_name: "redmine@example.net"
+      password: "redmine"
+
+  # Absolute path to the directory where attachments are stored.
+  # The default is the 'files' directory in your Redmine instance.
+  # Your Redmine instance needs to have write permission on this
+  # directory.
+  # Examples:
+  # attachments_storage_path: /var/redmine/files
+  # attachments_storage_path: D:/redmine/files
+  attachments_storage_path:
+
+  # Configuration of the autologin cookie.
+  # autologin_cookie_name: the name of the cookie (default: autologin)
+  # autologin_cookie_path: the cookie path (default: /)
+  # autologin_cookie_secure: true sets the cookie secure flag (default: false)
+  autologin_cookie_name:
+  autologin_cookie_path:
+  autologin_cookie_secure:
+
+  # Configuration of SCM executable command.
+  #
+  # Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
+  # On Windows + CRuby, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
+  #
+  # On Windows + JRuby 1.6.2, path which contains spaces does not work.
+  # For example, "C:\Program Files\TortoiseHg\hg.exe".
+  # If you want to this feature, you need to install to the path which does not contains spaces.
+  # For example, "C:\TortoiseHg\hg.exe".
+  #
+  # Examples:
+  # scm_subversion_command: svn                                       # (default: svn)
+  # scm_mercurial_command:  C:\Program Files\TortoiseHg\hg.exe        # (default: hg)
+  # scm_git_command:        /usr/local/bin/git                        # (default: git)
+  # scm_cvs_command:        cvs                                       # (default: cvs)
+  # scm_bazaar_command:     bzr.exe                                   # (default: bzr)
+  # scm_darcs_command:      darcs-1.0.9-i386-linux                    # (default: darcs)
+  #
+  scm_subversion_command:
+  scm_mercurial_command:
+  scm_git_command:
+  scm_cvs_command:
+  scm_bazaar_command:
+  scm_darcs_command:
+
+  # Absolute path to the SCM commands errors (stderr) log file.
+  # The default is to log in the 'log' directory of your Redmine instance.
+  # Example:
+  # scm_stderr_log_file: /var/log/redmine_scm_stderr.log
+  scm_stderr_log_file:
+
+  # Key used to encrypt sensitive data in the database (SCM and LDAP passwords).
+  # If you don't want to enable data encryption, just leave it blank.
+  # WARNING: losing/changing this key will make encrypted data unreadable.
+  #
+  # If you want to encrypt existing passwords in your database:
+  # * set the cipher key here in your configuration file
+  # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
+  #
+  # If you have encrypted data and want to change this key, you have to:
+  # * decrypt data using 'rake db:decrypt RAILS_ENV=production' first
+  # * change the cipher key here in your configuration file
+  # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
+  database_cipher_key:
+
+  # Set this to false to disable plugins' assets mirroring on startup.
+  # You can use `rake redmine:plugins:assets` to manually mirror assets
+  # to public/plugin_assets when you install/upgrade a Redmine plugin.
+  #
+  #mirror_plugins_assets_on_startup: false
+
+  # Your secret key for verifying cookie session data integrity. If you
+  # change this key, all old sessions will become invalid! Make sure the
+  # secret is at least 30 characters and all random, no regular words or
+  # you'll be exposed to dictionary attacks.
+  #
+  # If you have a load-balancing Redmine cluster, you have to use the
+  # same secret token on each machine.
+  #secret_token: 'change it to a long random string'
+
+  # Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to
+  # the ImageMagick's `convert` binary. Used to generate attachment thumbnails.
+  #imagemagick_convert_command:
+
+  # Configuration of RMagcik font.
+  #
+  # Redmine uses RMagcik in order to export gantt png.
+  # You don't need this setting if you don't install RMagcik.
+  #
+  # In CJK (Chinese, Japanese and Korean),
+  # in order to show CJK characters correctly,
+  # you need to set this configuration.
+  #
+  # Because there is no standard font across platforms in CJK,
+  # you need to set a font installed in your server.
+  #
+  # This setting is not necessary in non CJK.
+  #
+  # Examples for Japanese:
+  #   Windows:
+  #     rmagick_font_path: C:\windows\fonts\msgothic.ttc
+  #   Linux:
+  #     rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
+  #
+  rmagick_font_path:
+
+  # Maximum number of simultaneous AJAX uploads
+  #max_concurrent_ajax_uploads: 2
+
+  # Configure OpenIdAuthentication.store
+  #
+  # allowed values: :memory, :file, :memcache
+  #openid_authentication_store: :memory
+
+# specific configuration options for production environment
+# that overrides the default ones
+production:
+
+# specific configuration options for development environment
+# that overrides the default ones
+development:
--- a/.svn/pristine/e7/e782c41b495cdac1921cd58d5fd63f6ce30f9f15.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::ProjectsTest < Redmine::ApiTest::Base
-  fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
-           :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
-           :attachments, :custom_fields, :custom_values, :time_entries, :issue_categories
-
-  def setup
-    Setting.rest_api_enabled = '1'
-    set_tmp_attachments_directory
-  end
-
-  # TODO: A private project is needed because should_allow_api_authentication
-  # actually tests that authentication is *required*, not just allowed
-  should_allow_api_authentication(:get, "/projects/2.xml")
-  should_allow_api_authentication(:get, "/projects/2.json")
-  should_allow_api_authentication(:post,
-                                  '/projects.xml',
-                                  {:project => {:name => 'API test', :identifier => 'api-test'}},
-                                  {:success_code => :created})
-  should_allow_api_authentication(:put,
-                                  '/projects/2.xml',
-                                  {:project => {:name => 'API update'}},
-                                  {:success_code => :ok})
-  should_allow_api_authentication(:delete,
-                                  '/projects/2.xml',
-                                  {},
-                                  {:success_code => :ok})
-
-  test "GET /projects.xml should return projects" do
-    get '/projects.xml'
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-
-    assert_tag :tag => 'projects',
-      :child => {:tag => 'project', :child => {:tag => 'id', :content => '1'}}
-  end
-
-  test "GET /projects.json should return projects" do
-    get '/projects.json'
-    assert_response :success
-    assert_equal 'application/json', @response.content_type
-
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json
-    assert_kind_of Array, json['projects']
-    assert_kind_of Hash, json['projects'].first
-    assert json['projects'].first.has_key?('id')
-  end
-
-  test "GET /projects/:id.xml should return the project" do
-    get '/projects/1.xml'
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-
-    assert_tag :tag => 'project',
-      :child => {:tag => 'id', :content => '1'}
-    assert_tag :tag => 'custom_field',
-      :attributes => {:name => 'Development status'}, :content => 'Stable'
-
-    assert_no_tag 'trackers'
-    assert_no_tag 'issue_categories'
-  end
-
-  test "GET /projects/:id.json should return the project" do
-    get '/projects/1.json'
-
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json
-    assert_kind_of Hash, json['project']
-    assert_equal 1, json['project']['id']
-  end
-
-  test "GET /projects/:id.xml with hidden custom fields should not display hidden custom fields" do
-    ProjectCustomField.find_by_name('Development status').update_attribute :visible, false
-
-    get '/projects/1.xml'
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-
-    assert_no_tag 'custom_field',
-      :attributes => {:name => 'Development status'}
-  end
-
-  test "GET /projects/:id.xml with include=issue_categories should return categories" do
-    get '/projects/1.xml?include=issue_categories'
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-
-    assert_tag 'issue_categories',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'issue_category',
-        :attributes => {
-          :id => '2',
-          :name => 'Recipes'
-        }
-      }
-  end
-
-  test "GET /projects/:id.xml with include=trackers should return trackers" do
-    get '/projects/1.xml?include=trackers'
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-
-    assert_tag 'trackers',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'tracker',
-        :attributes => {
-          :id => '2',
-          :name => 'Feature request'
-        }
-      }
-  end
-
-  test "POST /projects.xml with valid parameters should create the project" do
-    Setting.default_projects_modules = ['issue_tracking', 'repository']
-
-    assert_difference('Project.count') do
-      post '/projects.xml',
-        {:project => {:name => 'API test', :identifier => 'api-test'}},
-        credentials('admin')
-    end
-
-    project = Project.first(:order => 'id DESC')
-    assert_equal 'API test', project.name
-    assert_equal 'api-test', project.identifier
-    assert_equal ['issue_tracking', 'repository'], project.enabled_module_names.sort
-    assert_equal Tracker.all.size, project.trackers.size
-
-    assert_response :created
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'project', :child => {:tag => 'id', :content => project.id.to_s}
-  end
-
-  test "POST /projects.xml should accept enabled_module_names attribute" do
-    assert_difference('Project.count') do
-      post '/projects.xml',
-        {:project => {:name => 'API test', :identifier => 'api-test', :enabled_module_names => ['issue_tracking', 'news', 'time_tracking']}},
-        credentials('admin')
-    end
-
-    project = Project.first(:order => 'id DESC')
-    assert_equal ['issue_tracking', 'news', 'time_tracking'], project.enabled_module_names.sort
-  end
-
-  test "POST /projects.xml should accept tracker_ids attribute" do
-    assert_difference('Project.count') do
-      post '/projects.xml',
-        {:project => {:name => 'API test', :identifier => 'api-test', :tracker_ids => [1, 3]}},
-        credentials('admin')
-    end
-
-    project = Project.first(:order => 'id DESC')
-    assert_equal [1, 3], project.trackers.map(&:id).sort
-  end
-
-  test "POST /projects.xml with invalid parameters should return errors" do
-    assert_no_difference('Project.count') do
-      post '/projects.xml', {:project => {:name => 'API test'}}, credentials('admin')
-    end
-
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'errors', :child => {:tag => 'error', :content => "Identifier can't be blank"}
-  end
-
-  test "PUT /projects/:id.xml with valid parameters should update the project" do
-    assert_no_difference 'Project.count' do
-      put '/projects/2.xml', {:project => {:name => 'API update'}}, credentials('jsmith')
-    end
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_equal 'application/xml', @response.content_type
-    project = Project.find(2)
-    assert_equal 'API update', project.name
-  end
-
-  test "PUT /projects/:id.xml should accept enabled_module_names attribute" do
-    assert_no_difference 'Project.count' do
-      put '/projects/2.xml', {:project => {:name => 'API update', :enabled_module_names => ['issue_tracking', 'news', 'time_tracking']}}, credentials('admin')
-    end
-    assert_response :ok
-    assert_equal '', @response.body
-    project = Project.find(2)
-    assert_equal ['issue_tracking', 'news', 'time_tracking'], project.enabled_module_names.sort
-  end
-
-  test "PUT /projects/:id.xml should accept tracker_ids attribute" do
-    assert_no_difference 'Project.count' do
-      put '/projects/2.xml', {:project => {:name => 'API update', :tracker_ids => [1, 3]}}, credentials('admin')
-    end
-    assert_response :ok
-    assert_equal '', @response.body
-    project = Project.find(2)
-    assert_equal [1, 3], project.trackers.map(&:id).sort
-  end
-
-  test "PUT /projects/:id.xml with invalid parameters should return errors" do
-    assert_no_difference('Project.count') do
-      put '/projects/2.xml', {:project => {:name => ''}}, credentials('admin')
-    end
-
-    assert_response :unprocessable_entity
-    assert_equal 'application/xml', @response.content_type
-    assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
-  end
-
-  test "DELETE /projects/:id.xml should delete the project" do
-    assert_difference('Project.count',-1) do
-      delete '/projects/2.xml', {}, credentials('admin')
-    end
-    assert_response :ok
-    assert_equal '', @response.body
-    assert_nil Project.find_by_id(2)
-  end
-end
--- a/.svn/pristine/e8/e8aa327e67355ce663b09a685e02ede1d8c6edd6.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Helpers
-    class TimeReport
-      attr_reader :criteria, :columns, :hours, :total_hours, :periods
-
-      def initialize(project, issue, criteria, columns, time_entry_scope)
-        @project = project
-        @issue = issue
-
-        @criteria = criteria || []
-        @criteria = @criteria.select{|criteria| available_criteria.has_key? criteria}
-        @criteria.uniq!
-        @criteria = @criteria[0,3]
-
-        @columns = (columns && %w(year month week day).include?(columns)) ? columns : 'month'
-        @scope = time_entry_scope
-
-        run
-      end
-
-      def available_criteria
-        @available_criteria || load_available_criteria
-      end
-
-      private
-
-      def run
-        unless @criteria.empty?
-          time_columns = %w(tyear tmonth tweek spent_on)
-          @hours = []
-          @scope.sum(:hours,
-              :include => [:issue, :activity],
-              :group => @criteria.collect{|criteria| @available_criteria[criteria][:sql]} + time_columns,
-              :joins => @criteria.collect{|criteria| @available_criteria[criteria][:joins]}.compact).each do |hash, hours|
-            h = {'hours' => hours}
-            (@criteria + time_columns).each_with_index do |name, i|
-              h[name] = hash[i]
-            end
-            @hours << h
-          end
-          
-          @hours.each do |row|
-            case @columns
-            when 'year'
-              row['year'] = row['tyear']
-            when 'month'
-              row['month'] = "#{row['tyear']}-#{row['tmonth']}"
-            when 'week'
-              row['week'] = "#{row['spent_on'].cwyear}-#{row['tweek']}"
-            when 'day'
-              row['day'] = "#{row['spent_on']}"
-            end
-          end
-          
-          min = @hours.collect {|row| row['spent_on']}.min
-          @from = min ? min.to_date : Date.today
-
-          max = @hours.collect {|row| row['spent_on']}.max
-          @to = max ? max.to_date : Date.today
-          
-          @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
-
-          @periods = []
-          # Date#at_beginning_of_ not supported in Rails 1.2.x
-          date_from = @from.to_time
-          # 100 columns max
-          while date_from <= @to.to_time && @periods.length < 100
-            case @columns
-            when 'year'
-              @periods << "#{date_from.year}"
-              date_from = (date_from + 1.year).at_beginning_of_year
-            when 'month'
-              @periods << "#{date_from.year}-#{date_from.month}"
-              date_from = (date_from + 1.month).at_beginning_of_month
-            when 'week'
-              @periods << "#{date_from.to_date.cwyear}-#{date_from.to_date.cweek}"
-              date_from = (date_from + 7.day).at_beginning_of_week
-            when 'day'
-              @periods << "#{date_from.to_date}"
-              date_from = date_from + 1.day
-            end
-          end
-        end
-      end
-
-      def load_available_criteria
-        @available_criteria = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id",
-                                              :klass => Project,
-                                              :label => :label_project},
-                                 'status' => {:sql => "#{Issue.table_name}.status_id",
-                                              :klass => IssueStatus,
-                                              :label => :field_status},
-                                 'version' => {:sql => "#{Issue.table_name}.fixed_version_id",
-                                              :klass => Version,
-                                              :label => :label_version},
-                                 'category' => {:sql => "#{Issue.table_name}.category_id",
-                                                :klass => IssueCategory,
-                                                :label => :field_category},
-                                 'user' => {:sql => "#{TimeEntry.table_name}.user_id",
-                                             :klass => User,
-                                             :label => :label_user},
-                                 'tracker' => {:sql => "#{Issue.table_name}.tracker_id",
-                                              :klass => Tracker,
-                                              :label => :label_tracker},
-                                 'activity' => {:sql => "#{TimeEntry.table_name}.activity_id",
-                                               :klass => TimeEntryActivity,
-                                               :label => :label_activity},
-                                 'issue' => {:sql => "#{TimeEntry.table_name}.issue_id",
-                                             :klass => Issue,
-                                             :label => :label_issue}
-                               }
-
-        # Add time entry custom fields
-        custom_fields = TimeEntryCustomField.all
-        # Add project custom fields
-        custom_fields += ProjectCustomField.all
-        # Add issue custom fields
-        custom_fields += (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields)
-        # Add time entry activity custom fields
-        custom_fields += TimeEntryActivityCustomField.all
-
-        # Add list and boolean custom fields as available criteria
-        custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
-          @available_criteria["cf_#{cf.id}"] = {:sql => "#{cf.join_alias}.value",
-                                                 :joins => cf.join_for_order_statement,
-                                                 :format => cf.field_format,
-                                                 :label => cf.name}
-        end
-
-        @available_criteria
-      end
-    end
-  end
-end
--- a/.svn/pristine/e8/e8f5719ac8290bf42290de6a5ad4ab322d08803d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class SearchHelperTest < ActionView::TestCase
-  include SearchHelper
-  include Redmine::I18n
-  include ERB::Util
-
-  def test_highlight_single_token
-    assert_equal 'This is a <span class="highlight token-0">token</span>.',
-                 highlight_tokens('This is a token.', %w(token))
-  end
-
-  def test_highlight_multiple_tokens
-    assert_equal 'This is a <span class="highlight token-0">token</span> and <span class="highlight token-1">another</span> <span class="highlight token-0">token</span>.',
-                 highlight_tokens('This is a token and another token.', %w(token another))
-  end
-
-  def test_highlight_should_not_exceed_maximum_length
-    s = (('1234567890' * 100) + ' token ') * 100
-    r = highlight_tokens(s, %w(token))
-    assert r.include?('<span class="highlight token-0">token</span>')
-    assert r.length <= 1300
-  end
-
-  def test_highlight_multibyte
-    s = ('й' * 200) + ' token ' + ('й' * 200)
-    r = highlight_tokens(s, %w(token))
-    assert_equal  ('й' * 45) + ' ... ' + ('й' * 44) + ' <span class="highlight token-0">token</span> ' + ('й' * 44) + ' ... ' + ('й' * 45), r
-  end
-end
--- a/.svn/pristine/e9/e9895d42866e8fe662252fd7f421c7dd0505d9a5.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/views/builders/json'
-require 'redmine/views/builders/xml'
-
-module Redmine
-  module Views
-    module Builders
-      def self.for(format, request, response, &block)
-        builder = case format
-          when 'xml',  :xml;  Builders::Xml.new(request, response)
-          when 'json', :json; Builders::Json.new(request, response)
-          else; raise "No builder for format #{format}"
-        end
-        if block
-          block.call(builder)
-        else
-          builder
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/ea/ea992c47f8d2112ec52008294e35e2cd3e7c1b5f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class GroupCustomField < CustomField
-  def type_name
-    :label_group_plural
-  end
-end
--- a/.svn/pristine/ea/eab1cd7b12156ed469f5471880818f7528dfed63.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Utils
-    class << self
-      # Returns the relative root url of the application
-      def relative_url_root
-        ActionController::Base.respond_to?('relative_url_root') ?
-          ActionController::Base.relative_url_root.to_s :
-          ActionController::Base.config.relative_url_root.to_s
-      end
-
-      # Sets the relative root url of the application
-      def relative_url_root=(arg)
-        if ActionController::Base.respond_to?('relative_url_root=')
-          ActionController::Base.relative_url_root=arg
-        else
-          ActionController::Base.config.relative_url_root = arg
-        end
-      end
-
-      # Generates a n bytes random hex string
-      # Example:
-      #   random_hex(4) # => "89b8c729"
-      def random_hex(n)
-        SecureRandom.hex(n)
-      end
-    end
-
-    module Shell
-      def shell_quote(str)
-        if Redmine::Platform.mswin?
-          '"' + str.gsub(/"/, '\\"') + '"'
-        else
-          "'" + str.gsub(/'/, "'\"'\"'") + "'"
-        end
-      end
-    end
-
-    module DateCalculation
-      # Returns the number of working days between from and to
-      def working_days(from, to)
-        days = (to - from).to_i
-        if days > 0
-          weeks = days / 7
-          result = weeks * (7 - non_working_week_days.size)
-          days_left = days - weeks * 7
-          start_cwday = from.cwday
-          days_left.times do |i|
-            unless non_working_week_days.include?(((start_cwday + i - 1) % 7) + 1)
-              result += 1
-            end
-          end
-          result
-        else
-          0
-        end
-      end
-
-      # Adds working days to the given date
-      def add_working_days(date, working_days)
-        if working_days > 0
-          weeks = working_days / (7 - non_working_week_days.size)
-          result = weeks * 7
-          days_left = working_days - weeks * (7 - non_working_week_days.size)
-          cwday = date.cwday
-          while days_left > 0
-            cwday += 1
-            unless non_working_week_days.include?(((cwday - 1) % 7) + 1)
-              days_left -= 1
-            end
-            result += 1
-          end
-          next_working_date(date + result)
-        else
-          date
-        end
-      end
-
-      # Returns the date of the first day on or after the given date that is a working day
-      def next_working_date(date)
-        cwday = date.cwday
-        days = 0
-        while non_working_week_days.include?(((cwday + days - 1) % 7) + 1)
-          days += 1
-        end
-        date + days
-      end
-
-      # Returns the index of non working week days (1=monday, 7=sunday)
-      def non_working_week_days
-        @non_working_week_days ||= begin
-          days = Setting.non_working_week_days
-          if days.is_a?(Array) && days.size < 7
-            days.map(&:to_i)
-          else
-            []
-          end
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/eb/eb6cb0f6889f62dec8dd9c85a7fb5ed905af22c8.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../test_case', __FILE__)
-require 'tmpdir'
-
-class RedminePmTest::RepositoryGitTest < RedminePmTest::TestCase
-  fixtures :projects, :users, :members, :roles, :member_roles
-
-  GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
-
-  def test_anonymous_read_on_public_repo_with_permission_should_succeed
-    assert_success "ls-remote", git_url
-  end
-
-  def test_anonymous_read_on_public_repo_without_permission_should_fail
-    Role.anonymous.remove_permission! :browse_repository
-    assert_failure "ls-remote", git_url
-  end
-
-  def test_invalid_credentials_should_fail
-    Project.find(1).update_attribute :is_public, false
-    with_credentials "dlopper", "foo" do
-      assert_success "ls-remote", git_url
-    end
-    with_credentials "dlopper", "wrong" do
-      assert_failure "ls-remote", git_url
-    end
-  end
-
-  def test_clone
-    Dir.mktmpdir do |dir|
-      Dir.chdir(dir) do
-        assert_success "clone", git_url
-      end
-    end
-  end
-
-  def test_write_commands
-    Role.find(2).add_permission! :commit_access
-    filename = random_filename
-
-    Dir.mktmpdir do |dir|
-      assert_success "clone", git_url, dir
-      Dir.chdir(dir) do
-        f = File.new(File.join(dir, filename), "w")
-        f.write "test file content"
-        f.close
-
-        with_credentials "dlopper", "foo" do
-          assert_success "add", filename
-          assert_success "commit -a --message Committing_a_file"
-          assert_success "push", git_url, "--all"
-        end
-      end
-    end
-
-    Dir.mktmpdir do |dir|
-      assert_success "clone", git_url, dir
-      Dir.chdir(dir) do
-        assert File.exists?(File.join(dir, "#{filename}"))
-      end
-    end
-  end
-
-  protected
-
-  def execute(*args)
-    a = [GIT_BIN]
-    super a, *args
-  end
-
-  def git_url(path=nil)
-    host = ENV['REDMINE_TEST_DAV_SERVER'] || '127.0.0.1'
-    credentials = nil
-    if username && password
-      credentials = "#{username}:#{password}"
-    end
-    url = "http://#{credentials}@#{host}/git/ecookbook"
-    url << "/#{path}" if path
-    url
-  end
-end
--- a/.svn/pristine/ec/ec7c0d826b7228b3557fac4fa00ebff6a515cfda.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1135 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class UserTest < ActiveSupport::TestCase
-  fixtures :users, :members, :projects, :roles, :member_roles, :auth_sources,
-            :trackers, :issue_statuses,
-            :projects_trackers,
-            :watchers,
-            :issue_categories, :enumerations, :issues,
-            :journals, :journal_details,
-            :groups_users,
-            :enabled_modules
-
-  def setup
-    @admin = User.find(1)
-    @jsmith = User.find(2)
-    @dlopper = User.find(3)
-  end
-
-  def test_sorted_scope_should_sort_user_by_display_name
-    assert_equal User.all.map(&:name).map(&:downcase).sort, User.sorted.all.map(&:name).map(&:downcase)
-  end
-
-  def test_generate
-    User.generate!(:firstname => 'Testing connection')
-    User.generate!(:firstname => 'Testing connection')
-    assert_equal 2, User.where(:firstname => 'Testing connection').count
-  end
-
-  def test_truth
-    assert_kind_of User, @jsmith
-  end
-
-  def test_mail_should_be_stripped
-    u = User.new
-    u.mail = " foo@bar.com  "
-    assert_equal "foo@bar.com", u.mail
-  end
-
-  def test_mail_validation
-    u = User.new
-    u.mail = ''
-    assert !u.valid?
-    assert_include I18n.translate('activerecord.errors.messages.blank'), u.errors[:mail]
-  end
-
-  def test_login_length_validation
-    user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
-    user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
-    assert !user.valid?
-
-    user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
-    assert user.valid?
-    assert user.save
-  end
-
-  def test_generate_password_should_respect_minimum_password_length
-    with_settings :password_min_length => 15 do
-      user = User.generate!(:generate_password => true)
-      assert user.password.length >= 15
-    end
-  end
-
-  def test_generate_password_should_not_generate_password_with_less_than_10_characters
-    with_settings :password_min_length => 4 do
-      user = User.generate!(:generate_password => true)
-      assert user.password.length >= 10
-    end
-  end
-
-  def test_generate_password_on_create_should_set_password
-    user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
-    user.login = "newuser"
-    user.generate_password = true
-    assert user.save
-
-    password = user.password
-    assert user.check_password?(password)
-  end
-
-  def test_generate_password_on_update_should_update_password
-    user = User.find(2)
-    hash = user.hashed_password
-    user.generate_password = true
-    assert user.save
-
-    password = user.password
-    assert user.check_password?(password)
-    assert_not_equal hash, user.reload.hashed_password
-  end
-
-  def test_create
-    user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
-
-    user.login = "jsmith"
-    user.password, user.password_confirmation = "password", "password"
-    # login uniqueness
-    assert !user.save
-    assert_equal 1, user.errors.count
-
-    user.login = "newuser"
-    user.password, user.password_confirmation = "password", "pass"
-    # password confirmation
-    assert !user.save
-    assert_equal 1, user.errors.count
-
-    user.password, user.password_confirmation = "password", "password"
-    assert user.save
-  end
-
-  def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
-    @user1 = User.generate!
-    assert_equal 'only_my_events', @user1.mail_notification
-    with_settings :default_notification_option => 'all' do
-      @user2 = User.generate!
-      assert_equal 'all', @user2.mail_notification
-    end
-  end
-
-  def test_user_login_should_be_case_insensitive
-    u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
-    u.login = 'newuser'
-    u.password, u.password_confirmation = "password", "password"
-    assert u.save
-    u = User.new(:firstname => "Similar", :lastname => "User", :mail => "similaruser@somenet.foo")
-    u.login = 'NewUser'
-    u.password, u.password_confirmation = "password", "password"
-    assert !u.save
-    assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
-  end
-
-  def test_mail_uniqueness_should_not_be_case_sensitive
-    u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
-    u.login = 'newuser1'
-    u.password, u.password_confirmation = "password", "password"
-    assert u.save
-
-    u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
-    u.login = 'newuser2'
-    u.password, u.password_confirmation = "password", "password"
-    assert !u.save
-    assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:mail]
-  end
-
-  def test_update
-    assert_equal "admin", @admin.login
-    @admin.login = "john"
-    assert @admin.save, @admin.errors.full_messages.join("; ")
-    @admin.reload
-    assert_equal "john", @admin.login
-  end
-
-  def test_update_should_not_fail_for_legacy_user_with_different_case_logins
-    u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
-    u1.login = 'newuser1'
-    assert u1.save
-
-    u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
-    u2.login = 'newuser1'
-    assert u2.save(:validate => false)
-
-    user = User.find(u2.id)
-    user.firstname = "firstname"
-    assert user.save, "Save failed"
-  end
-
-  def test_destroy_should_delete_members_and_roles
-    members = Member.find_all_by_user_id(2)
-    ms = members.size
-    rs = members.collect(&:roles).flatten.size
-
-    assert_difference 'Member.count', - ms do
-      assert_difference 'MemberRole.count', - rs do
-        User.find(2).destroy
-      end
-    end
-
-    assert_nil User.find_by_id(2)
-    assert Member.find_all_by_user_id(2).empty?
-  end
-
-  def test_destroy_should_update_attachments
-    attachment = Attachment.create!(:container => Project.find(1),
-      :file => uploaded_test_file("testfile.txt", "text/plain"),
-      :author_id => 2)
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous, attachment.reload.author
-  end
-
-  def test_destroy_should_update_comments
-    comment = Comment.create!(
-      :commented => News.create!(:project_id => 1, :author_id => 1, :title => 'foo', :description => 'foo'),
-      :author => User.find(2),
-      :comments => 'foo'
-    )
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous, comment.reload.author
-  end
-
-  def test_destroy_should_update_issues
-    issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo')
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous, issue.reload.author
-  end
-
-  def test_destroy_should_unassign_issues
-    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_nil issue.reload.assigned_to
-  end
-
-  def test_destroy_should_update_journals
-    issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo')
-    issue.init_journal(User.find(2), "update")
-    issue.save!
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous, issue.journals.first.reload.user
-  end
-
-  def test_destroy_should_update_journal_details_old_value
-    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
-    issue.init_journal(User.find(1), "update")
-    issue.assigned_to_id = nil
-    assert_difference 'JournalDetail.count' do
-      issue.save!
-    end
-    journal_detail = JournalDetail.first(:order => 'id DESC')
-    assert_equal '2', journal_detail.old_value
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
-  end
-
-  def test_destroy_should_update_journal_details_value
-    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo')
-    issue.init_journal(User.find(1), "update")
-    issue.assigned_to_id = 2
-    assert_difference 'JournalDetail.count' do
-      issue.save!
-    end
-    journal_detail = JournalDetail.first(:order => 'id DESC')
-    assert_equal '2', journal_detail.value
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous.id.to_s, journal_detail.reload.value
-  end
-
-  def test_destroy_should_update_messages
-    board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
-    message = Message.create!(:board_id => board.id, :author_id => 2, :subject => 'foo', :content => 'foo')
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous, message.reload.author
-  end
-
-  def test_destroy_should_update_news
-    news = News.create!(:project_id => 1, :author_id => 2, :title => 'foo', :description => 'foo')
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous, news.reload.author
-  end
-
-  def test_destroy_should_delete_private_queries
-    query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
-    query.project_id = 1
-    query.user_id = 2
-    query.save!
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_nil Query.find_by_id(query.id)
-  end
-
-  def test_destroy_should_update_public_queries
-    query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
-    query.project_id = 1
-    query.user_id = 2
-    query.save!
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous, query.reload.user
-  end
-
-  def test_destroy_should_update_time_entries
-    entry = TimeEntry.new(:hours => '2', :spent_on => Date.today, :activity => TimeEntryActivity.create!(:name => 'foo'))
-    entry.project_id = 1
-    entry.user_id = 2
-    entry.save!
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous, entry.reload.user
-  end
-
-  def test_destroy_should_delete_tokens
-    token = Token.create!(:user_id => 2, :value => 'foo')
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_nil Token.find_by_id(token.id)
-  end
-
-  def test_destroy_should_delete_watchers
-    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo')
-    watcher = Watcher.create!(:user_id => 2, :watchable => issue)
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_nil Watcher.find_by_id(watcher.id)
-  end
-
-  def test_destroy_should_update_wiki_contents
-    wiki_content = WikiContent.create!(
-      :text => 'foo',
-      :author_id => 2,
-      :page => WikiPage.create!(:title => 'Foo', :wiki => Wiki.create!(:project_id => 1, :start_page => 'Start'))
-    )
-    wiki_content.text = 'bar'
-    assert_difference 'WikiContent::Version.count' do
-      wiki_content.save!
-    end
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_equal User.anonymous, wiki_content.reload.author
-    wiki_content.versions.each do |version|
-      assert_equal User.anonymous, version.reload.author
-    end
-  end
-
-  def test_destroy_should_nullify_issue_categories
-    category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_nil category.reload.assigned_to_id
-  end
-
-  def test_destroy_should_nullify_changesets
-    changeset = Changeset.create!(
-      :repository => Repository::Subversion.create!(
-        :project_id => 1,
-        :url => 'file:///tmp',
-        :identifier => 'tmp'
-      ),
-      :revision => '12',
-      :committed_on => Time.now,
-      :committer => 'jsmith'
-      )
-    assert_equal 2, changeset.user_id
-
-    User.find(2).destroy
-    assert_nil User.find_by_id(2)
-    assert_nil changeset.reload.user_id
-  end
-
-  def test_anonymous_user_should_not_be_destroyable
-    assert_no_difference 'User.count' do
-      assert_equal false, User.anonymous.destroy
-    end
-  end
-
-  def test_validate_login_presence
-    @admin.login = ""
-    assert !@admin.save
-    assert_equal 1, @admin.errors.count
-  end
-
-  def test_validate_mail_notification_inclusion
-    u = User.new
-    u.mail_notification = 'foo'
-    u.save
-    assert_not_equal [], u.errors[:mail_notification]
-  end
-
-  def test_password
-    user = User.try_to_login("admin", "admin")
-    assert_kind_of User, user
-    assert_equal "admin", user.login
-    user.password = "hello123"
-    assert user.save
-
-    user = User.try_to_login("admin", "hello123")
-    assert_kind_of User, user
-    assert_equal "admin", user.login
-  end
-
-  def test_validate_password_length
-    with_settings :password_min_length => '100' do
-      user = User.new(:firstname => "new100", :lastname => "user100", :mail => "newuser100@somenet.foo")
-      user.login = "newuser100"
-      user.password, user.password_confirmation = "password100", "password100"
-      assert !user.save
-      assert_equal 1, user.errors.count
-    end
-  end
-
-  def test_name_format
-    assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
-    assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
-    with_settings :user_format => :firstname_lastname do
-      assert_equal 'John Smith', @jsmith.reload.name
-    end
-    with_settings :user_format => :username do
-      assert_equal 'jsmith', @jsmith.reload.name
-    end
-    with_settings :user_format => :lastname do
-      assert_equal 'Smith', @jsmith.reload.name
-    end
-  end
-
-  def test_today_should_return_the_day_according_to_user_time_zone
-    preference = User.find(1).pref
-    date = Date.new(2012, 05, 15)
-    time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
-    Date.stubs(:today).returns(date)
-    Time.stubs(:now).returns(time)
-
-    preference.update_attribute :time_zone, 'Baku' # UTC+4
-    assert_equal '2012-05-16', User.find(1).today.to_s
-
-    preference.update_attribute :time_zone, 'La Paz' # UTC-4
-    assert_equal '2012-05-15', User.find(1).today.to_s
-
-    preference.update_attribute :time_zone, ''
-    assert_equal '2012-05-15', User.find(1).today.to_s
-  end
-
-  def test_time_to_date_should_return_the_date_according_to_user_time_zone
-    preference = User.find(1).pref
-    time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
-
-    preference.update_attribute :time_zone, 'Baku' # UTC+4
-    assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
-
-    preference.update_attribute :time_zone, 'La Paz' # UTC-4
-    assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
-
-    preference.update_attribute :time_zone, ''
-    assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
-  end
-
-  def test_fields_for_order_statement_should_return_fields_according_user_format_setting
-    with_settings :user_format => 'lastname_coma_firstname' do
-      assert_equal ['users.lastname', 'users.firstname', 'users.id'], User.fields_for_order_statement
-    end
-  end
-
-  def test_fields_for_order_statement_width_table_name_should_prepend_table_name
-    with_settings :user_format => 'lastname_firstname' do
-      assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'], User.fields_for_order_statement('authors')
-    end
-  end
-
-  def test_fields_for_order_statement_with_blank_format_should_return_default
-    with_settings :user_format => '' do
-      assert_equal ['users.firstname', 'users.lastname', 'users.id'], User.fields_for_order_statement
-    end
-  end
-
-  def test_fields_for_order_statement_with_invalid_format_should_return_default
-    with_settings :user_format => 'foo' do
-      assert_equal ['users.firstname', 'users.lastname', 'users.id'], User.fields_for_order_statement
-    end
-  end
-
-  test ".try_to_login with good credentials should return the user" do
-    user = User.try_to_login("admin", "admin")
-    assert_kind_of User, user
-    assert_equal "admin", user.login
-  end
-
-  test ".try_to_login with wrong credentials should return nil" do
-    assert_nil User.try_to_login("admin", "foo")
-  end
-
-  def test_try_to_login_with_locked_user_should_return_nil
-    @jsmith.status = User::STATUS_LOCKED
-    @jsmith.save!
-
-    user = User.try_to_login("jsmith", "jsmith")
-    assert_equal nil, user
-  end
-
-  def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
-    @jsmith.status = User::STATUS_LOCKED
-    @jsmith.save!
-
-    user = User.try_to_login("jsmith", "jsmith", false)
-    assert_equal @jsmith, user
-  end
-
-  test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
-    user = User.try_to_login("AdMin", "admin")
-    assert_kind_of User, user
-    assert_equal "admin", user.login
-  end
-
-  test ".try_to_login should select the exact matching user first" do
-    case_sensitive_user = User.generate! do |user|
-      user.password = "admin123"
-    end
-    # bypass validations to make it appear like existing data
-    case_sensitive_user.update_attribute(:login, 'ADMIN')
-
-    user = User.try_to_login("ADMIN", "admin123")
-    assert_kind_of User, user
-    assert_equal "ADMIN", user.login
-  end
-
-  if ldap_configured?
-    context "#try_to_login using LDAP" do
-      context "with failed connection to the LDAP server" do
-        should "return nil" do
-          @auth_source = AuthSourceLdap.find(1)
-          AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
-
-          assert_equal nil, User.try_to_login('edavis', 'wrong')
-        end
-      end
-
-      context "with an unsuccessful authentication" do
-        should "return nil" do
-          assert_equal nil, User.try_to_login('edavis', 'wrong')
-        end
-      end
-
-      context "binding with user's account" do
-        setup do
-          @auth_source = AuthSourceLdap.find(1)
-          @auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
-          @auth_source.account_password = ''
-          @auth_source.save!
-
-          @ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
-          @ldap_user.login = 'example1'
-          @ldap_user.save!
-        end
-
-        context "with a successful authentication" do
-          should "return the user" do
-            assert_equal @ldap_user, User.try_to_login('example1', '123456')
-          end
-        end
-
-        context "with an unsuccessful authentication" do
-          should "return nil" do
-            assert_nil User.try_to_login('example1', '11111')
-          end
-        end
-      end
-
-      context "on the fly registration" do
-        setup do
-          @auth_source = AuthSourceLdap.find(1)
-          @auth_source.update_attribute :onthefly_register, true
-        end
-
-        context "with a successful authentication" do
-          should "create a new user account if it doesn't exist" do
-            assert_difference('User.count') do
-              user = User.try_to_login('edavis', '123456')
-              assert !user.admin?
-            end
-          end
-
-          should "retrieve existing user" do
-            user = User.try_to_login('edavis', '123456')
-            user.admin = true
-            user.save!
-
-            assert_no_difference('User.count') do
-              user = User.try_to_login('edavis', '123456')
-              assert user.admin?
-            end
-          end
-        end
-
-        context "binding with user's account" do
-          setup do
-            @auth_source = AuthSourceLdap.find(1)
-            @auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
-            @auth_source.account_password = ''
-            @auth_source.save!
-          end
-
-          context "with a successful authentication" do
-            should "create a new user account if it doesn't exist" do
-              assert_difference('User.count') do
-                user = User.try_to_login('example1', '123456')
-                assert_kind_of User, user
-              end
-            end
-          end
-
-          context "with an unsuccessful authentication" do
-            should "return nil" do
-              assert_nil User.try_to_login('example1', '11111')
-            end
-          end
-        end
-      end
-    end
-
-  else
-    puts "Skipping LDAP tests."
-  end
-
-  def test_create_anonymous
-    AnonymousUser.delete_all
-    anon = User.anonymous
-    assert !anon.new_record?
-    assert_kind_of AnonymousUser, anon
-  end
-
-  def test_ensure_single_anonymous_user
-    AnonymousUser.delete_all
-    anon1 = User.anonymous
-    assert !anon1.new_record?
-    assert_kind_of AnonymousUser, anon1
-    anon2 = AnonymousUser.create(
-                :lastname => 'Anonymous', :firstname => '',
-                :mail => '', :login => '', :status => 0)
-    assert_equal 1, anon2.errors.count
-  end
-
-  def test_rss_key
-    assert_nil @jsmith.rss_token
-    key = @jsmith.rss_key
-    assert_equal 40, key.length
-
-    @jsmith.reload
-    assert_equal key, @jsmith.rss_key
-  end
-
-  def test_rss_key_should_not_be_generated_twice
-    assert_difference 'Token.count', 1 do
-      key1 = @jsmith.rss_key
-      key2 = @jsmith.rss_key
-      assert_equal key1, key2
-    end
-  end
-
-  def test_api_key_should_not_be_generated_twice
-    assert_difference 'Token.count', 1 do
-      key1 = @jsmith.api_key
-      key2 = @jsmith.api_key
-      assert_equal key1, key2
-    end
-  end
-
-  test "#api_key should generate a new one if the user doesn't have one" do
-    user = User.generate!(:api_token => nil)
-    assert_nil user.api_token
-
-    key = user.api_key
-    assert_equal 40, key.length
-    user.reload
-    assert_equal key, user.api_key
-  end
-
-  test "#api_key should return the existing api token value" do
-    user = User.generate!
-    token = Token.create!(:action => 'api')
-    user.api_token = token
-    assert user.save
-
-    assert_equal token.value, user.api_key
-  end
-
-  test "#find_by_api_key should return nil if no matching key is found" do
-    assert_nil User.find_by_api_key('zzzzzzzzz')
-  end
-
-  test "#find_by_api_key should return nil if the key is found for an inactive user" do
-    user = User.generate!
-    user.status = User::STATUS_LOCKED
-    token = Token.create!(:action => 'api')
-    user.api_token = token
-    user.save
-
-    assert_nil User.find_by_api_key(token.value)
-  end
-
-  test "#find_by_api_key should return the user if the key is found for an active user" do
-    user = User.generate!
-    token = Token.create!(:action => 'api')
-    user.api_token = token
-    user.save
-
-    assert_equal user, User.find_by_api_key(token.value)
-  end
-
-  def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
-    user = User.find_by_login("admin")
-    user.password = "admin"
-    assert user.save(:validate => false)
-
-    assert_equal false, User.default_admin_account_changed?
-  end
-
-  def test_default_admin_account_changed_should_return_true_if_password_was_changed
-    user = User.find_by_login("admin")
-    user.password = "newpassword"
-    user.save!
-
-    assert_equal true, User.default_admin_account_changed?
-  end
-
-  def test_default_admin_account_changed_should_return_true_if_account_is_disabled
-    user = User.find_by_login("admin")
-    user.password = "admin"
-    user.status = User::STATUS_LOCKED
-    assert user.save(:validate => false)
-
-    assert_equal true, User.default_admin_account_changed?
-  end
-
-  def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
-    user = User.find_by_login("admin")
-    user.destroy
-
-    assert_equal true, User.default_admin_account_changed?
-  end
-
-  def test_membership_with_project_should_return_membership
-    project = Project.find(1)
-
-    membership = @jsmith.membership(project)
-    assert_kind_of Member, membership
-    assert_equal @jsmith, membership.user
-    assert_equal project, membership.project
-  end
-
-  def test_membership_with_project_id_should_return_membership
-    project = Project.find(1)
-
-    membership = @jsmith.membership(1)
-    assert_kind_of Member, membership
-    assert_equal @jsmith, membership.user
-    assert_equal project, membership.project
-  end
-
-  def test_membership_for_non_member_should_return_nil
-    project = Project.find(1)
-
-    user = User.generate!
-    membership = user.membership(1)
-    assert_nil membership
-  end
-
-  def test_roles_for_project
-    # user with a role
-    roles = @jsmith.roles_for_project(Project.find(1))
-    assert_kind_of Role, roles.first
-    assert_equal "Manager", roles.first.name
-
-    # user with no role
-    assert_nil @dlopper.roles_for_project(Project.find(2)).detect {|role| role.member?}
-  end
-
-  def test_projects_by_role_for_user_with_role
-    user = User.find(2)
-    assert_kind_of Hash, user.projects_by_role
-    assert_equal 2, user.projects_by_role.size
-    assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
-    assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
-  end
-
-  def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
-    user = User.find(2)
-    assert_equal [], user.projects_by_role[Role.find(3)]
-    # should not update the hash
-    assert_nil user.projects_by_role.values.detect(&:blank?)
-  end
-
-  def test_projects_by_role_for_user_with_no_role
-    user = User.generate!
-    assert_equal({}, user.projects_by_role)
-  end
-
-  def test_projects_by_role_for_anonymous
-    assert_equal({}, User.anonymous.projects_by_role)
-  end
-
-  def test_valid_notification_options
-    # without memberships
-    assert_equal 5, User.find(7).valid_notification_options.size
-    # with memberships
-    assert_equal 6, User.find(2).valid_notification_options.size
-  end
-
-  def test_valid_notification_options_class_method
-    assert_equal 5, User.valid_notification_options.size
-    assert_equal 5, User.valid_notification_options(User.find(7)).size
-    assert_equal 6, User.valid_notification_options(User.find(2)).size
-  end
-
-  def test_mail_notification_all
-    @jsmith.mail_notification = 'all'
-    @jsmith.notified_project_ids = []
-    @jsmith.save
-    @jsmith.reload
-    assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
-  end
-
-  def test_mail_notification_selected
-    @jsmith.mail_notification = 'selected'
-    @jsmith.notified_project_ids = [1]
-    @jsmith.save
-    @jsmith.reload
-    assert Project.find(1).recipients.include?(@jsmith.mail)
-  end
-
-  def test_mail_notification_only_my_events
-    @jsmith.mail_notification = 'only_my_events'
-    @jsmith.notified_project_ids = []
-    @jsmith.save
-    @jsmith.reload
-    assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
-  end
-
-  def test_comments_sorting_preference
-    assert !@jsmith.wants_comments_in_reverse_order?
-    @jsmith.pref.comments_sorting = 'asc'
-    assert !@jsmith.wants_comments_in_reverse_order?
-    @jsmith.pref.comments_sorting = 'desc'
-    assert @jsmith.wants_comments_in_reverse_order?
-  end
-
-  def test_find_by_mail_should_be_case_insensitive
-    u = User.find_by_mail('JSmith@somenet.foo')
-    assert_not_nil u
-    assert_equal 'jsmith@somenet.foo', u.mail
-  end
-
-  def test_random_password
-    u = User.new
-    u.random_password
-    assert !u.password.blank?
-    assert !u.password_confirmation.blank?
-  end
-
-  test "#change_password_allowed? should be allowed if no auth source is set" do
-    user = User.generate!
-    assert user.change_password_allowed?
-  end
-
-  test "#change_password_allowed? should delegate to the auth source" do
-    user = User.generate!
-
-    allowed_auth_source = AuthSource.generate!
-    def allowed_auth_source.allow_password_changes?; true; end
-
-    denied_auth_source = AuthSource.generate!
-    def denied_auth_source.allow_password_changes?; false; end
-
-    assert user.change_password_allowed?
-
-    user.auth_source = allowed_auth_source
-    assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
-
-    user.auth_source = denied_auth_source
-    assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
-  end
-
-  def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
-    with_settings :unsubscribe => '1' do
-      assert_equal true, User.find(2).own_account_deletable?
-    end
-  end
-
-  def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
-    with_settings :unsubscribe => '0' do
-      assert_equal false, User.find(2).own_account_deletable?
-    end
-  end
-
-  def test_own_account_deletable_should_be_false_for_a_single_admin
-    User.delete_all(["admin = ? AND id <> ?", true, 1])
-
-    with_settings :unsubscribe => '1' do
-      assert_equal false, User.find(1).own_account_deletable?
-    end
-  end
-
-  def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
-    User.generate! do |user|
-      user.admin = true
-    end
-
-    with_settings :unsubscribe => '1' do
-      assert_equal true, User.find(1).own_account_deletable?
-    end
-  end
-
-  context "#allowed_to?" do
-    context "with a unique project" do
-      should "return false if project is archived" do
-        project = Project.find(1)
-        Project.any_instance.stubs(:status).returns(Project::STATUS_ARCHIVED)
-        assert_equal false, @admin.allowed_to?(:view_issues, Project.find(1))
-      end
-
-      should "return false for write action if project is closed" do
-        project = Project.find(1)
-        Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
-        assert_equal false, @admin.allowed_to?(:edit_project, Project.find(1))
-      end
-
-      should "return true for read action if project is closed" do
-        project = Project.find(1)
-        Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
-        assert_equal true, @admin.allowed_to?(:view_project, Project.find(1))
-      end
-
-      should "return false if related module is disabled" do
-        project = Project.find(1)
-        project.enabled_module_names = ["issue_tracking"]
-        assert_equal true, @admin.allowed_to?(:add_issues, project)
-        assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
-      end
-
-      should "authorize nearly everything for admin users" do
-        project = Project.find(1)
-        assert ! @admin.member_of?(project)
-        %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
-          assert_equal true, @admin.allowed_to?(p.to_sym, project)
-        end
-      end
-
-      should "authorize normal users depending on their roles" do
-        project = Project.find(1)
-        assert_equal true, @jsmith.allowed_to?(:delete_messages, project)    #Manager
-        assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
-      end
-    end
-
-    context "with multiple projects" do
-      should "return false if array is empty" do
-        assert_equal false, @admin.allowed_to?(:view_project, [])
-      end
-
-      should "return true only if user has permission on all these projects" do
-        assert_equal true, @admin.allowed_to?(:view_project, Project.all)
-        assert_equal false, @dlopper.allowed_to?(:view_project, Project.all) #cannot see Project(2)
-        assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects) #Manager or Developer everywhere
-        assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects) #Dev cannot delete_issue_watchers
-      end
-
-      should "behave correctly with arrays of 1 project" do
-        assert_equal false, User.anonymous.allowed_to?(:delete_issues, [Project.first])
-      end
-    end
-
-    context "with options[:global]" do
-      should "authorize if user has at least one role that has this permission" do
-        @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
-        @anonymous = User.find(6)
-        assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
-        assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
-        assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
-        assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
-        assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
-      end
-    end
-  end
-
-  context "User#notify_about?" do
-    context "Issues" do
-      setup do
-        @project = Project.find(1)
-        @author = User.generate!
-        @assignee = User.generate!
-        @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
-      end
-
-      should "be true for a user with :all" do
-        @author.update_attribute(:mail_notification, 'all')
-        assert @author.notify_about?(@issue)
-      end
-
-      should "be false for a user with :none" do
-        @author.update_attribute(:mail_notification, 'none')
-        assert ! @author.notify_about?(@issue)
-      end
-
-      should "be false for a user with :only_my_events and isn't an author, creator, or assignee" do
-        @user = User.generate!(:mail_notification => 'only_my_events')
-        Member.create!(:user => @user, :project => @project, :role_ids => [1])
-        assert ! @user.notify_about?(@issue)
-      end
-
-      should "be true for a user with :only_my_events and is the author" do
-        @author.update_attribute(:mail_notification, 'only_my_events')
-        assert @author.notify_about?(@issue)
-      end
-
-      should "be true for a user with :only_my_events and is the assignee" do
-        @assignee.update_attribute(:mail_notification, 'only_my_events')
-        assert @assignee.notify_about?(@issue)
-      end
-
-      should "be true for a user with :only_assigned and is the assignee" do
-        @assignee.update_attribute(:mail_notification, 'only_assigned')
-        assert @assignee.notify_about?(@issue)
-      end
-
-      should "be false for a user with :only_assigned and is not the assignee" do
-        @author.update_attribute(:mail_notification, 'only_assigned')
-        assert ! @author.notify_about?(@issue)
-      end
-
-      should "be true for a user with :only_owner and is the author" do
-        @author.update_attribute(:mail_notification, 'only_owner')
-        assert @author.notify_about?(@issue)
-      end
-
-      should "be false for a user with :only_owner and is not the author" do
-        @assignee.update_attribute(:mail_notification, 'only_owner')
-        assert ! @assignee.notify_about?(@issue)
-      end
-
-      should "be true for a user with :selected and is the author" do
-        @author.update_attribute(:mail_notification, 'selected')
-        assert @author.notify_about?(@issue)
-      end
-
-      should "be true for a user with :selected and is the assignee" do
-        @assignee.update_attribute(:mail_notification, 'selected')
-        assert @assignee.notify_about?(@issue)
-      end
-
-      should "be false for a user with :selected and is not the author or assignee" do
-        @user = User.generate!(:mail_notification => 'selected')
-        Member.create!(:user => @user, :project => @project, :role_ids => [1])
-        assert ! @user.notify_about?(@issue)
-      end
-    end
-  end
-
-  def test_notify_about_news
-    user = User.generate!
-    news = News.new
-
-    User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
-      user.mail_notification = option
-      assert_equal (option != 'none'), user.notify_about?(news)
-    end
-  end
-
-  def test_salt_unsalted_passwords
-    # Restore a user with an unsalted password
-    user = User.find(1)
-    user.salt = nil
-    user.hashed_password = User.hash_password("unsalted")
-    user.save!
-
-    User.salt_unsalted_passwords!
-
-    user.reload
-    # Salt added
-    assert !user.salt.blank?
-    # Password still valid
-    assert user.check_password?("unsalted")
-    assert_equal user, User.try_to_login(user.login, "unsalted")
-  end
-
-  if Object.const_defined?(:OpenID)
-
-  def test_setting_identity_url
-    normalized_open_id_url = 'http://example.com/'
-    u = User.new( :identity_url => 'http://example.com/' )
-    assert_equal normalized_open_id_url, u.identity_url
-  end
-
-  def test_setting_identity_url_without_trailing_slash
-    normalized_open_id_url = 'http://example.com/'
-    u = User.new( :identity_url => 'http://example.com' )
-    assert_equal normalized_open_id_url, u.identity_url
-  end
-
-  def test_setting_identity_url_without_protocol
-    normalized_open_id_url = 'http://example.com/'
-    u = User.new( :identity_url => 'example.com' )
-    assert_equal normalized_open_id_url, u.identity_url
-  end
-
-  def test_setting_blank_identity_url
-    u = User.new( :identity_url => 'example.com' )
-    u.identity_url = ''
-    assert u.identity_url.blank?
-  end
-
-  def test_setting_invalid_identity_url
-    u = User.new( :identity_url => 'this is not an openid url' )
-    assert u.identity_url.blank?
-  end
-
-  else
-    puts "Skipping openid tests."
-  end
-
-end
--- a/.svn/pristine/ec/ecefbcb550b756f6256573a28f797d89d864d36f.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class ProjectCustomField < CustomField
-  def type_name
-    :label_project_plural
-  end
-end
--- a/.svn/pristine/ec/ecf9241c1e6ccd1ccee3ece4b5568fb173ad0940.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class IssuesHelperTest < ActionView::TestCase
-  include ApplicationHelper
-  include Redmine::I18n
-  include IssuesHelper
-  include CustomFieldsHelper
-  include ERB::Util
-
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :custom_fields,
-           :attachments,
-           :versions
-
-  def setup
-    super
-    set_language_if_valid('en')
-    User.current = nil
-  end
-
-  def test_issue_heading
-    assert_equal "Bug #1", issue_heading(Issue.find(1))
-  end
-
-  def test_issues_destroy_confirmation_message_with_one_root_issue
-    assert_equal l(:text_issues_destroy_confirmation),
-                 issues_destroy_confirmation_message(Issue.find(1))
-  end
-
-  def test_issues_destroy_confirmation_message_with_an_arrayt_of_root_issues
-    assert_equal l(:text_issues_destroy_confirmation),
-                 issues_destroy_confirmation_message(Issue.find([1, 2]))
-  end
-
-  def test_issues_destroy_confirmation_message_with_one_parent_issue
-    Issue.find(2).update_attribute :parent_issue_id, 1
-    assert_equal l(:text_issues_destroy_confirmation) + "\n" +
-                   l(:text_issues_destroy_descendants_confirmation, :count => 1),
-                 issues_destroy_confirmation_message(Issue.find(1))
-  end
-
-  def test_issues_destroy_confirmation_message_with_one_parent_issue_and_its_child
-    Issue.find(2).update_attribute :parent_issue_id, 1
-    assert_equal l(:text_issues_destroy_confirmation),
-                 issues_destroy_confirmation_message(Issue.find([1, 2]))
-  end
-
-  test 'show_detail with no_html should show a changing attribute' do
-    detail = JournalDetail.new(:property => 'attr', :old_value => '40',
-                               :value => '100', :prop_key => 'done_ratio')
-    assert_equal "% Done changed from 40 to 100", show_detail(detail, true)
-  end
-
-  test 'show_detail with no_html should show a new attribute' do
-    detail = JournalDetail.new(:property => 'attr', :old_value => nil,
-                               :value => '100', :prop_key => 'done_ratio')
-    assert_equal "% Done set to 100", show_detail(detail, true)
-  end
-
-  test 'show_detail with no_html should show a deleted attribute' do
-    detail = JournalDetail.new(:property => 'attr', :old_value => '50',
-                               :value => nil, :prop_key => 'done_ratio')
-    assert_equal "% Done deleted (50)", show_detail(detail, true)
-  end
-
-  test 'show_detail with html should show a changing attribute with HTML highlights' do
-    detail = JournalDetail.new(:property => 'attr', :old_value => '40',
-                               :value => '100', :prop_key => 'done_ratio')
-    html = show_detail(detail, false)
-    assert_include '<strong>% Done</strong>', html
-    assert_include '<i>40</i>', html
-    assert_include '<i>100</i>', html
-  end
-
-  test 'show_detail with html should show a new attribute with HTML highlights' do
-    detail = JournalDetail.new(:property => 'attr', :old_value => nil,
-                               :value => '100', :prop_key => 'done_ratio')
-    html = show_detail(detail, false)
-    assert_include '<strong>% Done</strong>', html
-    assert_include '<i>100</i>', html
-  end
-
-  test 'show_detail with html should show a deleted attribute with HTML highlights' do
-    detail = JournalDetail.new(:property => 'attr', :old_value => '50',
-                               :value => nil, :prop_key => 'done_ratio')
-    html = show_detail(detail, false)
-    assert_include '<strong>% Done</strong>', html
-    assert_include '<del><i>50</i></del>', html
-  end
-
-  test 'show_detail with a start_date attribute should format the dates' do
-    detail = JournalDetail.new(
-               :property  => 'attr',
-               :old_value => '2010-01-01',
-               :value     => '2010-01-31',
-               :prop_key  => 'start_date'
-            )
-    with_settings :date_format => '%m/%d/%Y' do
-      assert_match "01/31/2010", show_detail(detail, true)
-      assert_match "01/01/2010", show_detail(detail, true)
-    end
-  end
-
-  test 'show_detail with a due_date attribute should format the dates' do
-    detail = JournalDetail.new(
-              :property  => 'attr',
-              :old_value => '2010-01-01',
-              :value     => '2010-01-31',
-              :prop_key  => 'due_date'
-            )
-    with_settings :date_format => '%m/%d/%Y' do
-      assert_match "01/31/2010", show_detail(detail, true)
-      assert_match "01/01/2010", show_detail(detail, true)
-    end
-  end
-
-  test 'show_detail should show old and new values with a project attribute' do
-    detail = JournalDetail.new(:property => 'attr', :prop_key => 'project_id',
-                               :old_value => 1, :value => 2)
-    assert_match 'eCookbook', show_detail(detail, true)
-    assert_match 'OnlineStore', show_detail(detail, true)
-  end
-
-  test 'show_detail should show old and new values with a issue status attribute' do
-    detail = JournalDetail.new(:property => 'attr', :prop_key => 'status_id',
-                               :old_value => 1, :value => 2)
-    assert_match 'New', show_detail(detail, true)
-    assert_match 'Assigned', show_detail(detail, true)
-  end
-
-  test 'show_detail should show old and new values with a tracker attribute' do
-    detail = JournalDetail.new(:property => 'attr', :prop_key => 'tracker_id',
-                               :old_value => 1, :value => 2)
-    assert_match 'Bug', show_detail(detail, true)
-    assert_match 'Feature request', show_detail(detail, true)
-  end
-
-  test 'show_detail should show old and new values with a assigned to attribute' do
-    detail = JournalDetail.new(:property => 'attr', :prop_key => 'assigned_to_id',
-                               :old_value => 1, :value => 2)
-    assert_match 'Redmine Admin', show_detail(detail, true)
-    assert_match 'John Smith', show_detail(detail, true)
-  end
-
-  test 'show_detail should show old and new values with a priority attribute' do
-    detail = JournalDetail.new(:property => 'attr', :prop_key => 'priority_id',
-                               :old_value => 4, :value => 5)
-    assert_match 'Low', show_detail(detail, true)
-    assert_match 'Normal', show_detail(detail, true)
-  end
-
-  test 'show_detail should show old and new values with a category attribute' do
-    detail = JournalDetail.new(:property => 'attr', :prop_key => 'category_id',
-                               :old_value => 1, :value => 2)
-    assert_match 'Printing', show_detail(detail, true)
-    assert_match 'Recipes', show_detail(detail, true)
-  end
-
-  test 'show_detail should show old and new values with a fixed version attribute' do
-    detail = JournalDetail.new(:property => 'attr', :prop_key => 'fixed_version_id',
-                               :old_value => 1, :value => 2)
-    assert_match '0.1', show_detail(detail, true)
-    assert_match '1.0', show_detail(detail, true)
-  end
-
-  test 'show_detail should show old and new values with a estimated hours attribute' do
-    detail = JournalDetail.new(:property => 'attr', :prop_key => 'estimated_hours',
-                               :old_value => '5', :value => '6.3')
-    assert_match '5.00', show_detail(detail, true)
-    assert_match '6.30', show_detail(detail, true)
-  end
-
-  test 'show_detail should show old and new values with a custom field' do
-    detail = JournalDetail.new(:property => 'cf', :prop_key => '1',
-                               :old_value => 'MySQL', :value => 'PostgreSQL')
-    assert_equal 'Database changed from MySQL to PostgreSQL', show_detail(detail, true)
-  end
-
-  test 'show_detail should show added file' do
-    detail = JournalDetail.new(:property => 'attachment', :prop_key => '1',
-                               :old_value => nil, :value => 'error281.txt')
-    assert_match 'error281.txt', show_detail(detail, true)
-  end
-
-  test 'show_detail should show removed file' do
-    detail = JournalDetail.new(:property => 'attachment', :prop_key => '1',
-                               :old_value => 'error281.txt', :value => nil)
-    assert_match 'error281.txt', show_detail(detail, true)
-  end
-
-  def test_show_detail_relation_added
-    detail = JournalDetail.new(:property => 'relation',
-                               :prop_key => 'label_precedes',
-                               :value    => 1)
-    assert_equal "Precedes Bug #1: Can't print recipes added", show_detail(detail, true)
-    assert_match %r{<strong>Precedes</strong> <i><a href="/issues/1" class=".+">Bug #1</a>: Can&#x27;t print recipes</i> added},
-                 show_detail(detail, false)
-  end
-
-  def test_show_detail_relation_added_with_inexistant_issue
-    inexistant_issue_number = 9999
-    assert_nil  Issue.find_by_id(inexistant_issue_number)
-    detail = JournalDetail.new(:property => 'relation',
-                               :prop_key => 'label_precedes',
-                               :value    => inexistant_issue_number)
-    assert_equal "Precedes Issue ##{inexistant_issue_number} added", show_detail(detail, true)
-    assert_equal "<strong>Precedes</strong> <i>Issue ##{inexistant_issue_number}</i> added", show_detail(detail, false)
-  end
-
-  def test_show_detail_relation_added_should_not_disclose_issue_that_is_not_visible
-    issue = Issue.generate!(:is_private => true)
-    detail = JournalDetail.new(:property => 'relation',
-                               :prop_key => 'label_precedes',
-                               :value    => issue.id)
-
-    assert_equal "Precedes Issue ##{issue.id} added", show_detail(detail, true)
-    assert_equal "<strong>Precedes</strong> <i>Issue ##{issue.id}</i> added", show_detail(detail, false)
-  end
-
-  def test_show_detail_relation_deleted
-    detail = JournalDetail.new(:property  => 'relation',
-                               :prop_key  => 'label_precedes',
-                               :old_value => 1)
-    assert_equal "Precedes deleted (Bug #1: Can't print recipes)", show_detail(detail, true)
-    assert_match %r{<strong>Precedes</strong> deleted \(<i><a href="/issues/1" class=".+">Bug #1</a>: Can&#x27;t print recipes</i>\)},
-                 show_detail(detail, false)
-  end
-
-  def test_show_detail_relation_deleted_with_inexistant_issue
-    inexistant_issue_number = 9999
-    assert_nil  Issue.find_by_id(inexistant_issue_number)
-    detail = JournalDetail.new(:property  => 'relation',
-                               :prop_key  => 'label_precedes',
-                               :old_value => inexistant_issue_number)
-    assert_equal "Precedes deleted (Issue #9999)", show_detail(detail, true)
-    assert_equal "<strong>Precedes</strong> deleted (<i>Issue #9999</i>)", show_detail(detail, false)
-  end
-
-  def test_show_detail_relation_deleted_should_not_disclose_issue_that_is_not_visible
-    issue = Issue.generate!(:is_private => true)
-    detail = JournalDetail.new(:property => 'relation',
-                               :prop_key => 'label_precedes',
-                               :old_value    => issue.id)
-
-    assert_equal "Precedes deleted (Issue ##{issue.id})", show_detail(detail, true)
-    assert_equal "<strong>Precedes</strong> deleted (<i>Issue ##{issue.id}</i>)", show_detail(detail, false)
-  end
-end
--- a/.svn/pristine/ed/edfff204737c4c393e698de5497cb166b80631df.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,663 +0,0 @@
-# -*- coding: utf-8 -*-
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class TimelogControllerTest < ActionController::TestCase
-  fixtures :projects, :enabled_modules, :roles, :members,
-           :member_roles, :issues, :time_entries, :users,
-           :trackers, :enumerations, :issue_statuses,
-           :custom_fields, :custom_values,
-           :projects_trackers, :custom_fields_trackers,
-           :custom_fields_projects
-
-  include Redmine::I18n
-
-  def test_new_with_project_id
-    @request.session[:user_id] = 3
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-    assert_select 'select[name=?]', 'time_entry[project_id]', 0
-    assert_select 'input[name=?][value=1][type=hidden]', 'time_entry[project_id]'
-  end
-
-  def test_new_with_issue_id
-    @request.session[:user_id] = 3
-    get :new, :issue_id => 2
-    assert_response :success
-    assert_template 'new'
-    assert_select 'select[name=?]', 'time_entry[project_id]', 0
-    assert_select 'input[name=?][value=1][type=hidden]', 'time_entry[project_id]'
-  end
-
-  def test_new_without_project
-    @request.session[:user_id] = 3
-    get :new
-    assert_response :success
-    assert_template 'new'
-    assert_select 'select[name=?]', 'time_entry[project_id]'
-    assert_select 'input[name=?]', 'time_entry[project_id]', 0
-  end
-
-  def test_new_without_project_should_prefill_the_form
-    @request.session[:user_id] = 3
-    get :new, :time_entry => {:project_id => '1'}
-    assert_response :success
-    assert_template 'new'
-    assert_select 'select[name=?]', 'time_entry[project_id]' do
-      assert_select 'option[value=1][selected=selected]'
-    end
-    assert_select 'input[name=?]', 'time_entry[project_id]', 0
-  end
-
-  def test_new_without_project_should_deny_without_permission
-    Role.all.each {|role| role.remove_permission! :log_time}
-    @request.session[:user_id] = 3
-
-    get :new
-    assert_response 403
-  end
-
-  def test_new_should_select_default_activity
-    @request.session[:user_id] = 3
-    get :new, :project_id => 1
-    assert_response :success
-    assert_select 'select[name=?]', 'time_entry[activity_id]' do
-      assert_select 'option[selected=selected]', :text => 'Development'
-    end
-  end
-
-  def test_new_should_only_show_active_time_entry_activities
-    @request.session[:user_id] = 3
-    get :new, :project_id => 1
-    assert_response :success
-    assert_no_tag 'option', :content => 'Inactive Activity'
-  end
-
-  def test_get_edit_existing_time
-    @request.session[:user_id] = 2
-    get :edit, :id => 2, :project_id => nil
-    assert_response :success
-    assert_template 'edit'
-    # Default activity selected
-    assert_tag :tag => 'form', :attributes => { :action => '/projects/ecookbook/time_entries/2' }
-  end
-
-  def test_get_edit_with_an_existing_time_entry_with_inactive_activity
-    te = TimeEntry.find(1)
-    te.activity = TimeEntryActivity.find_by_name("Inactive Activity")
-    te.save!
-
-    @request.session[:user_id] = 1
-    get :edit, :project_id => 1, :id => 1
-    assert_response :success
-    assert_template 'edit'
-    # Blank option since nothing is pre-selected
-    assert_tag :tag => 'option', :content => '--- Please select ---'
-  end
-
-  def test_post_create
-    # TODO: should POST to issues’ time log instead of project. change form
-    # and routing
-    @request.session[:user_id] = 3
-    post :create, :project_id => 1,
-                :time_entry => {:comments => 'Some work on TimelogControllerTest',
-                                # Not the default activity
-                                :activity_id => '11',
-                                :spent_on => '2008-03-14',
-                                :issue_id => '1',
-                                :hours => '7.3'}
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-
-    i = Issue.find(1)
-    t = TimeEntry.find_by_comments('Some work on TimelogControllerTest')
-    assert_not_nil t
-    assert_equal 11, t.activity_id
-    assert_equal 7.3, t.hours
-    assert_equal 3, t.user_id
-    assert_equal i, t.issue
-    assert_equal i.project, t.project
-  end
-
-  def test_post_create_with_blank_issue
-    # TODO: should POST to issues’ time log instead of project. change form
-    # and routing
-    @request.session[:user_id] = 3
-    post :create, :project_id => 1,
-                :time_entry => {:comments => 'Some work on TimelogControllerTest',
-                                # Not the default activity
-                                :activity_id => '11',
-                                :issue_id => '',
-                                :spent_on => '2008-03-14',
-                                :hours => '7.3'}
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-
-    t = TimeEntry.find_by_comments('Some work on TimelogControllerTest')
-    assert_not_nil t
-    assert_equal 11, t.activity_id
-    assert_equal 7.3, t.hours
-    assert_equal 3, t.user_id
-  end
-
-  def test_create_and_continue
-    @request.session[:user_id] = 2
-    post :create, :project_id => 1,
-                :time_entry => {:activity_id => '11',
-                                :issue_id => '',
-                                :spent_on => '2008-03-14',
-                                :hours => '7.3'},
-                :continue => '1'
-    assert_redirected_to '/projects/ecookbook/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D='
-  end
-
-  def test_create_and_continue_with_issue_id
-    @request.session[:user_id] = 2
-    post :create, :project_id => 1,
-                :time_entry => {:activity_id => '11',
-                                :issue_id => '1',
-                                :spent_on => '2008-03-14',
-                                :hours => '7.3'},
-                :continue => '1'
-    assert_redirected_to '/projects/ecookbook/issues/1/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=1'
-  end
-
-  def test_create_and_continue_without_project
-    @request.session[:user_id] = 2
-    post :create, :time_entry => {:project_id => '1',
-                                :activity_id => '11',
-                                :issue_id => '',
-                                :spent_on => '2008-03-14',
-                                :hours => '7.3'},
-                  :continue => '1'
-
-    assert_redirected_to '/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=&time_entry%5Bproject_id%5D=1'
-  end
-
-  def test_create_without_log_time_permission_should_be_denied
-    @request.session[:user_id] = 2
-    Role.find_by_name('Manager').remove_permission! :log_time
-    post :create, :project_id => 1,
-                :time_entry => {:activity_id => '11',
-                                :issue_id => '',
-                                :spent_on => '2008-03-14',
-                                :hours => '7.3'}
-
-    assert_response 403
-  end
-
-  def test_create_with_failure
-    @request.session[:user_id] = 2
-    post :create, :project_id => 1,
-                :time_entry => {:activity_id => '',
-                                :issue_id => '',
-                                :spent_on => '2008-03-14',
-                                :hours => '7.3'}
-
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_create_without_project
-    @request.session[:user_id] = 2
-    assert_difference 'TimeEntry.count' do
-      post :create, :time_entry => {:project_id => '1',
-                                  :activity_id => '11',
-                                  :issue_id => '',
-                                  :spent_on => '2008-03-14',
-                                  :hours => '7.3'}
-    end
-
-    assert_redirected_to '/projects/ecookbook/time_entries'
-    time_entry = TimeEntry.first(:order => 'id DESC')
-    assert_equal 1, time_entry.project_id
-  end
-
-  def test_create_without_project_should_fail_with_issue_not_inside_project
-    @request.session[:user_id] = 2
-    assert_no_difference 'TimeEntry.count' do
-      post :create, :time_entry => {:project_id => '1',
-                                  :activity_id => '11',
-                                  :issue_id => '5',
-                                  :spent_on => '2008-03-14',
-                                  :hours => '7.3'}
-    end
-
-    assert_response :success
-    assert assigns(:time_entry).errors[:issue_id].present?
-  end
-
-  def test_create_without_project_should_deny_without_permission
-    @request.session[:user_id] = 2
-    Project.find(3).disable_module!(:time_tracking)
-
-    assert_no_difference 'TimeEntry.count' do
-      post :create, :time_entry => {:project_id => '3',
-                                  :activity_id => '11',
-                                  :issue_id => '',
-                                  :spent_on => '2008-03-14',
-                                  :hours => '7.3'}
-    end
-
-    assert_response 403
-  end
-
-  def test_create_without_project_with_failure
-    @request.session[:user_id] = 2
-    assert_no_difference 'TimeEntry.count' do
-      post :create, :time_entry => {:project_id => '1',
-                                  :activity_id => '11',
-                                  :issue_id => '',
-                                  :spent_on => '2008-03-14',
-                                  :hours => ''}
-    end
-
-    assert_response :success
-    assert_tag 'select', :attributes => {:name => 'time_entry[project_id]'},
-      :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
-  end
-
-  def test_update
-    entry = TimeEntry.find(1)
-    assert_equal 1, entry.issue_id
-    assert_equal 2, entry.user_id
-
-    @request.session[:user_id] = 1
-    put :update, :id => 1,
-                :time_entry => {:issue_id => '2',
-                                :hours => '8'}
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    entry.reload
-
-    assert_equal 8, entry.hours
-    assert_equal 2, entry.issue_id
-    assert_equal 2, entry.user_id
-  end
-
-  def test_get_bulk_edit
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 2]
-    assert_response :success
-    assert_template 'bulk_edit'
-
-    assert_select 'ul#bulk-selection' do
-      assert_select 'li', 2
-      assert_select 'li a', :text => '03/23/2007 - eCookbook: 4.25 hours'
-    end
-
-    assert_select 'form#bulk_edit_form[action=?]', '/time_entries/bulk_update' do
-      # System wide custom field
-      assert_select 'select[name=?]', 'time_entry[custom_field_values][10]'
-  
-      # Activities
-      assert_select 'select[name=?]', 'time_entry[activity_id]' do
-        assert_select 'option[value=]', :text => '(No change)'
-        assert_select 'option[value=9]', :text => 'Design'
-      end
-    end
-  end
-
-  def test_get_bulk_edit_on_different_projects
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 2, 6]
-    assert_response :success
-    assert_template 'bulk_edit'
-  end
-
-  def test_bulk_update
-    @request.session[:user_id] = 2
-    # update time entry activity
-    post :bulk_update, :ids => [1, 2], :time_entry => { :activity_id => 9}
-
-    assert_response 302
-    # check that the issues were updated
-    assert_equal [9, 9], TimeEntry.find_all_by_id([1, 2]).collect {|i| i.activity_id}
-  end
-
-  def test_bulk_update_with_failure
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2], :time_entry => { :hours => 'A'}
-
-    assert_response 302
-    assert_match /Failed to save 2 time entrie/, flash[:error]
-  end
-
-  def test_bulk_update_on_different_projects
-    @request.session[:user_id] = 2
-    # makes user a manager on the other project
-    Member.create!(:user_id => 2, :project_id => 3, :role_ids => [1])
-    
-    # update time entry activity
-    post :bulk_update, :ids => [1, 2, 4], :time_entry => { :activity_id => 9 }
-
-    assert_response 302
-    # check that the issues were updated
-    assert_equal [9, 9, 9], TimeEntry.find_all_by_id([1, 2, 4]).collect {|i| i.activity_id}
-  end
-
-  def test_bulk_update_on_different_projects_without_rights
-    @request.session[:user_id] = 3
-    user = User.find(3)
-    action = { :controller => "timelog", :action => "bulk_update" }
-    assert user.allowed_to?(action, TimeEntry.find(1).project)
-    assert ! user.allowed_to?(action, TimeEntry.find(5).project)
-    post :bulk_update, :ids => [1, 5], :time_entry => { :activity_id => 9 }
-    assert_response 403
-  end
-
-  def test_bulk_update_custom_field
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2], :time_entry => { :custom_field_values => {'10' => '0'} }
-
-    assert_response 302
-    assert_equal ["0", "0"], TimeEntry.find_all_by_id([1, 2]).collect {|i| i.custom_value_for(10).value}
-  end
-
-  def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1,2], :back_url => '/time_entries'
-
-    assert_response :redirect
-    assert_redirected_to '/time_entries'
-  end
-
-  def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
-
-    assert_response :redirect
-    assert_redirected_to :controller => 'timelog', :action => 'index', :project_id => Project.find(1).identifier
-  end
-
-  def test_post_bulk_update_without_edit_permission_should_be_denied
-    @request.session[:user_id] = 2
-    Role.find_by_name('Manager').remove_permission! :edit_time_entries
-    post :bulk_update, :ids => [1,2]
-
-    assert_response 403
-  end
-
-  def test_destroy
-    @request.session[:user_id] = 2
-    delete :destroy, :id => 1
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    assert_equal I18n.t(:notice_successful_delete), flash[:notice]
-    assert_nil TimeEntry.find_by_id(1)
-  end
-
-  def test_destroy_should_fail
-    # simulate that this fails (e.g. due to a plugin), see #5700
-    TimeEntry.any_instance.expects(:destroy).returns(false)
-
-    @request.session[:user_id] = 2
-    delete :destroy, :id => 1
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    assert_equal I18n.t(:notice_unable_delete_time_entry), flash[:error]
-    assert_not_nil TimeEntry.find_by_id(1)
-  end
-
-  def test_index_all_projects
-    get :index
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:total_hours)
-    assert_equal "162.90", "%.2f" % assigns(:total_hours)
-    assert_tag :form,
-      :attributes => {:action => "/time_entries", :id => 'query_form'}
-  end
-
-  def test_index_all_projects_should_show_log_time_link
-    @request.session[:user_id] = 2
-    get :index
-    assert_response :success
-    assert_template 'index'
-    assert_tag 'a', :attributes => {:href => '/time_entries/new'}, :content => /Log time/
-  end
-
-  def test_index_my_spent_time
-    @request.session[:user_id] = 2
-    get :index, :user_id => 'me'
-    assert_response :success
-    assert_template 'index'
-    assert assigns(:entries).all? {|entry| entry.user_id == 2}
-  end
-
-  def test_index_at_project_level
-    get :index, :project_id => 'ecookbook'
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:entries)
-    assert_equal 4, assigns(:entries).size
-    # project and subproject
-    assert_equal [1, 3], assigns(:entries).collect(&:project_id).uniq.sort
-    assert_not_nil assigns(:total_hours)
-    assert_equal "162.90", "%.2f" % assigns(:total_hours)
-    assert_tag :form,
-      :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
-  end
-
-  def test_index_with_display_subprojects_issues_to_false_should_not_include_subproject_entries
-    entry = TimeEntry.generate!(:project => Project.find(3))
-
-    with_settings :display_subprojects_issues => '0' do
-      get :index, :project_id => 'ecookbook'
-      assert_response :success
-      assert_template 'index'
-      assert_not_include entry, assigns(:entries)
-    end
-  end
-
-  def test_index_with_display_subprojects_issues_to_false_and_subproject_filter_should_include_subproject_entries
-    entry = TimeEntry.generate!(:project => Project.find(3))
-
-    with_settings :display_subprojects_issues => '0' do
-      get :index, :project_id => 'ecookbook', :subproject_id => 3
-      assert_response :success
-      assert_template 'index'
-      assert_include entry, assigns(:entries)
-    end
-  end
-
-  def test_index_at_project_level_with_date_range
-    get :index, :project_id => 'ecookbook',
-      :f => ['spent_on'],
-      :op => {'spent_on' => '><'},
-      :v => {'spent_on' => ['2007-03-20', '2007-04-30']}
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:entries)
-    assert_equal 3, assigns(:entries).size
-    assert_not_nil assigns(:total_hours)
-    assert_equal "12.90", "%.2f" % assigns(:total_hours)
-    assert_tag :form,
-      :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
-  end
-
-  def test_index_at_project_level_with_date_range_using_from_and_to_params
-    get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30'
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:entries)
-    assert_equal 3, assigns(:entries).size
-    assert_not_nil assigns(:total_hours)
-    assert_equal "12.90", "%.2f" % assigns(:total_hours)
-    assert_tag :form,
-      :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
-  end
-
-  def test_index_at_project_level_with_period
-    get :index, :project_id => 'ecookbook',
-      :f => ['spent_on'],
-      :op => {'spent_on' => '>t-'},
-      :v => {'spent_on' => ['7']}
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:entries)
-    assert_not_nil assigns(:total_hours)
-    assert_tag :form,
-      :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
-  end
-
-  def test_index_at_issue_level
-    get :index, :issue_id => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:entries)
-    assert_equal 2, assigns(:entries).size
-    assert_not_nil assigns(:total_hours)
-    assert_equal 154.25, assigns(:total_hours)
-    # display all time
-    assert_nil assigns(:from)
-    assert_nil assigns(:to)
-    # TODO: remove /projects/:project_id/issues/:issue_id/time_entries routes
-    # to use /issues/:issue_id/time_entries
-    assert_tag :form,
-      :attributes => {:action => "/projects/ecookbook/issues/1/time_entries", :id => 'query_form'}
-  end
-
-  def test_index_should_sort_by_spent_on_and_created_on
-    t1 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-16', :created_on => '2012-06-16 20:00:00', :activity_id => 10)
-    t2 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-16', :created_on => '2012-06-16 20:05:00', :activity_id => 10)
-    t3 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-15', :created_on => '2012-06-16 20:10:00', :activity_id => 10)
-
-    get :index, :project_id => 1,
-      :f => ['spent_on'],
-      :op => {'spent_on' => '><'},
-      :v => {'spent_on' => ['2012-06-15', '2012-06-16']}
-    assert_response :success
-    assert_equal [t2, t1, t3], assigns(:entries)
-
-    get :index, :project_id => 1,
-      :f => ['spent_on'],
-      :op => {'spent_on' => '><'},
-      :v => {'spent_on' => ['2012-06-15', '2012-06-16']},
-      :sort => 'spent_on'
-    assert_response :success
-    assert_equal [t3, t1, t2], assigns(:entries)
-  end
-
-  def test_index_with_filter_on_issue_custom_field
-    issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
-    entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
-
-    get :index, :f => ['issue.cf_2'], :op => {'issue.cf_2' => '='}, :v => {'issue.cf_2' => ['filter_on_issue_custom_field']}
-    assert_response :success
-    assert_equal [entry], assigns(:entries)
-  end
-
-  def test_index_with_issue_custom_field_column
-    issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
-    entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
-
-    get :index, :c => %w(project spent_on issue comments hours issue.cf_2)
-    assert_response :success
-    assert_include :'issue.cf_2', assigns(:query).column_names
-    assert_select 'td.issue_cf_2', :text => 'filter_on_issue_custom_field'
-  end
-
-  def test_index_with_time_entry_custom_field_column
-    field = TimeEntryCustomField.generate!(:field_format => 'string')
-    entry = TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value'})
-    field_name = "cf_#{field.id}"
-
-    get :index, :c => ["hours", field_name]
-    assert_response :success
-    assert_include field_name.to_sym, assigns(:query).column_names
-    assert_select "td.#{field_name}", :text => 'CF Value'
-  end
-
-  def test_index_with_time_entry_custom_field_sorting
-    field = TimeEntryCustomField.generate!(:field_format => 'string', :name => 'String Field')
-    TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 1'})
-    TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 3'})
-    TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 2'})
-    field_name = "cf_#{field.id}"
-
-    get :index, :c => ["hours", field_name], :sort => field_name
-    assert_response :success
-    assert_include field_name.to_sym, assigns(:query).column_names
-    assert_select "th a.sort", :text => 'String Field'
-
-    # Make sure that values are properly sorted
-    values = assigns(:entries).map {|e| e.custom_field_value(field)}.compact
-    assert_equal 3, values.size
-    assert_equal values.sort, values
-  end
-
-  def test_index_atom_feed
-    get :index, :project_id => 1, :format => 'atom'
-    assert_response :success
-    assert_equal 'application/atom+xml', @response.content_type
-    assert_not_nil assigns(:items)
-    assert assigns(:items).first.is_a?(TimeEntry)
-  end
-
-  def test_index_at_project_level_should_include_csv_export_dialog
-    get :index, :project_id => 'ecookbook', 
-      :f => ['spent_on'],
-      :op => {'spent_on' => '>='},
-      :v => {'spent_on' => ['2007-04-01']},
-      :c => ['spent_on', 'user']
-    assert_response :success
-
-    assert_select '#csv-export-options' do
-      assert_select 'form[action=?][method=get]', '/projects/ecookbook/time_entries.csv' do
-        # filter
-        assert_select 'input[name=?][value=?]', 'f[]', 'spent_on'
-        assert_select 'input[name=?][value=?]', 'op[spent_on]', '&gt;='
-        assert_select 'input[name=?][value=?]', 'v[spent_on][]', '2007-04-01'
-        # columns
-        assert_select 'input[name=?][value=?]', 'c[]', 'spent_on'
-        assert_select 'input[name=?][value=?]', 'c[]', 'user'
-        assert_select 'input[name=?]', 'c[]', 2
-      end
-    end
-  end
-
-  def test_index_cross_project_should_include_csv_export_dialog
-    get :index
-    assert_response :success
-
-    assert_select '#csv-export-options' do
-      assert_select 'form[action=?][method=get]', '/time_entries.csv'
-    end
-  end
-
-  def test_index_at_issue_level_should_include_csv_export_dialog
-    get :index, :project_id => 'ecookbook', :issue_id => 3
-    assert_response :success
-
-    assert_select '#csv-export-options' do
-      assert_select 'form[action=?][method=get]', '/projects/ecookbook/issues/3/time_entries.csv'
-    end
-  end
-
-  def test_index_csv_all_projects
-    Setting.date_format = '%m/%d/%Y'
-    get :index, :format => 'csv'
-    assert_response :success
-    assert_equal 'text/csv; header=present', response.content_type
-  end
-
-  def test_index_csv
-    Setting.date_format = '%m/%d/%Y'
-    get :index, :project_id => 1, :format => 'csv'
-    assert_response :success
-    assert_equal 'text/csv; header=present', response.content_type
-  end
-end
--- a/.svn/pristine/ef/ef01ace269b8f950664d9b52e99400c8a56e9cdf.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class FilesControllerTest < ActionController::TestCase
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :journals, :journal_details,
-           :attachments,
-           :versions
-
-  def setup
-    @request.session[:user_id] = nil
-    Setting.default_language = 'en'
-  end
-
-  def test_index
-    get :index, :project_id => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:containers)
-
-    # file attached to the project
-    assert_tag :a, :content => 'project_file.zip',
-                   :attributes => { :href => '/attachments/download/8/project_file.zip' }
-
-    # file attached to a project's version
-    assert_tag :a, :content => 'version_file.zip',
-                   :attributes => { :href => '/attachments/download/9/version_file.zip' }
-  end
-
-  def test_new
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_tag 'select', :attributes => {:name => 'version_id'}
-  end
-
-  def test_new_without_versions
-    Version.delete_all
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_no_tag 'select', :attributes => {:name => 'version_id'}
-  end
-
-  def test_create_file
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-    ActionMailer::Base.deliveries.clear
-
-    with_settings :notified_events => %w(file_added) do
-      assert_difference 'Attachment.count' do
-        post :create, :project_id => 1, :version_id => '',
-             :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
-        assert_response :redirect
-      end
-    end
-    assert_redirected_to '/projects/ecookbook/files'
-    a = Attachment.order('created_on DESC').first
-    assert_equal 'testfile.txt', a.filename
-    assert_equal Project.find(1), a.container
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert_equal "[eCookbook] New file", mail.subject
-    assert_mail_body_match 'testfile.txt', mail
-  end
-
-  def test_create_version_file
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-
-    assert_difference 'Attachment.count' do
-      post :create, :project_id => 1, :version_id => '2',
-           :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
-      assert_response :redirect
-    end
-    assert_redirected_to '/projects/ecookbook/files'
-    a = Attachment.order('created_on DESC').first
-    assert_equal 'testfile.txt', a.filename
-    assert_equal Version.find(2), a.container
-  end
-
-end
--- a/.svn/pristine/f0/f0263c221f5ea74d2c30c55c3240a08d7cddc2f4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class TimeEntryActivityTest < ActiveSupport::TestCase
-  fixtures :enumerations, :time_entries, :custom_fields
-
-  include Redmine::I18n
-
-  def test_should_be_an_enumeration
-    assert TimeEntryActivity.ancestors.include?(Enumeration)
-  end
-
-  def test_objects_count
-    assert_equal 3, TimeEntryActivity.find_by_name("Design").objects_count
-    assert_equal 2, TimeEntryActivity.find_by_name("Development").objects_count
-  end
-
-  def test_option_name
-    assert_equal :enumeration_activities, TimeEntryActivity.new.option_name
-  end
-
-  def test_create_with_custom_field
-    field = TimeEntryActivityCustomField.find_by_name('Billable')
-    e = TimeEntryActivity.new(:name => 'Custom Data')
-    e.custom_field_values = {field.id => "1"}
-    assert e.save
-
-    e.reload
-    assert_equal "1", e.custom_value_for(field).value
-  end
-
-  def test_create_without_required_custom_field_should_fail
-    set_language_if_valid 'en'
-    field = TimeEntryActivityCustomField.find_by_name('Billable')
-    field.update_attribute(:is_required, true)
-
-    e = TimeEntryActivity.new(:name => 'Custom Data')
-    assert !e.save
-    assert_equal ["Billable can't be blank"], e.errors.full_messages
-  end
-
-  def test_create_with_required_custom_field_should_succeed
-    field = TimeEntryActivityCustomField.find_by_name('Billable')
-    field.update_attribute(:is_required, true)
-
-    e = TimeEntryActivity.new(:name => 'Custom Data')
-    e.custom_field_values = {field.id => "1"}
-    assert e.save
-  end
-
-  def test_update_with_required_custom_field_change
-    set_language_if_valid 'en'
-    field = TimeEntryActivityCustomField.find_by_name('Billable')
-    field.update_attribute(:is_required, true)
-
-    e = TimeEntryActivity.find(10)
-    assert e.available_custom_fields.include?(field)
-    # No change to custom field, record can be saved
-    assert e.save
-    # Blanking custom field, save should fail
-    e.custom_field_values = {field.id => ""}
-    assert !e.save
-    assert_equal ["Billable can't be blank"], e.errors.full_messages
-
-    # Update custom field to valid value, save should succeed
-    e.custom_field_values = {field.id => "0"}
-    assert e.save
-    e.reload
-    assert_equal "0", e.custom_value_for(field).value
-  end
-
-  def test_system_activity_with_child_in_use_should_be_in_use
-    project = Project.generate!
-    system_activity = TimeEntryActivity.create!(:name => 'Activity')
-    project_activity = TimeEntryActivity.create!(:name => 'Activity', :project => project, :parent_id => system_activity.id)
-
-    TimeEntry.generate!(:project => project, :activity => project_activity)
-
-    assert project_activity.in_use?
-    assert system_activity.in_use?
-  end
-
-  def test_destroying_a_system_activity_should_reassign_children_activities
-    project = Project.generate!
-    system_activity = TimeEntryActivity.create!(:name => 'Activity')
-    project_activity = TimeEntryActivity.create!(:name => 'Activity', :project => project, :parent_id => system_activity.id)
-
-    entries = [
-      TimeEntry.generate!(:project => project, :activity => system_activity),
-      TimeEntry.generate!(:project => project, :activity => project_activity)
-    ]
-
-    assert_difference 'TimeEntryActivity.count', -2 do
-      assert_nothing_raised do
-        assert system_activity.destroy(TimeEntryActivity.find_by_name('Development'))
-      end
-    end
-    assert entries.all? {|entry| entry.reload.activity.name == 'Development'}
-  end
-end
--- a/.svn/pristine/f0/f0fa25d2662f25ee7e3a4a54f9fb5b50422d6b41.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,282 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class Changeset < ActiveRecord::Base
-  belongs_to :repository
-  belongs_to :user
-  has_many :filechanges, :class_name => 'Change', :dependent => :delete_all
-  has_and_belongs_to_many :issues
-  has_and_belongs_to_many :parents,
-                          :class_name => "Changeset",
-                          :join_table => "#{table_name_prefix}changeset_parents#{table_name_suffix}",
-                          :association_foreign_key => 'parent_id', :foreign_key => 'changeset_id'
-  has_and_belongs_to_many :children,
-                          :class_name => "Changeset",
-                          :join_table => "#{table_name_prefix}changeset_parents#{table_name_suffix}",
-                          :association_foreign_key => 'changeset_id', :foreign_key => 'parent_id'
-
-  acts_as_event :title => Proc.new {|o| o.title},
-                :description => :long_comments,
-                :datetime => :committed_on,
-                :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :repository_id => o.repository.identifier_param, :rev => o.identifier}}
-
-  acts_as_searchable :columns => 'comments',
-                     :include => {:repository => :project},
-                     :project_key => "#{Repository.table_name}.project_id",
-                     :date_column => 'committed_on'
-
-  acts_as_activity_provider :timestamp => "#{table_name}.committed_on",
-                            :author_key => :user_id,
-                            :find_options => {:include => [:user, {:repository => :project}]}
-
-  validates_presence_of :repository_id, :revision, :committed_on, :commit_date
-  validates_uniqueness_of :revision, :scope => :repository_id
-  validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
-
-  scope :visible, lambda {|*args|
-    includes(:repository => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args))
-  }
-
-  after_create :scan_for_issues
-  before_create :before_create_cs
-
-  def revision=(r)
-    write_attribute :revision, (r.nil? ? nil : r.to_s)
-  end
-
-  # Returns the identifier of this changeset; depending on repository backends
-  def identifier
-    if repository.class.respond_to? :changeset_identifier
-      repository.class.changeset_identifier self
-    else
-      revision.to_s
-    end
-  end
-
-  def committed_on=(date)
-    self.commit_date = date
-    super
-  end
-
-  # Returns the readable identifier
-  def format_identifier
-    if repository.class.respond_to? :format_changeset_identifier
-      repository.class.format_changeset_identifier self
-    else
-      identifier
-    end
-  end
-
-  def project
-    repository.project
-  end
-
-  def author
-    user || committer.to_s.split('<').first
-  end
-
-  def before_create_cs
-    self.committer = self.class.to_utf8(self.committer, repository.repo_log_encoding)
-    self.comments  = self.class.normalize_comments(
-                       self.comments, repository.repo_log_encoding)
-    self.user = repository.find_committer_user(self.committer)
-  end
-
-  def scan_for_issues
-    scan_comment_for_issue_ids
-  end
-
-  TIMELOG_RE = /
-    (
-    ((\d+)(h|hours?))((\d+)(m|min)?)?
-    |
-    ((\d+)(h|hours?|m|min))
-    |
-    (\d+):(\d+)
-    |
-    (\d+([\.,]\d+)?)h?
-    )
-    /x
-
-  def scan_comment_for_issue_ids
-    return if comments.blank?
-    # keywords used to reference issues
-    ref_keywords = Setting.commit_ref_keywords.downcase.split(",").collect(&:strip)
-    ref_keywords_any = ref_keywords.delete('*')
-    # keywords used to fix issues
-    fix_keywords = Setting.commit_update_keywords_array.map {|r| r['keywords']}.flatten.compact
-
-    kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|")
-
-    referenced_issues = []
-
-    comments.scan(/([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)/i) do |match|
-      action, refs = match[2].to_s.downcase, match[3]
-      next unless action.present? || ref_keywords_any
-
-      refs.scan(/#(\d+)(\s+@#{TIMELOG_RE})?/).each do |m|
-        issue, hours = find_referenced_issue_by_id(m[0].to_i), m[2]
-        if issue
-          referenced_issues << issue
-          # Don't update issues or log time when importing old commits
-          unless repository.created_on && committed_on && committed_on < repository.created_on
-            fix_issue(issue, action) if fix_keywords.include?(action)
-            log_time(issue, hours) if hours && Setting.commit_logtime_enabled?
-          end
-        end
-      end
-    end
-
-    referenced_issues.uniq!
-    self.issues = referenced_issues unless referenced_issues.empty?
-  end
-
-  def short_comments
-    @short_comments || split_comments.first
-  end
-
-  def long_comments
-    @long_comments || split_comments.last
-  end
-
-  def text_tag(ref_project=nil)
-    tag = if scmid?
-      "commit:#{scmid}"
-    else
-      "r#{revision}"
-    end
-    if repository && repository.identifier.present?
-      tag = "#{repository.identifier}|#{tag}"
-    end
-    if ref_project && project && ref_project != project
-      tag = "#{project.identifier}:#{tag}"
-    end
-    tag
-  end
-
-  # Returns the title used for the changeset in the activity/search results
-  def title
-    repo = (repository && repository.identifier.present?) ? " (#{repository.identifier})" : ''
-    comm = short_comments.blank? ? '' : (': ' + short_comments)
-    "#{l(:label_revision)} #{format_identifier}#{repo}#{comm}"
-  end
-
-  # Returns the previous changeset
-  def previous
-    @previous ||= Changeset.where(["id < ? AND repository_id = ?", id, repository_id]).order('id DESC').first
-  end
-
-  # Returns the next changeset
-  def next
-    @next ||= Changeset.where(["id > ? AND repository_id = ?", id, repository_id]).order('id ASC').first
-  end
-
-  # Creates a new Change from it's common parameters
-  def create_change(change)
-    Change.create(:changeset     => self,
-                  :action        => change[:action],
-                  :path          => change[:path],
-                  :from_path     => change[:from_path],
-                  :from_revision => change[:from_revision])
-  end
-
-  # Finds an issue that can be referenced by the commit message
-  def find_referenced_issue_by_id(id)
-    return nil if id.blank?
-    issue = Issue.find_by_id(id.to_i, :include => :project)
-    if Setting.commit_cross_project_ref?
-      # all issues can be referenced/fixed
-    elsif issue
-      # issue that belong to the repository project, a subproject or a parent project only
-      unless issue.project &&
-                (project == issue.project || project.is_ancestor_of?(issue.project) ||
-                 project.is_descendant_of?(issue.project))
-        issue = nil
-      end
-    end
-    issue
-  end
-
-  private
-
-  # Updates the +issue+ according to +action+
-  def fix_issue(issue, action)
-    # the issue may have been updated by the closure of another one (eg. duplicate)
-    issue.reload
-    # don't change the status is the issue is closed
-    return if issue.status && issue.status.is_closed?
-
-    journal = issue.init_journal(user || User.anonymous,
-                                 ll(Setting.default_language,
-                                    :text_status_changed_by_changeset,
-                                    text_tag(issue.project)))
-    rule = Setting.commit_update_keywords_array.detect do |rule|
-      rule['keywords'].include?(action) &&
-        (rule['if_tracker_id'].blank? || rule['if_tracker_id'] == issue.tracker_id.to_s)
-    end
-    if rule
-      issue.assign_attributes rule.slice(*Issue.attribute_names)
-    end
-    Redmine::Hook.call_hook(:model_changeset_scan_commit_for_issue_ids_pre_issue_update,
-                            { :changeset => self, :issue => issue, :action => action })
-    unless issue.save
-      logger.warn("Issue ##{issue.id} could not be saved by changeset #{id}: #{issue.errors.full_messages}") if logger
-    end
-    issue
-  end
-
-  def log_time(issue, hours)
-    time_entry = TimeEntry.new(
-      :user => user,
-      :hours => hours,
-      :issue => issue,
-      :spent_on => commit_date,
-      :comments => l(:text_time_logged_by_changeset, :value => text_tag(issue.project),
-                     :locale => Setting.default_language)
-      )
-    time_entry.activity = log_time_activity unless log_time_activity.nil?
-
-    unless time_entry.save
-      logger.warn("TimeEntry could not be created by changeset #{id}: #{time_entry.errors.full_messages}") if logger
-    end
-    time_entry
-  end
-
-  def log_time_activity
-    if Setting.commit_logtime_activity_id.to_i > 0
-      TimeEntryActivity.find_by_id(Setting.commit_logtime_activity_id.to_i)
-    end
-  end
-
-  def split_comments
-    comments =~ /\A(.+?)\r?\n(.*)$/m
-    @short_comments = $1 || comments
-    @long_comments = $2.to_s.strip
-    return @short_comments, @long_comments
-  end
-
-  public
-
-  # Strips and reencodes a commit log before insertion into the database
-  def self.normalize_comments(str, encoding)
-    Changeset.to_utf8(str.to_s.strip, encoding)
-  end
-
-  def self.to_utf8(str, encoding)
-    Redmine::CodesetUtil.to_utf8(str, encoding)
-  end
-end
--- a/.svn/pristine/f1/f11f6b57f7e2388c7777d4dc34576404ddd5230b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module AccessControl
-
-    class << self
-      def map
-        mapper = Mapper.new
-        yield mapper
-        @permissions ||= []
-        @permissions += mapper.mapped_permissions
-      end
-
-      def permissions
-        @permissions
-      end
-
-      # Returns the permission of given name or nil if it wasn't found
-      # Argument should be a symbol
-      def permission(name)
-        permissions.detect {|p| p.name == name}
-      end
-
-      # Returns the actions that are allowed by the permission of given name
-      def allowed_actions(permission_name)
-        perm = permission(permission_name)
-        perm ? perm.actions : []
-      end
-
-      def public_permissions
-        @public_permissions ||= @permissions.select {|p| p.public?}
-      end
-
-      def members_only_permissions
-        @members_only_permissions ||= @permissions.select {|p| p.require_member?}
-      end
-
-      def loggedin_only_permissions
-        @loggedin_only_permissions ||= @permissions.select {|p| p.require_loggedin?}
-      end
-
-      def read_action?(action)
-        if action.is_a?(Symbol)
-          perm = permission(action)
-          !perm.nil? && perm.read?
-        else
-          s = "#{action[:controller]}/#{action[:action]}"
-          permissions.detect {|p| p.actions.include?(s) && !p.read?}.nil?
-        end
-      end
-
-      def available_project_modules
-        @available_project_modules ||= @permissions.collect(&:project_module).uniq.compact
-      end
-
-      def modules_permissions(modules)
-        @permissions.select {|p| p.project_module.nil? || modules.include?(p.project_module.to_s)}
-      end
-    end
-
-    class Mapper
-      def initialize
-        @project_module = nil
-      end
-
-      def permission(name, hash, options={})
-        @permissions ||= []
-        options.merge!(:project_module => @project_module)
-        @permissions << Permission.new(name, hash, options)
-      end
-
-      def project_module(name, options={})
-        @project_module = name
-        yield self
-        @project_module = nil
-      end
-
-      def mapped_permissions
-        @permissions
-      end
-    end
-
-    class Permission
-      attr_reader :name, :actions, :project_module
-
-      def initialize(name, hash, options)
-        @name = name
-        @actions = []
-        @public = options[:public] || false
-        @require = options[:require]
-        @read = options[:read] || false
-        @project_module = options[:project_module]
-        hash.each do |controller, actions|
-          if actions.is_a? Array
-            @actions << actions.collect {|action| "#{controller}/#{action}"}
-          else
-            @actions << "#{controller}/#{actions}"
-          end
-        end
-        @actions.flatten!
-      end
-
-      def public?
-        @public
-      end
-
-      def require_member?
-        @require && @require == :member
-      end
-
-      def require_loggedin?
-        @require && (@require == :member || @require == :loggedin)
-      end
-
-      def read?
-        @read
-      end
-    end
-  end
-end
Binary file .svn/pristine/f1/f1cdf29a721cc514cb39f1d1983090024969bffe.svn-base has changed
--- a/.svn/pristine/f1/f1e462b67d8967f5d1fe2af96802c244faffb89d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssueRelationTest < ActiveSupport::TestCase
-  fixtures :projects,
-           :users,
-           :roles,
-           :members,
-           :member_roles,
-           :issues,
-           :issue_statuses,
-           :issue_relations,
-           :enabled_modules,
-           :enumerations,
-           :trackers,
-           :projects_trackers
-
-  include Redmine::I18n
-
-  def test_create
-    from = Issue.find(1)
-    to = Issue.find(2)
-
-    relation = IssueRelation.new :issue_from => from, :issue_to => to,
-                                 :relation_type => IssueRelation::TYPE_PRECEDES
-    assert relation.save
-    relation.reload
-    assert_equal IssueRelation::TYPE_PRECEDES, relation.relation_type
-    assert_equal from, relation.issue_from
-    assert_equal to, relation.issue_to
-  end
-
-  def test_create_minimum
-    relation = IssueRelation.new :issue_from => Issue.find(1), :issue_to => Issue.find(2)
-    assert relation.save
-    assert_equal IssueRelation::TYPE_RELATES, relation.relation_type
-  end
-
-  def test_follows_relation_should_be_reversed
-    from = Issue.find(1)
-    to = Issue.find(2)
-
-    relation = IssueRelation.new :issue_from => from, :issue_to => to,
-                                 :relation_type => IssueRelation::TYPE_FOLLOWS
-    assert relation.save
-    relation.reload
-    assert_equal IssueRelation::TYPE_PRECEDES, relation.relation_type
-    assert_equal to, relation.issue_from
-    assert_equal from, relation.issue_to
-  end
-
-  def test_follows_relation_should_not_be_reversed_if_validation_fails
-    from = Issue.find(1)
-    to = Issue.find(2)
-
-    relation = IssueRelation.new :issue_from => from, :issue_to => to,
-                                 :relation_type => IssueRelation::TYPE_FOLLOWS,
-                                 :delay => 'xx'
-    assert !relation.save
-    assert_equal IssueRelation::TYPE_FOLLOWS, relation.relation_type
-    assert_equal from, relation.issue_from
-    assert_equal to, relation.issue_to
-  end
-
-  def test_relation_type_for
-    from = Issue.find(1)
-    to = Issue.find(2)
-
-    relation = IssueRelation.new :issue_from => from, :issue_to => to,
-                                 :relation_type => IssueRelation::TYPE_PRECEDES
-    assert_equal IssueRelation::TYPE_PRECEDES, relation.relation_type_for(from)
-    assert_equal IssueRelation::TYPE_FOLLOWS, relation.relation_type_for(to)
-  end
-
-  def test_set_issue_to_dates_without_issue_to
-    r = IssueRelation.new(:issue_from => Issue.new(:start_date => Date.today),
-                          :relation_type => IssueRelation::TYPE_PRECEDES,
-                          :delay => 1)
-    assert_nil r.set_issue_to_dates
-  end
-
-  def test_set_issue_to_dates_without_issues
-    r = IssueRelation.new(:relation_type => IssueRelation::TYPE_PRECEDES, :delay => 1)
-    assert_nil r.set_issue_to_dates
-  end
-
-  def test_validates_circular_dependency
-    IssueRelation.delete_all
-    assert IssueRelation.create!(
-             :issue_from => Issue.find(1), :issue_to => Issue.find(2),
-             :relation_type => IssueRelation::TYPE_PRECEDES
-           )
-    assert IssueRelation.create!(
-             :issue_from => Issue.find(2), :issue_to => Issue.find(3),
-             :relation_type => IssueRelation::TYPE_PRECEDES
-           )
-    r = IssueRelation.new(
-          :issue_from => Issue.find(3), :issue_to => Issue.find(1),
-          :relation_type => IssueRelation::TYPE_PRECEDES
-        )
-    assert !r.save
-    assert_not_equal [], r.errors[:base]
-  end
-
-  def test_validates_circular_dependency_of_subtask
-    set_language_if_valid 'en'
-    issue1 = Issue.generate!
-    issue2 = Issue.generate!
-    IssueRelation.create!(
-      :issue_from => issue1, :issue_to => issue2,
-      :relation_type => IssueRelation::TYPE_PRECEDES
-    )
-    child = Issue.generate!(:parent_issue_id => issue2.id)
-    issue1.reload
-    child.reload
-
-    r = IssueRelation.new(
-          :issue_from => child, :issue_to => issue1,
-          :relation_type => IssueRelation::TYPE_PRECEDES
-        )
-    assert !r.save
-    assert_include 'This relation would create a circular dependency', r.errors.full_messages
-  end
-
-  def test_subtasks_should_allow_precedes_relation
-    parent = Issue.generate!
-    child1 = Issue.generate!(:parent_issue_id => parent.id)
-    child2 = Issue.generate!(:parent_issue_id => parent.id)
-
-    r = IssueRelation.new(
-          :issue_from => child1, :issue_to => child2,
-          :relation_type => IssueRelation::TYPE_PRECEDES
-        )
-    assert r.valid?
-    assert r.save
-  end
-
-  def test_validates_circular_dependency_on_reverse_relations
-    IssueRelation.delete_all
-    assert IssueRelation.create!(
-             :issue_from => Issue.find(1), :issue_to => Issue.find(3),
-             :relation_type => IssueRelation::TYPE_BLOCKS
-           )
-    assert IssueRelation.create!(
-             :issue_from => Issue.find(1), :issue_to => Issue.find(2),
-             :relation_type => IssueRelation::TYPE_BLOCKED
-           )
-    r = IssueRelation.new(
-          :issue_from => Issue.find(2), :issue_to => Issue.find(1),
-          :relation_type => IssueRelation::TYPE_BLOCKED
-        )
-    assert !r.save
-    assert_not_equal [], r.errors[:base]
-  end
-
-  def test_create_should_make_journal_entry
-    from = Issue.find(1)
-    to   = Issue.find(2)
-    from_journals = from.journals.size
-    to_journals   = to.journals.size
-    relation = IssueRelation.new(:issue_from => from, :issue_to => to,
-                                 :relation_type => IssueRelation::TYPE_PRECEDES)
-    assert relation.save
-    from.reload
-    to.reload
-    relation.reload
-    assert_equal from.journals.size, (from_journals + 1)
-    assert_equal to.journals.size, (to_journals + 1)
-    assert_equal 'relation', from.journals.last.details.last.property
-    assert_equal 'label_precedes', from.journals.last.details.last.prop_key
-    assert_equal '2', from.journals.last.details.last.value
-    assert_nil   from.journals.last.details.last.old_value
-    assert_equal 'relation', to.journals.last.details.last.property
-    assert_equal 'label_follows', to.journals.last.details.last.prop_key
-    assert_equal '1', to.journals.last.details.last.value
-    assert_nil   to.journals.last.details.last.old_value
-  end
-
-  def test_delete_should_make_journal_entry
-    relation = IssueRelation.find(1)
-    id = relation.id
-    from = relation.issue_from
-    to   = relation.issue_to
-    from_journals = from.journals.size
-    to_journals   = to.journals.size
-    assert relation.destroy
-    from.reload
-    to.reload
-    assert_equal from.journals.size, (from_journals + 1)
-    assert_equal to.journals.size, (to_journals + 1)
-    assert_equal 'relation', from.journals.last.details.last.property
-    assert_equal 'label_blocks', from.journals.last.details.last.prop_key
-    assert_equal '9', from.journals.last.details.last.old_value
-    assert_nil   from.journals.last.details.last.value
-    assert_equal 'relation', to.journals.last.details.last.property
-    assert_equal 'label_blocked_by', to.journals.last.details.last.prop_key
-    assert_equal '10', to.journals.last.details.last.old_value
-    assert_nil   to.journals.last.details.last.value
-  end
-end
--- a/.svn/pristine/f2/f2015be9c3b679bedb2c24e4bc1e2d51751badea.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redcloth3'
-require 'digest/md5'
-
-module Redmine
-  module WikiFormatting
-    module Textile
-      class Formatter < RedCloth3
-        include ActionView::Helpers::TagHelper
-        include Redmine::WikiFormatting::LinksHelper
-
-        alias :inline_auto_link :auto_link!
-        alias :inline_auto_mailto :auto_mailto!
-
-        # auto_link rule after textile rules so that it doesn't break !image_url! tags
-        RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto]
-
-        def initialize(*args)
-          super
-          self.hard_breaks=true
-          self.no_span_caps=true
-          self.filter_styles=false
-        end
-
-        def to_html(*rules)
-          @toc = []
-          super(*RULES).to_s
-        end
-
-        def get_section(index)
-          section = extract_sections(index)[1]
-          hash = Digest::MD5.hexdigest(section)
-          return section, hash
-        end
-
-        def update_section(index, update, hash=nil)
-          t = extract_sections(index)
-          if hash.present? && hash != Digest::MD5.hexdigest(t[1])
-            raise Redmine::WikiFormatting::StaleSectionError
-          end
-          t[1] = update unless t[1].blank?
-          t.reject(&:blank?).join "\n\n"
-        end
-
-        def extract_sections(index)
-          @pre_list = []
-          text = self.dup
-          rip_offtags text, false, false
-          before = ''
-          s = ''
-          after = ''
-          i = 0
-          l = 1
-          started = false
-          ended = false
-          text.scan(/(((?:.*?)(\A|\r?\n\s*\r?\n))(h(\d+)(#{A}#{C})\.(?::(\S+))?[ \t](.*?)$)|.*)/m).each do |all, content, lf, heading, level|
-            if heading.nil?
-              if ended
-                after << all
-              elsif started
-                s << all
-              else
-                before << all
-              end
-              break
-            end
-            i += 1
-            if ended
-              after << all
-            elsif i == index
-              l = level.to_i
-              before << content
-              s << heading
-              started = true
-            elsif i > index
-              s << content
-              if level.to_i > l
-                s << heading
-              else
-                after << heading
-                ended = true
-              end
-            else
-              before << all
-            end
-          end
-          sections = [before.strip, s.strip, after.strip]
-          sections.each {|section| smooth_offtags_without_code_highlighting section}
-          sections
-        end
-
-      private
-
-        # Patch for RedCloth.  Fixed in RedCloth r128 but _why hasn't released it yet.
-        # <a href="http://code.whytheluckystiff.net/redcloth/changeset/128">http://code.whytheluckystiff.net/redcloth/changeset/128</a>
-        def hard_break( text )
-          text.gsub!( /(.)\n(?!\n|\Z| *([#*=]+(\s|$)|[{|]))/, "\\1<br />" ) if hard_breaks
-        end
-
-        alias :smooth_offtags_without_code_highlighting :smooth_offtags
-        # Patch to add code highlighting support to RedCloth
-        def smooth_offtags( text )
-          unless @pre_list.empty?
-            ## replace <pre> content
-            text.gsub!(/<redpre#(\d+)>/) do
-              content = @pre_list[$1.to_i]
-              if content.match(/<code\s+class="(\w+)">\s?(.+)/m)
-                content = "<code class=\"#{$1} syntaxhl\">" +
-                  Redmine::SyntaxHighlighting.highlight_by_language($2, $1)
-              end
-              content
-            end
-          end
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/f2/f2726ad84a3873a4a39cbceb7b5b654ff347068a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class MyController < ApplicationController
-  before_filter :require_login
-  # let user change user's password when user has to
-  skip_before_filter :check_password_change, :only => :password
-
-  helper :issues
-  helper :users
-  helper :custom_fields
-
-  BLOCKS = { 'issuesassignedtome' => :label_assigned_to_me_issues,
-             'issuesreportedbyme' => :label_reported_issues,
-             'issueswatched' => :label_watched_issues,
-             'news' => :label_news_latest,
-             'calendar' => :label_calendar,
-             'documents' => :label_document_plural,
-             'timelog' => :label_spent_time
-           }.merge(Redmine::Views::MyPage::Block.additional_blocks).freeze
-
-  DEFAULT_LAYOUT = {  'left' => ['issuesassignedtome'],
-                      'right' => ['issuesreportedbyme']
-                   }.freeze
-
-  def index
-    page
-    render :action => 'page'
-  end
-
-  # Show user's page
-  def page
-    @user = User.current
-    @blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
-  end
-
-  # Edit user's account
-  def account
-    @user = User.current
-    @pref = @user.pref
-    if request.post?
-      @user.safe_attributes = params[:user]
-      @user.pref.attributes = params[:pref]
-      if @user.save
-        @user.pref.save
-        set_language_if_valid @user.language
-        flash[:notice] = l(:notice_account_updated)
-        redirect_to my_account_path
-        return
-      end
-    end
-  end
-
-  # Destroys user's account
-  def destroy
-    @user = User.current
-    unless @user.own_account_deletable?
-      redirect_to my_account_path
-      return
-    end
-
-    if request.post? && params[:confirm]
-      @user.destroy
-      if @user.destroyed?
-        logout_user
-        flash[:notice] = l(:notice_account_deleted)
-      end
-      redirect_to home_path
-    end
-  end
-
-  # Manage user's password
-  def password
-    @user = User.current
-    unless @user.change_password_allowed?
-      flash[:error] = l(:notice_can_t_change_password)
-      redirect_to my_account_path
-      return
-    end
-    if request.post?
-      if !@user.check_password?(params[:password])
-        flash.now[:error] = l(:notice_account_wrong_password)
-      elsif params[:password] == params[:new_password]
-        flash.now[:error] = l(:notice_new_password_must_be_different)
-      else
-        @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
-        @user.must_change_passwd = false
-        if @user.save
-          flash[:notice] = l(:notice_account_password_updated)
-          redirect_to my_account_path
-        end
-      end
-    end
-  end
-
-  # Create a new feeds key
-  def reset_rss_key
-    if request.post?
-      if User.current.rss_token
-        User.current.rss_token.destroy
-        User.current.reload
-      end
-      User.current.rss_key
-      flash[:notice] = l(:notice_feeds_access_key_reseted)
-    end
-    redirect_to my_account_path
-  end
-
-  # Create a new API key
-  def reset_api_key
-    if request.post?
-      if User.current.api_token
-        User.current.api_token.destroy
-        User.current.reload
-      end
-      User.current.api_key
-      flash[:notice] = l(:notice_api_access_key_reseted)
-    end
-    redirect_to my_account_path
-  end
-
-  # User's page layout configuration
-  def page_layout
-    @user = User.current
-    @blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT.dup
-    @block_options = []
-    BLOCKS.each do |k, v|
-      unless %w(top left right).detect {|f| (@blocks[f] ||= []).include?(k)}
-        @block_options << [l("my.blocks.#{v}", :default => [v, v.to_s.humanize]), k.dasherize]
-      end
-    end
-  end
-
-  # Add a block to user's page
-  # The block is added on top of the page
-  # params[:block] : id of the block to add
-  def add_block
-    block = params[:block].to_s.underscore
-    if block.present? && BLOCKS.key?(block)
-      @user = User.current
-      layout = @user.pref[:my_page_layout] || {}
-      # remove if already present in a group
-      %w(top left right).each {|f| (layout[f] ||= []).delete block }
-      # add it on top
-      layout['top'].unshift block
-      @user.pref[:my_page_layout] = layout
-      @user.pref.save
-    end
-    redirect_to my_page_layout_path
-  end
-
-  # Remove a block to user's page
-  # params[:block] : id of the block to remove
-  def remove_block
-    block = params[:block].to_s.underscore
-    @user = User.current
-    # remove block in all groups
-    layout = @user.pref[:my_page_layout] || {}
-    %w(top left right).each {|f| (layout[f] ||= []).delete block }
-    @user.pref[:my_page_layout] = layout
-    @user.pref.save
-    redirect_to my_page_layout_path
-  end
-
-  # Change blocks order on user's page
-  # params[:group] : group to order (top, left or right)
-  # params[:list-(top|left|right)] : array of block ids of the group
-  def order_blocks
-    group = params[:group]
-    @user = User.current
-    if group.is_a?(String)
-      group_items = (params["blocks"] || []).collect(&:underscore)
-      group_items.each {|s| s.sub!(/^block_/, '')}
-      if group_items and group_items.is_a? Array
-        layout = @user.pref[:my_page_layout] || {}
-        # remove group blocks if they are presents in other groups
-        %w(top left right).each {|f|
-          layout[f] = (layout[f] || []) - group_items
-        }
-        layout[group] = group_items
-        @user.pref[:my_page_layout] = layout
-        @user.pref.save
-      end
-    end
-    render :nothing => true
-  end
-end
--- a/.svn/pristine/f3/f3202e275b36fcaa2493cbc5897c69215e65214b.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class DocumentsControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :roles, :members, :member_roles,
-           :enabled_modules, :documents, :enumerations,
-           :groups_users, :attachments
-
-  def setup
-    User.current = nil
-  end
-
-  def test_index
-    # Sets a default category
-    e = Enumeration.find_by_name('Technical documentation')
-    e.update_attributes(:is_default => true)
-
-    get :index, :project_id => 'ecookbook'
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:grouped)
-
-    # Default category selected in the new document form
-    assert_tag :select, :attributes => {:name => 'document[category_id]'},
-                        :child => {:tag => 'option', :attributes => {:selected => 'selected'},
-                                                     :content => 'Technical documentation'}
-
-    assert ! DocumentCategory.find(16).active?
-    assert_no_tag :option, :attributes => {:value => '16'},
-                           :parent => {:tag => 'select', :attributes => {:id => 'document_category_id'} }
-  end
-
-  def test_index_grouped_by_date
-    get :index, :project_id => 'ecookbook', :sort_by => 'date'
-    assert_response :success
-    assert_tag 'h3', :content => '2007-02-12'
-  end
-
-  def test_index_grouped_by_title
-    get :index, :project_id => 'ecookbook', :sort_by => 'title'
-    assert_response :success
-    assert_tag 'h3', :content => 'T'
-  end
-
-  def test_index_grouped_by_author
-    get :index, :project_id => 'ecookbook', :sort_by => 'author'
-    assert_response :success
-    assert_tag 'h3', :content => 'John Smith'
-  end
-
-  def test_index_with_long_description
-    # adds a long description to the first document
-    doc = documents(:documents_001)
-    doc.update_attributes(:description => <<LOREM)
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut egestas, mi vehicula varius varius, ipsum massa fermentum orci, eget tristique ante sem vel mi. Nulla facilisi. Donec enim libero, luctus ac sagittis sit amet, vehicula sagittis magna. Duis ultrices molestie ante, eget scelerisque sem iaculis vitae. Etiam fermentum mauris vitae metus pharetra condimentum fermentum est pretium. Proin sollicitudin elementum quam quis pharetra.  Aenean facilisis nunc quis elit volutpat mollis. Aenean eleifend varius euismod. Ut dolor est, congue eget dapibus eget, elementum eu odio. Integer et lectus neque, nec scelerisque nisi. EndOfLineHere
-
-Vestibulum non velit mi. Aliquam scelerisque libero ut nulla fringilla a sollicitudin magna rhoncus.  Praesent a nunc lorem, ac porttitor eros. Sed ac diam nec neque interdum adipiscing quis quis justo. Donec arcu nunc, fringilla eu dictum at, venenatis ac sem. Vestibulum quis elit urna, ac mattis sapien. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
-LOREM
-
-    get :index, :project_id => 'ecookbook'
-    assert_response :success
-    assert_template 'index'
-
-    # should only truncate on new lines to avoid breaking wiki formatting
-    assert_select '.wiki p', :text => (doc.description.split("\n").first + '...')
-    assert_select '.wiki p', :text => Regexp.new(Regexp.escape("EndOfLineHere..."))
-  end
-
-  def test_show
-    get :show, :id => 1
-    assert_response :success
-    assert_template 'show'
-  end
-
-  def test_new
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_create_with_one_attachment
-    ActionMailer::Base.deliveries.clear
-    @request.session[:user_id] = 2
-    set_tmp_attachments_directory
-
-    with_settings :notified_events => %w(document_added) do
-      post :create, :project_id => 'ecookbook',
-               :document => { :title => 'DocumentsControllerTest#test_post_new',
-                              :description => 'This is a new document',
-                              :category_id => 2},
-               :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
-    end
-    assert_redirected_to '/projects/ecookbook/documents'
-
-    document = Document.find_by_title('DocumentsControllerTest#test_post_new')
-    assert_not_nil document
-    assert_equal Enumeration.find(2), document.category
-    assert_equal 1, document.attachments.size
-    assert_equal 'testfile.txt', document.attachments.first.filename
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_create_with_failure
-    @request.session[:user_id] = 2
-    assert_no_difference 'Document.count' do
-      post :create, :project_id => 'ecookbook', :document => { :title => ''}
-    end
-    assert_response :success
-    assert_template 'new'
-  end
-
-  def test_create_non_default_category
-    @request.session[:user_id] = 2
-    category2 = Enumeration.find_by_name('User documentation')
-    category2.update_attributes(:is_default => true)
-    category1 = Enumeration.find_by_name('Uncategorized')
-    post :create,
-         :project_id => 'ecookbook',
-         :document => { :title => 'no default',
-                        :description => 'This is a new document',
-                        :category_id => category1.id }
-    assert_redirected_to '/projects/ecookbook/documents'
-    doc = Document.find_by_title('no default')
-    assert_not_nil doc
-    assert_equal category1.id, doc.category_id
-    assert_equal category1, doc.category
-  end
-
-  def test_edit
-    @request.session[:user_id] = 2
-    get :edit, :id => 1
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_update
-    @request.session[:user_id] = 2
-    put :update, :id => 1, :document => {:title => 'test_update'}
-    assert_redirected_to '/documents/1'
-    document = Document.find(1)
-    assert_equal 'test_update', document.title
-  end
-
-  def test_update_with_failure
-    @request.session[:user_id] = 2
-    put :update, :id => 1, :document => {:title => ''}
-    assert_response :success
-    assert_template 'edit'
-  end
-
-  def test_destroy
-    @request.session[:user_id] = 2
-    assert_difference 'Document.count', -1 do
-      delete :destroy, :id => 1
-    end
-    assert_redirected_to '/projects/ecookbook/documents'
-    assert_nil Document.find_by_id(1)
-  end
-
-  def test_add_attachment
-    @request.session[:user_id] = 2
-    assert_difference 'Attachment.count' do
-      post :add_attachment, :id => 1,
-        :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
-    end
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_equal Document.find(1), attachment.container
-  end
-end
--- a/.svn/pristine/f3/f3937f219362099cca8dc63d36f1da6d0e5c4f05.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::NewsTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :news
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  should_allow_api_authentication(:get, "/projects/onlinestore/news.xml")
-  should_allow_api_authentication(:get, "/projects/onlinestore/news.json")
-
-  test "GET /news.xml should return news" do
-    get '/news.xml'
-
-    assert_tag :tag => 'news',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'news',
-        :child => {
-          :tag => 'id',
-          :content => '2'
-        }
-      }
-  end
-
-  test "GET /news.json should return news" do
-    get '/news.json'
-
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json
-    assert_kind_of Array, json['news']
-    assert_kind_of Hash, json['news'].first
-    assert_equal 2, json['news'].first['id']
-  end
-
-  test "GET /projects/:project_id/news.xml should return news" do
-    get '/projects/ecookbook/news.xml'
-
-    assert_tag :tag => 'news',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'news',
-        :child => {
-          :tag => 'id',
-          :content => '2'
-        }
-      }
-  end
-
-  test "GET /projects/:project_id/news.json should return news" do
-    get '/projects/ecookbook/news.json'
-
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json
-    assert_kind_of Array, json['news']
-    assert_kind_of Hash, json['news'].first
-    assert_equal 2, json['news'].first['id']
-  end
-end
--- a/.svn/pristine/f4/f43305298989567d96f5b7cd3fec323aa70a3dd0.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingQueriesTest < ActionController::IntegrationTest
-  def test_queries
-    assert_routing(
-        { :method => 'get', :path => "/queries.xml" },
-        { :controller => 'queries', :action => 'index', :format => 'xml' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/queries.json" },
-        { :controller => 'queries', :action => 'index', :format => 'json' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/queries/new" },
-        { :controller => 'queries', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/queries" },
-        { :controller => 'queries', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/queries/1/edit" },
-        { :controller => 'queries', :action => 'edit', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/queries/1" },
-        { :controller => 'queries', :action => 'update', :id => '1' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/queries/1" },
-        { :controller => 'queries', :action => 'destroy', :id => '1' }
-      )
-  end
-
-  def test_queries_scoped_under_project
-    assert_routing(
-        { :method => 'get', :path => "/projects/redmine/queries/new" },
-        { :controller => 'queries', :action => 'new', :project_id => 'redmine' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/redmine/queries" },
-        { :controller => 'queries', :action => 'create', :project_id => 'redmine' }
-      )
-  end
-end
--- a/.svn/pristine/f4/f45cadd45e22c8df0a53045d3c2f398d9f064ea9.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,370 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoryTest < ActiveSupport::TestCase
-  fixtures :projects,
-           :trackers,
-           :projects_trackers,
-           :enabled_modules,
-           :repositories,
-           :issues,
-           :issue_statuses,
-           :issue_categories,
-           :changesets,
-           :changes,
-           :users,
-           :members,
-           :member_roles,
-           :roles,
-           :enumerations
-
-  include Redmine::I18n
-
-  def setup
-    @repository = Project.find(1).repository
-  end
-
-  def test_blank_log_encoding_error_message
-    set_language_if_valid 'en'
-    repo = Repository::Bazaar.new(
-                        :project      => Project.find(3),
-                        :url          => "/test",
-                        :log_encoding => ''
-                      )
-    assert !repo.save
-    assert_include "Commit messages encoding can't be blank",
-                   repo.errors.full_messages
-  end
-
-  def test_blank_log_encoding_error_message_fr
-    set_language_if_valid 'fr'
-    str = "Encodage des messages de commit doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    repo = Repository::Bazaar.new(
-                        :project      => Project.find(3),
-                        :url          => "/test"
-                      )
-    assert !repo.save
-    assert_include str, repo.errors.full_messages
-  end
-
-  def test_create
-    repository = Repository::Subversion.new(:project => Project.find(3))
-    assert !repository.save
-
-    repository.url = "svn://localhost"
-    assert repository.save
-    repository.reload
-
-    project = Project.find(3)
-    assert_equal repository, project.repository
-  end
-
-  def test_first_repository_should_be_set_as_default
-    repository1 = Repository::Subversion.new(
-                      :project => Project.find(3),
-                      :identifier => 'svn1',
-                      :url => 'file:///svn1'
-                    )
-    assert repository1.save
-    assert repository1.is_default?
-
-    repository2 = Repository::Subversion.new(
-                      :project => Project.find(3),
-                      :identifier => 'svn2',
-                      :url => 'file:///svn2'
-                    )
-    assert repository2.save
-    assert !repository2.is_default?
-
-    assert_equal repository1, Project.find(3).repository
-    assert_equal [repository1, repository2], Project.find(3).repositories.sort
-  end
-
-  def test_identifier_should_accept_letters_digits_dashes_and_underscores
-    r = Repository::Subversion.new(
-      :project_id => 3,
-      :identifier => 'svn-123_45',
-      :url => 'file:///svn'
-    )
-    assert r.save
-  end
-  
-  def test_identifier_should_not_be_frozen_for_a_new_repository
-    assert_equal false, Repository.new.identifier_frozen?
-  end
-
-  def test_identifier_should_not_be_frozen_for_a_saved_repository_with_blank_identifier
-    Repository.update_all(["identifier = ''"], "id = 10")
-
-    assert_equal false, Repository.find(10).identifier_frozen?
-  end
-
-  def test_identifier_should_be_frozen_for_a_saved_repository_with_valid_identifier
-    Repository.update_all(["identifier = 'abc123'"], "id = 10")
-
-    assert_equal true, Repository.find(10).identifier_frozen?
-  end
-
-  def test_identifier_should_not_accept_change_if_frozen
-    r = Repository.new(:identifier => 'foo')
-    r.stubs(:identifier_frozen?).returns(true)
-
-    r.identifier = 'bar'
-    assert_equal 'foo', r.identifier
-  end
-
-  def test_identifier_should_accept_change_if_not_frozen
-    r = Repository.new(:identifier => 'foo')
-    r.stubs(:identifier_frozen?).returns(false)
-
-    r.identifier = 'bar'
-    assert_equal 'bar', r.identifier
-  end
-
-  def test_destroy
-    repository = Repository.find(10)
-    changesets = repository.changesets.count
-    changes = repository.filechanges.count
-
-    assert_difference 'Changeset.count', -changesets do
-      assert_difference 'Change.count', -changes do
-        Repository.find(10).destroy
-      end
-    end
-  end
-
-  def test_destroy_should_delete_parents_associations
-    changeset = Changeset.find(102)
-    changeset.parents = Changeset.find_all_by_id([100, 101])
-
-    assert_difference 'Changeset.connection.select_all("select * from changeset_parents").size', -2 do
-      Repository.find(10).destroy
-    end
-  end
-
-  def test_destroy_should_delete_issues_associations
-    changeset = Changeset.find(102)
-    changeset.issues = Issue.find_all_by_id([1, 2])
-
-    assert_difference 'Changeset.connection.select_all("select * from changesets_issues").size', -2 do
-      Repository.find(10).destroy
-    end
-  end
-
-  def test_should_not_create_with_disabled_scm
-    # disable Subversion
-    with_settings :enabled_scm => ['Darcs', 'Git'] do
-      repository = Repository::Subversion.new(
-                      :project => Project.find(3), :url => "svn://localhost")
-      assert !repository.save
-      assert_include I18n.translate('activerecord.errors.messages.invalid'),
-                     repository.errors[:type]
-    end
-  end
-
-  def test_scan_changesets_for_issue_ids
-    Setting.default_language = 'en'
-
-    Setting.commit_ref_keywords = 'refs , references, IssueID'
-    Setting.commit_update_keywords = [
-      {'keywords' => 'fixes , closes', 'status_id' => IssueStatus.where(:is_closed => true).first.id, 'done_ratio' => '90'}
-    ]
-    Setting.default_language = 'en'
-    ActionMailer::Base.deliveries.clear
-
-    # make sure issue 1 is not already closed
-    fixed_issue = Issue.find(1)
-    assert !fixed_issue.status.is_closed?
-    old_status = fixed_issue.status
-
-    with_settings :notified_events => %w(issue_added issue_updated) do
-      Repository.scan_changesets_for_issue_ids
-    end
-    assert_equal [101, 102], Issue.find(3).changeset_ids
-
-    # fixed issues
-    fixed_issue.reload
-    assert fixed_issue.status.is_closed?
-    assert_equal 90, fixed_issue.done_ratio
-    assert_equal [101], fixed_issue.changeset_ids
-
-    # issue change
-    journal = fixed_issue.journals.reorder('created_on desc').first
-    assert_equal User.find_by_login('dlopper'), journal.user
-    assert_equal 'Applied in changeset r2.', journal.notes
-
-    # 2 email notifications
-    assert_equal 2, ActionMailer::Base.deliveries.size
-    mail = ActionMailer::Base.deliveries.first
-    assert_not_nil mail
-    assert mail.subject.starts_with?(
-        "[#{fixed_issue.project.name} - #{fixed_issue.tracker.name} ##{fixed_issue.id}]")
-    assert_mail_body_match(
-        "Status changed from #{old_status} to #{fixed_issue.status}", mail)
-
-    # ignoring commits referencing an issue of another project
-    assert_equal [], Issue.find(4).changesets
-  end
-
-  def test_for_changeset_comments_strip
-    repository = Repository::Mercurial.create(
-                    :project => Project.find( 4 ),
-                    :url => '/foo/bar/baz' )
-    comment = <<-COMMENT
-    This is a loooooooooooooooooooooooooooong comment                                                   
-                                                                                                       
-                                                                                            
-    COMMENT
-    changeset = Changeset.new(
-      :comments => comment, :commit_date => Time.now,
-      :revision => 0, :scmid => 'f39b7922fb3c',
-      :committer => 'foo <foo@example.com>',
-      :committed_on => Time.now, :repository => repository )
-    assert( changeset.save )
-    assert_not_equal( comment, changeset.comments )
-    assert_equal( 'This is a loooooooooooooooooooooooooooong comment',
-                  changeset.comments )
-  end
-
-  def test_for_urls_strip_cvs
-    repository = Repository::Cvs.create(
-        :project => Project.find(4),
-        :url => ' :pserver:login:password@host:/path/to/the/repository',
-        :root_url => 'foo  ',
-        :log_encoding => 'UTF-8')
-    assert repository.save
-    repository.reload
-    assert_equal ':pserver:login:password@host:/path/to/the/repository',
-                  repository.url
-    assert_equal 'foo', repository.root_url
-  end
-
-  def test_for_urls_strip_subversion
-    repository = Repository::Subversion.create(
-        :project => Project.find(4),
-        :url => ' file:///dummy   ')
-    assert repository.save
-    repository.reload
-    assert_equal 'file:///dummy', repository.url
-  end
-
-  def test_for_urls_strip_git
-    repository = Repository::Git.create(
-        :project => Project.find(4),
-        :url => ' c:\dummy   ')
-    assert repository.save
-    repository.reload
-    assert_equal 'c:\dummy', repository.url
-  end
-
-  def test_manual_user_mapping
-    assert_no_difference "Changeset.where('user_id <> 2').count" do
-      c = Changeset.create!(
-              :repository => @repository,
-              :committer => 'foo',
-              :committed_on => Time.now,
-              :revision => 100,
-              :comments => 'Committed by foo.'
-            )
-      assert_nil c.user
-      @repository.committer_ids = {'foo' => '2'}
-      assert_equal User.find(2), c.reload.user
-      # committer is now mapped
-      c = Changeset.create!(
-              :repository => @repository,
-              :committer => 'foo',
-              :committed_on => Time.now,
-              :revision => 101,
-              :comments => 'Another commit by foo.'
-            )
-      assert_equal User.find(2), c.user
-    end
-  end
-
-  def test_auto_user_mapping_by_username
-    c = Changeset.create!(
-          :repository   => @repository,
-          :committer    => 'jsmith',
-          :committed_on => Time.now,
-          :revision     => 100,
-          :comments     => 'Committed by john.'
-        )
-    assert_equal User.find(2), c.user
-  end
-
-  def test_auto_user_mapping_by_email
-    c = Changeset.create!(
-          :repository   => @repository,
-          :committer    => 'john <jsmith@somenet.foo>',
-          :committed_on => Time.now,
-          :revision     => 100,
-          :comments     => 'Committed by john.'
-        )
-    assert_equal User.find(2), c.user
-  end
-
-  def test_filesystem_avaialbe
-    klass = Repository::Filesystem
-    assert klass.scm_adapter_class
-    assert_equal true, klass.scm_available
-  end
-
-  def test_merge_extra_info
-    repo = Repository::Subversion.new(:project => Project.find(3))
-    assert !repo.save
-    repo.url = "svn://localhost"
-    assert repo.save
-    repo.reload
-    project = Project.find(3)
-    assert_equal repo, project.repository
-    assert_nil repo.extra_info
-    h1 = {"test_1" => {"test_11" => "test_value_11"}}
-    repo.merge_extra_info(h1)
-    assert_equal h1, repo.extra_info
-    h2 = {"test_2" => {
-                   "test_21" => "test_value_21",
-                   "test_22" => "test_value_22",
-                  }}
-    repo.merge_extra_info(h2)
-    assert_equal (h = {"test_11" => "test_value_11"}),
-                 repo.extra_info["test_1"]
-    assert_equal "test_value_21",
-                 repo.extra_info["test_2"]["test_21"]
-    h3 = {"test_2" => {
-                   "test_23" => "test_value_23",
-                   "test_24" => "test_value_24",
-                  }}
-    repo.merge_extra_info(h3)
-    assert_equal (h = {"test_11" => "test_value_11"}),
-                 repo.extra_info["test_1"]
-    assert_nil repo.extra_info["test_2"]["test_21"]
-    assert_equal "test_value_23",
-                 repo.extra_info["test_2"]["test_23"]
-  end
-
-  def test_sort_should_not_raise_an_error_with_nil_identifiers
-    r1 = Repository.new
-    r2 = Repository.new
-
-    assert_nothing_raised do
-      [r1, r2].sort
-    end
-  end
-end
--- a/.svn/pristine/f4/f4bd9cf8c7227a2836ae6369246ebcb1a93c4265.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'builder'
-
-module Redmine
-  module Views
-    module Builders
-      class Xml < ::Builder::XmlMarkup
-        def initialize(request, response)
-          super()
-          instruct!
-        end
-
-        def output
-          target!
-        end
-
-        def method_missing(sym, *args, &block)
-          if args.size == 1 && args.first.is_a?(::Time)
-            __send__ sym, args.first.xmlschema, &block
-          else
-            super
-          end
-        end
-
-        def array(name, options={}, &block)
-          __send__ name, (options || {}).merge(:type => 'array'), &block
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/f4/f4f821cd00b02aca16ddb8be972d9bda8452365e.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,224 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module QueriesHelper
-  def filters_options_for_select(query)
-    options_for_select(filters_options(query))
-  end
-
-  def filters_options(query)
-    options = [[]]
-    options += query.available_filters.map do |field, field_options|
-      [field_options[:name], field]
-    end
-  end
-
-  def query_filters_hidden_tags(query)
-    tags = ''.html_safe
-    query.filters.each do |field, options|
-      tags << hidden_field_tag("f[]", field, :id => nil)
-      tags << hidden_field_tag("op[#{field}]", options[:operator], :id => nil)
-      options[:values].each do |value|
-        tags << hidden_field_tag("v[#{field}][]", value, :id => nil)
-      end
-    end
-    tags
-  end
-
-  def query_columns_hidden_tags(query)
-    tags = ''.html_safe
-    query.columns.each do |column|
-      tags << hidden_field_tag("c[]", column.name, :id => nil)
-    end
-    tags
-  end
-
-  def query_hidden_tags(query)
-    query_filters_hidden_tags(query) + query_columns_hidden_tags(query)
-  end
-
-  def available_block_columns_tags(query)
-    tags = ''.html_safe
-    query.available_block_columns.each do |column|
-      tags << content_tag('label', check_box_tag('c[]', column.name.to_s, query.has_column?(column)) + " #{column.caption}", :class => 'inline')
-    end
-    tags
-  end
-
-  def query_available_inline_columns_options(query)
-    (query.available_inline_columns - query.columns).reject(&:frozen?).collect {|column| [column.caption, column.name]}
-  end
-
-  def query_selected_inline_columns_options(query)
-    (query.inline_columns & query.available_inline_columns).reject(&:frozen?).collect {|column| [column.caption, column.name]}
-  end
-
-  def render_query_columns_selection(query, options={})
-    tag_name = (options[:name] || 'c') + '[]'
-    render :partial => 'queries/columns', :locals => {:query => query, :tag_name => tag_name}
-  end
-
-  def column_header(column)
-    column.sortable ? sort_header_tag(column.name.to_s, :caption => column.caption,
-                                                        :default_order => column.default_order) :
-                      content_tag('th', h(column.caption))
-  end
-
-  def column_content(column, issue)
-    value = column.value(issue)
-    if value.is_a?(Array)
-      value.collect {|v| column_value(column, issue, v)}.compact.join(', ').html_safe
-    else
-      column_value(column, issue, value)
-    end
-  end
-  
-  def column_value(column, issue, value)
-    case value.class.name
-    when 'String'
-      if column.name == :subject
-        link_to(h(value), :controller => 'issues', :action => 'show', :id => issue)
-      elsif column.name == :description
-        issue.description? ? content_tag('div', textilizable(issue, :description), :class => "wiki") : ''
-      else
-        h(value)
-      end
-    when 'Time'
-      format_time(value)
-    when 'Date'
-      format_date(value)
-    when 'Fixnum'
-      if column.name == :id
-        link_to value, issue_path(issue)
-      elsif column.name == :done_ratio
-        progress_bar(value, :width => '80px')
-      else
-        value.to_s
-      end
-    when 'Float'
-      sprintf "%.2f", value
-    when 'User'
-      link_to_user value
-    when 'Project'
-      link_to_project value
-    when 'Version'
-      link_to(h(value), :controller => 'versions', :action => 'show', :id => value)
-    when 'TrueClass'
-      l(:general_text_Yes)
-    when 'FalseClass'
-      l(:general_text_No)
-    when 'Issue'
-      value.visible? ? link_to_issue(value) : "##{value.id}"
-    when 'IssueRelation'
-      other = value.other_issue(issue)
-      content_tag('span',
-        (l(value.label_for(issue)) + " " + link_to_issue(other, :subject => false, :tracker => false)).html_safe,
-        :class => value.css_classes_for(issue))
-    else
-      h(value)
-    end
-  end
-
-  def csv_content(column, issue)
-    value = column.value(issue)
-    if value.is_a?(Array)
-      value.collect {|v| csv_value(column, issue, v)}.compact.join(', ')
-    else
-      csv_value(column, issue, value)
-    end
-  end
-
-  def csv_value(column, issue, value)
-    case value.class.name
-    when 'Time'
-      format_time(value)
-    when 'Date'
-      format_date(value)
-    when 'Float'
-      sprintf("%.2f", value).gsub('.', l(:general_csv_decimal_separator))
-    when 'IssueRelation'
-      other = value.other_issue(issue)
-      l(value.label_for(issue)) + " ##{other.id}"
-    else
-      value.to_s
-    end
-  end
-
-  def query_to_csv(items, query, options={})
-    encoding = l(:general_csv_encoding)
-    columns = (options[:columns] == 'all' ? query.available_inline_columns : query.inline_columns)
-    query.available_block_columns.each do |column|
-      if options[column.name].present?
-        columns << column
-      end
-    end
-
-    export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
-      # csv header fields
-      csv << columns.collect {|c| Redmine::CodesetUtil.from_utf8(c.caption.to_s, encoding) }
-      # csv lines
-      items.each do |item|
-        csv << columns.collect {|c| Redmine::CodesetUtil.from_utf8(csv_content(c, item), encoding) }
-      end
-    end
-    export
-  end
-
-  # Retrieve query from session or build a new query
-  def retrieve_query
-    if !params[:query_id].blank?
-      cond = "project_id IS NULL"
-      cond << " OR project_id = #{@project.id}" if @project
-      @query = IssueQuery.where(cond).find(params[:query_id])
-      raise ::Unauthorized unless @query.visible?
-      @query.project = @project
-      session[:query] = {:id => @query.id, :project_id => @query.project_id}
-      sort_clear
-    elsif api_request? || params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
-      # Give it a name, required to be valid
-      @query = IssueQuery.new(:name => "_")
-      @query.project = @project
-      @query.build_from_params(params)
-      session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
-    else
-      # retrieve from session
-      @query = nil
-      @query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id]
-      @query ||= IssueQuery.new(:name => "_", :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names])
-      @query.project = @project
-    end
-  end
-
-  def retrieve_query_from_session
-    if session[:query]
-      if session[:query][:id]
-        @query = IssueQuery.find_by_id(session[:query][:id])
-        return unless @query
-      else
-        @query = IssueQuery.new(:name => "_", :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names])
-      end
-      if session[:query].has_key?(:project_id)
-        @query.project_id = session[:query][:project_id]
-      else
-        @query.project = @project
-      end
-      @query
-    end
-  end
-end
--- a/.svn/pristine/f5/f57965ef8e80be257ec5fce2399cf84a7480d6c4.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Scm
-    module Adapters
-      class CommandFailed < StandardError #:nodoc:
-      end
-    end
-  end
-end
--- a/.svn/pristine/f5/f57cb4b2fd4e8b282707982829017761e21ff080.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module Ciphering
-    def self.included(base)
-      base.extend ClassMethods
-    end
-
-    class << self
-      def encrypt_text(text)
-        if cipher_key.blank? || text.blank?
-          text
-        else
-          c = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
-          iv = c.random_iv
-          c.encrypt
-          c.key = cipher_key
-          c.iv = iv
-          e = c.update(text.to_s)
-          e << c.final
-          "aes-256-cbc:" + [e, iv].map {|v| Base64.encode64(v).strip}.join('--')
-        end
-      end
-
-      def decrypt_text(text)
-        if text && match = text.match(/\Aaes-256-cbc:(.+)\Z/)
-          if cipher_key.blank?
-            logger.error "Attempt to decrypt a ciphered text with no cipher key configured in config/configuration.yml" if logger
-            return text
-          end
-          text = match[1]
-          c = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
-          e, iv = text.split("--").map {|s| Base64.decode64(s)}
-          c.decrypt
-          c.key = cipher_key
-          c.iv = iv
-          d = c.update(e)
-          d << c.final
-        else
-          text
-        end
-      end
-
-      def cipher_key
-        key = Redmine::Configuration['database_cipher_key'].to_s
-        key.blank? ? nil : Digest::SHA256.hexdigest(key)
-      end
-      
-      def logger
-        Rails.logger
-      end
-    end
-
-    module ClassMethods
-      def encrypt_all(attribute)
-        transaction do
-          all.each do |object|
-            clear = object.send(attribute)
-            object.send "#{attribute}=", clear
-            raise(ActiveRecord::Rollback) unless object.save(:validation => false)
-          end
-        end ? true : false
-      end
-
-      def decrypt_all(attribute)
-        transaction do
-          all.each do |object|
-            clear = object.send(attribute)
-            object.send :write_attribute, attribute, clear
-            raise(ActiveRecord::Rollback) unless object.save(:validation => false)
-          end
-        end
-      end ? true : false
-    end
-
-    private
-
-    # Returns the value of the given ciphered attribute
-    def read_ciphered_attribute(attribute)
-      Redmine::Ciphering.decrypt_text(read_attribute(attribute))
-    end
-
-    # Sets the value of the given ciphered attribute
-    def write_ciphered_attribute(attribute, value)
-      write_attribute(attribute, Redmine::Ciphering.encrypt_text(value))
-    end
-  end
-end
--- a/.svn/pristine/f5/f593ea5869b339d3716433b9f9c8cbcd53fdd758.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::RolesTest < Redmine::ApiTest::Base
-  fixtures :roles
-
-  def setup
-    Setting.rest_api_enabled = '1'
-  end
-
-  test "GET /roles.xml should return the roles" do
-    get '/roles.xml'
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_equal 3, assigns(:roles).size
-
-    assert_tag :tag => 'roles',
-      :attributes => {:type => 'array'},
-      :child => {
-        :tag => 'role',
-        :child => {
-          :tag => 'id',
-          :content => '2',
-          :sibling => {
-            :tag => 'name',
-            :content => 'Developer'
-          }
-        }
-      }
-  end
-
-  test "GET /roles.json should return the roles" do
-    get '/roles.json'
-
-    assert_response :success
-    assert_equal 'application/json', @response.content_type
-    assert_equal 3, assigns(:roles).size
-
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json
-    assert_kind_of Array, json['roles']
-    assert_include({'id' => 2, 'name' => 'Developer'}, json['roles'])
-  end
-
-  test "GET /roles/:id.xml should return the role" do
-    get '/roles/1.xml'
-
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-
-    assert_select 'role' do
-      assert_select 'name', :text => 'Manager'
-      assert_select 'role permissions[type=array]' do
-        assert_select 'permission', Role.find(1).permissions.size
-        assert_select 'permission', :text => 'view_issues'
-      end
-    end
-  end
-end
--- a/.svn/pristine/f6/f60338f68ffe02f90e6ab9b5d825ff71b8197897.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1270 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'forwardable'
-require 'cgi'
-
-module ApplicationHelper
-  include Redmine::WikiFormatting::Macros::Definitions
-  include Redmine::I18n
-  include GravatarHelper::PublicMethods
-  include Redmine::Pagination::Helper
-
-  extend Forwardable
-  def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter
-
-  # Return true if user is authorized for controller/action, otherwise false
-  def authorize_for(controller, action)
-    User.current.allowed_to?({:controller => controller, :action => action}, @project)
-  end
-
-  # Display a link if user is authorized
-  #
-  # @param [String] name Anchor text (passed to link_to)
-  # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized
-  # @param [optional, Hash] html_options Options passed to link_to
-  # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to
-  def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
-    link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
-  end
-
-  # Displays a link to user's account page if active
-  def link_to_user(user, options={})
-    if user.is_a?(User)
-      name = h(user.name(options[:format]))
-      if user.active? || (User.current.admin? && user.logged?)
-        link_to name, user_path(user), :class => user.css_classes
-      else
-        name
-      end
-    else
-      h(user.to_s)
-    end
-  end
-
-  # Displays a link to +issue+ with its subject.
-  # Examples:
-  #
-  #   link_to_issue(issue)                        # => Defect #6: This is the subject
-  #   link_to_issue(issue, :truncate => 6)        # => Defect #6: This i...
-  #   link_to_issue(issue, :subject => false)     # => Defect #6
-  #   link_to_issue(issue, :project => true)      # => Foo - Defect #6
-  #   link_to_issue(issue, :subject => false, :tracker => false)     # => #6
-  #
-  def link_to_issue(issue, options={})
-    title = nil
-    subject = nil
-    text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}"
-    if options[:subject] == false
-      title = truncate(issue.subject, :length => 60)
-    else
-      subject = issue.subject
-      if options[:truncate]
-        subject = truncate(subject, :length => options[:truncate])
-      end
-    end
-    only_path = options[:only_path].nil? ? true : options[:only_path]
-    s = link_to text, issue_path(issue, :only_path => only_path), :class => issue.css_classes, :title => title
-    s << h(": #{subject}") if subject
-    s = h("#{issue.project} - ") + s if options[:project]
-    s
-  end
-
-  # Generates a link to an attachment.
-  # Options:
-  # * :text - Link text (default to attachment filename)
-  # * :download - Force download (default: false)
-  def link_to_attachment(attachment, options={})
-    text = options.delete(:text) || attachment.filename
-    route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path
-    html_options = options.slice!(:only_path)
-    url = send(route_method, attachment, attachment.filename, options)
-    link_to text, url, html_options
-  end
-
-  # Generates a link to a SCM revision
-  # Options:
-  # * :text - Link text (default to the formatted revision)
-  def link_to_revision(revision, repository, options={})
-    if repository.is_a?(Project)
-      repository = repository.repository
-    end
-    text = options.delete(:text) || format_revision(revision)
-    rev = revision.respond_to?(:identifier) ? revision.identifier : revision
-    link_to(
-        h(text),
-        {:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev},
-        :title => l(:label_revision_id, format_revision(revision))
-      )
-  end
-
-  # Generates a link to a message
-  def link_to_message(message, options={}, html_options = nil)
-    link_to(
-      truncate(message.subject, :length => 60),
-      board_message_path(message.board_id, message.parent_id || message.id, {
-        :r => (message.parent_id && message.id),
-        :anchor => (message.parent_id ? "message-#{message.id}" : nil)
-      }.merge(options)),
-      html_options
-    )
-  end
-
-  # Generates a link to a project if active
-  # Examples:
-  #
-  #   link_to_project(project)                          # => link to the specified project overview
-  #   link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options
-  #   link_to_project(project, {}, :class => "project") # => html options with default url (project overview)
-  #
-  def link_to_project(project, options={}, html_options = nil)
-    if project.archived?
-      h(project.name)
-    elsif options.key?(:action)
-      ActiveSupport::Deprecation.warn "#link_to_project with :action option is deprecated and will be removed in Redmine 3.0."
-      url = {:controller => 'projects', :action => 'show', :id => project}.merge(options)
-      link_to project.name, url, html_options
-    else
-      link_to project.name, project_path(project, options), html_options
-    end
-  end
-
-  # Generates a link to a project settings if active
-  def link_to_project_settings(project, options={}, html_options=nil)
-    if project.active?
-      link_to project.name, settings_project_path(project, options), html_options
-    elsif project.archived?
-      h(project.name)
-    else
-      link_to project.name, project_path(project, options), html_options
-    end
-  end
-
-  def wiki_page_path(page, options={})
-    url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options))
-  end
-
-  def thumbnail_tag(attachment)
-    link_to image_tag(thumbnail_path(attachment)),
-      named_attachment_path(attachment, attachment.filename),
-      :title => attachment.filename
-  end
-
-  def toggle_link(name, id, options={})
-    onclick = "$('##{id}').toggle(); "
-    onclick << (options[:focus] ? "$('##{options[:focus]}').focus(); " : "this.blur(); ")
-    onclick << "return false;"
-    link_to(name, "#", :onclick => onclick)
-  end
-
-  def image_to_function(name, function, html_options = {})
-    html_options.symbolize_keys!
-    tag(:input, html_options.merge({
-        :type => "image", :src => image_path(name),
-        :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
-        }))
-  end
-
-  def format_activity_title(text)
-    h(truncate_single_line(text, :length => 100))
-  end
-
-  def format_activity_day(date)
-    date == User.current.today ? l(:label_today).titleize : format_date(date)
-  end
-
-  def format_activity_description(text)
-    h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')
-       ).gsub(/[\r\n]+/, "<br />").html_safe
-  end
-
-  def format_version_name(version)
-    if version.project == @project
-      h(version)
-    else
-      h("#{version.project} - #{version}")
-    end
-  end
-
-  def due_date_distance_in_words(date)
-    if date
-      l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date))
-    end
-  end
-
-  # Renders a tree of projects as a nested set of unordered lists
-  # The given collection may be a subset of the whole project tree
-  # (eg. some intermediate nodes are private and can not be seen)
-  def render_project_nested_lists(projects)
-    s = ''
-    if projects.any?
-      ancestors = []
-      original_project = @project
-      projects.sort_by(&:lft).each do |project|
-        # set the project environment to please macros.
-        @project = project
-        if (ancestors.empty? || project.is_descendant_of?(ancestors.last))
-          s << "<ul class='projects #{ ancestors.empty? ? 'root' : nil}'>\n"
-        else
-          ancestors.pop
-          s << "</li>"
-          while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
-            ancestors.pop
-            s << "</ul></li>\n"
-          end
-        end
-        classes = (ancestors.empty? ? 'root' : 'child')
-        s << "<li class='#{classes}'><div class='#{classes}'>"
-        s << h(block_given? ? yield(project) : project.name)
-        s << "</div>\n"
-        ancestors << project
-      end
-      s << ("</li></ul>\n" * ancestors.size)
-      @project = original_project
-    end
-    s.html_safe
-  end
-
-  def render_page_hierarchy(pages, node=nil, options={})
-    content = ''
-    if pages[node]
-      content << "<ul class=\"pages-hierarchy\">\n"
-      pages[node].each do |page|
-        content << "<li>"
-        content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title, :version => nil},
-                           :title => (options[:timestamp] && page.updated_on ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))
-        content << "\n" + render_page_hierarchy(pages, page.id, options) if pages[page.id]
-        content << "</li>\n"
-      end
-      content << "</ul>\n"
-    end
-    content.html_safe
-  end
-
-  # Renders flash messages
-  def render_flash_messages
-    s = ''
-    flash.each do |k,v|
-      s << content_tag('div', v.html_safe, :class => "flash #{k}", :id => "flash_#{k}")
-    end
-    s.html_safe
-  end
-
-  # Renders tabs and their content
-  def render_tabs(tabs)
-    if tabs.any?
-      render :partial => 'common/tabs', :locals => {:tabs => tabs}
-    else
-      content_tag 'p', l(:label_no_data), :class => "nodata"
-    end
-  end
-
-  # Renders the project quick-jump box
-  def render_project_jump_box
-    return unless User.current.logged?
-    projects = User.current.memberships.collect(&:project).compact.select(&:active?).uniq
-    if projects.any?
-      options =
-        ("<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
-         '<option value="" disabled="disabled">---</option>').html_safe
-
-      options << project_tree_options_for_select(projects, :selected => @project) do |p|
-        { :value => project_path(:id => p, :jump => current_menu_item) }
-      end
-
-      select_tag('project_quick_jump_box', options, :onchange => 'if (this.value != \'\') { window.location = this.value; }')
-    end
-  end
-
-  def project_tree_options_for_select(projects, options = {})
-    s = ''
-    project_tree(projects) do |project, level|
-      name_prefix = (level > 0 ? '&nbsp;' * 2 * level + '&#187; ' : '').html_safe
-      tag_options = {:value => project.id}
-      if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project))
-        tag_options[:selected] = 'selected'
-      else
-        tag_options[:selected] = nil
-      end
-      tag_options.merge!(yield(project)) if block_given?
-      s << content_tag('option', name_prefix + h(project), tag_options)
-    end
-    s.html_safe
-  end
-
-  # Yields the given block for each project with its level in the tree
-  #
-  # Wrapper for Project#project_tree
-  def project_tree(projects, &block)
-    Project.project_tree(projects, &block)
-  end
-
-  def principals_check_box_tags(name, principals)
-    s = ''
-    principals.each do |principal|
-      s << "<label>#{ check_box_tag name, principal.id, false, :id => nil } #{h principal}</label>\n"
-    end
-    s.html_safe
-  end
-
-  # Returns a string for users/groups option tags
-  def principals_options_for_select(collection, selected=nil)
-    s = ''
-    if collection.include?(User.current)
-      s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id)
-    end
-    groups = ''
-    collection.sort.each do |element|
-      selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) || element.id.to_s == selected
-      (element.is_a?(Group) ? groups : s) << %(<option value="#{element.id}"#{selected_attribute}>#{h element.name}</option>)
-    end
-    unless groups.empty?
-      s << %(<optgroup label="#{h(l(:label_group_plural))}">#{groups}</optgroup>)
-    end
-    s.html_safe
-  end
-
-  # Options for the new membership projects combo-box
-  def options_for_membership_project_select(principal, projects)
-    options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---")
-    options << project_tree_options_for_select(projects) do |p|
-      {:disabled => principal.projects.to_a.include?(p)}
-    end
-    options
-  end
-
-  def option_tag(name, text, value, selected=nil, options={})
-    content_tag 'option', value, options.merge(:value => value, :selected => (value == selected))
-  end
-
-  # Truncates and returns the string as a single line
-  def truncate_single_line(string, *args)
-    truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ')
-  end
-
-  # Truncates at line break after 250 characters or options[:length]
-  def truncate_lines(string, options={})
-    length = options[:length] || 250
-    if string.to_s =~ /\A(.{#{length}}.*?)$/m
-      "#{$1}..."
-    else
-      string
-    end
-  end
-
-  def anchor(text)
-    text.to_s.gsub(' ', '_')
-  end
-
-  def html_hours(text)
-    text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>').html_safe
-  end
-
-  def authoring(created, author, options={})
-    l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)).html_safe
-  end
-
-  def time_tag(time)
-    text = distance_of_time_in_words(Time.now, time)
-    if @project
-      link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => User.current.time_to_date(time)}, :title => format_time(time))
-    else
-      content_tag('abbr', text, :title => format_time(time))
-    end
-  end
-
-  def syntax_highlight_lines(name, content)
-    lines = []
-    syntax_highlight(name, content).each_line { |line| lines << line }
-    lines
-  end
-
-  def syntax_highlight(name, content)
-    Redmine::SyntaxHighlighting.highlight_by_filename(content, name)
-  end
-
-  def to_path_param(path)
-    str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/")
-    str.blank? ? nil : str
-  end
-
-  def reorder_links(name, url, method = :post)
-    link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)),
-            url.merge({"#{name}[move_to]" => 'highest'}),
-            :method => method, :title => l(:label_sort_highest)) +
-    link_to(image_tag('1uparrow.png',   :alt => l(:label_sort_higher)),
-            url.merge({"#{name}[move_to]" => 'higher'}),
-           :method => method, :title => l(:label_sort_higher)) +
-    link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)),
-            url.merge({"#{name}[move_to]" => 'lower'}),
-            :method => method, :title => l(:label_sort_lower)) +
-    link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)),
-            url.merge({"#{name}[move_to]" => 'lowest'}),
-           :method => method, :title => l(:label_sort_lowest))
-  end
-
-  def breadcrumb(*args)
-    elements = args.flatten
-    elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'breadcrumb') : nil
-  end
-
-  def other_formats_links(&block)
-    concat('<p class="other-formats">'.html_safe + l(:label_export_to))
-    yield Redmine::Views::OtherFormatsBuilder.new(self)
-    concat('</p>'.html_safe)
-  end
-
-  def page_header_title
-    if @project.nil? || @project.new_record?
-      h(Setting.app_title)
-    else
-      b = []
-      ancestors = (@project.root? ? [] : @project.ancestors.visible.all)
-      if ancestors.any?
-        root = ancestors.shift
-        b << link_to_project(root, {:jump => current_menu_item}, :class => 'root')
-        if ancestors.size > 2
-          b << "\xe2\x80\xa6"
-          ancestors = ancestors[-2, 2]
-        end
-        b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') }
-      end
-      b << h(@project)
-      b.join(" \xc2\xbb ").html_safe
-    end
-  end
-
-  # Returns a h2 tag and sets the html title with the given arguments
-  def title(*args)
-    strings = args.map do |arg|
-      if arg.is_a?(Array) && arg.size >= 2
-        link_to(*arg)
-      else
-        h(arg.to_s)
-      end
-    end
-    html_title args.reverse.map {|s| (s.is_a?(Array) ? s.first : s).to_s}
-    content_tag('h2', strings.join(' &#187; ').html_safe)
-  end
-
-  # Sets the html title
-  # Returns the html title when called without arguments
-  # Current project name and app_title and automatically appended
-  # Exemples:
-  #   html_title 'Foo', 'Bar'
-  #   html_title # => 'Foo - Bar - My Project - Redmine'
-  def html_title(*args)
-    if args.empty?
-      title = @html_title || []
-      title << @project.name if @project
-      title << Setting.app_title unless Setting.app_title == title.last
-      title.reject(&:blank?).join(' - ')
-    else
-      @html_title ||= []
-      @html_title += args
-    end
-  end
-
-  # Returns the theme, controller name, and action as css classes for the
-  # HTML body.
-  def body_css_classes
-    css = []
-    if theme = Redmine::Themes.theme(Setting.ui_theme)
-      css << 'theme-' + theme.name
-    end
-
-    css << 'project-' + @project.identifier if @project && @project.identifier.present?
-    css << 'controller-' + controller_name
-    css << 'action-' + action_name
-    css.join(' ')
-  end
-
-  def accesskey(s)
-    @used_accesskeys ||= []
-    key = Redmine::AccessKeys.key_for(s)
-    return nil if @used_accesskeys.include?(key)
-    @used_accesskeys << key
-    key
-  end
-
-  # Formats text according to system settings.
-  # 2 ways to call this method:
-  # * with a String: textilizable(text, options)
-  # * with an object and one of its attribute: textilizable(issue, :description, options)
-  def textilizable(*args)
-    options = args.last.is_a?(Hash) ? args.pop : {}
-    case args.size
-    when 1
-      obj = options[:object]
-      text = args.shift
-    when 2
-      obj = args.shift
-      attr = args.shift
-      text = obj.send(attr).to_s
-    else
-      raise ArgumentError, 'invalid arguments to textilizable'
-    end
-    return '' if text.blank?
-    project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
-    only_path = options.delete(:only_path) == false ? false : true
-
-    text = text.dup
-    macros = catch_macros(text)
-    text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr)
-
-    @parsed_headings = []
-    @heading_anchors = {}
-    @current_section = 0 if options[:edit_section_links]
-
-    parse_sections(text, project, obj, attr, only_path, options)
-    text = parse_non_pre_blocks(text, obj, macros) do |text|
-      [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name|
-        send method_name, text, project, obj, attr, only_path, options
-      end
-    end
-    parse_headings(text, project, obj, attr, only_path, options)
-
-    if @parsed_headings.any?
-      replace_toc(text, @parsed_headings)
-    end
-
-    text.html_safe
-  end
-
-  def parse_non_pre_blocks(text, obj, macros)
-    s = StringScanner.new(text)
-    tags = []
-    parsed = ''
-    while !s.eos?
-      s.scan(/(.*?)(<(\/)?(pre|code)(.*?)>|\z)/im)
-      text, full_tag, closing, tag = s[1], s[2], s[3], s[4]
-      if tags.empty?
-        yield text
-        inject_macros(text, obj, macros) if macros.any?
-      else
-        inject_macros(text, obj, macros, false) if macros.any?
-      end
-      parsed << text
-      if tag
-        if closing
-          if tags.last == tag.downcase
-            tags.pop
-          end
-        else
-          tags << tag.downcase
-        end
-        parsed << full_tag
-      end
-    end
-    # Close any non closing tags
-    while tag = tags.pop
-      parsed << "</#{tag}>"
-    end
-    parsed
-  end
-
-  def parse_inline_attachments(text, project, obj, attr, only_path, options)
-    # when using an image link, try to use an attachment, if possible
-    attachments = options[:attachments] || []
-    attachments += obj.attachments if obj.respond_to?(:attachments)
-    if attachments.present?
-      text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m|
-        filename, ext, alt, alttext = $1.downcase, $2, $3, $4
-        # search for the picture in attachments
-        if found = Attachment.latest_attach(attachments, filename)
-          image_url = download_named_attachment_path(found, found.filename, :only_path => only_path)
-          desc = found.description.to_s.gsub('"', '')
-          if !desc.blank? && alttext.blank?
-            alt = " title=\"#{desc}\" alt=\"#{desc}\""
-          end
-          "src=\"#{image_url}\"#{alt}"
-        else
-          m
-        end
-      end
-    end
-  end
-
-  # Wiki links
-  #
-  # Examples:
-  #   [[mypage]]
-  #   [[mypage|mytext]]
-  # wiki links can refer other project wikis, using project name or identifier:
-  #   [[project:]] -> wiki starting page
-  #   [[project:|mytext]]
-  #   [[project:mypage]]
-  #   [[project:mypage|mytext]]
-  def parse_wiki_links(text, project, obj, attr, only_path, options)
-    text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m|
-      link_project = project
-      esc, all, page, title = $1, $2, $3, $5
-      if esc.nil?
-        if page =~ /^([^\:]+)\:(.*)$/
-          identifier, page = $1, $2
-          link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier)
-          title ||= identifier if page.blank?
-        end
-
-        if link_project && link_project.wiki
-          # extract anchor
-          anchor = nil
-          if page =~ /^(.+?)\#(.+)$/
-            page, anchor = $1, $2
-          end
-          anchor = sanitize_anchor_name(anchor) if anchor.present?
-          # check if page exists
-          wiki_page = link_project.wiki.find_page(page)
-          url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page
-            "##{anchor}"
-          else
-            case options[:wiki_links]
-            when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '')
-            when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export
-            else
-              wiki_page_id = page.present? ? Wiki.titleize(page) : nil
-              parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil
-              url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project,
-               :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent)
-            end
-          end
-          link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
-        else
-          # project or wiki doesn't exist
-          all
-        end
-      else
-        all
-      end
-    end
-  end
-
-  # Redmine links
-  #
-  # Examples:
-  #   Issues:
-  #     #52 -> Link to issue #52
-  #   Changesets:
-  #     r52 -> Link to revision 52
-  #     commit:a85130f -> Link to scmid starting with a85130f
-  #   Documents:
-  #     document#17 -> Link to document with id 17
-  #     document:Greetings -> Link to the document with title "Greetings"
-  #     document:"Some document" -> Link to the document with title "Some document"
-  #   Versions:
-  #     version#3 -> Link to version with id 3
-  #     version:1.0.0 -> Link to version named "1.0.0"
-  #     version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
-  #   Attachments:
-  #     attachment:file.zip -> Link to the attachment of the current object named file.zip
-  #   Source files:
-  #     source:some/file -> Link to the file located at /some/file in the project's repository
-  #     source:some/file@52 -> Link to the file's revision 52
-  #     source:some/file#L120 -> Link to line 120 of the file
-  #     source:some/file@52#L120 -> Link to line 120 of the file's revision 52
-  #     export:some/file -> Force the download of the file
-  #   Forum messages:
-  #     message#1218 -> Link to message with id 1218
-  #  Projects:
-  #     project:someproject -> Link to project named "someproject"
-  #     project#3 -> Link to project with id 3
-  #
-  #   Links can refer other objects from other projects, using project identifier:
-  #     identifier:r52
-  #     identifier:document:"Some document"
-  #     identifier:version:1.0.0
-  #     identifier:source:some/file
-  def parse_redmine_links(text, default_project, obj, attr, only_path, options)
-    text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m|
-      leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $1, $2, $3, $4, $5, $10, $11, $8 || $12 || $18, $14 || $19, $15, $17
-      link = nil
-      project = default_project
-      if project_identifier
-        project = Project.visible.find_by_identifier(project_identifier)
-      end
-      if esc.nil?
-        if prefix.nil? && sep == 'r'
-          if project
-            repository = nil
-            if repo_identifier
-              repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
-            else
-              repository = project.repository
-            end
-            # project.changesets.visible raises an SQL error because of a double join on repositories
-            if repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(repository.id, identifier))
-              link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.revision},
-                                        :class => 'changeset',
-                                        :title => truncate_single_line(changeset.comments, :length => 100))
-            end
-          end
-        elsif sep == '#'
-          oid = identifier.to_i
-          case prefix
-          when nil
-            if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status)
-              anchor = comment_id ? "note-#{comment_id}" : nil
-              link = link_to(h("##{oid}#{comment_suffix}"), {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor},
-                                        :class => issue.css_classes,
-                                        :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
-            end
-          when 'document'
-            if document = Document.visible.find_by_id(oid)
-              link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
-                                                :class => 'document'
-            end
-          when 'version'
-            if version = Version.visible.find_by_id(oid)
-              link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
-                                              :class => 'version'
-            end
-          when 'message'
-            if message = Message.visible.find_by_id(oid, :include => :parent)
-              link = link_to_message(message, {:only_path => only_path}, :class => 'message')
-            end
-          when 'forum'
-            if board = Board.visible.find_by_id(oid)
-              link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
-                                             :class => 'board'
-            end
-          when 'news'
-            if news = News.visible.find_by_id(oid)
-              link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
-                                            :class => 'news'
-            end
-          when 'project'
-            if p = Project.visible.find_by_id(oid)
-              link = link_to_project(p, {:only_path => only_path}, :class => 'project')
-            end
-          end
-        elsif sep == ':'
-          # removes the double quotes if any
-          name = identifier.gsub(%r{^"(.*)"$}, "\\1")
-          case prefix
-          when 'document'
-            if project && document = project.documents.visible.find_by_title(name)
-              link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
-                                                :class => 'document'
-            end
-          when 'version'
-            if project && version = project.versions.visible.find_by_name(name)
-              link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
-                                              :class => 'version'
-            end
-          when 'forum'
-            if project && board = project.boards.visible.find_by_name(name)
-              link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
-                                             :class => 'board'
-            end
-          when 'news'
-            if project && news = project.news.visible.find_by_title(name)
-              link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
-                                            :class => 'news'
-            end
-          when 'commit', 'source', 'export'
-            if project
-              repository = nil
-              if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
-                repo_prefix, repo_identifier, name = $1, $2, $3
-                repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
-              else
-                repository = project.repository
-              end
-              if prefix == 'commit'
-                if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
-                  link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
-                                               :class => 'changeset',
-                                               :title => truncate_single_line(changeset.comments, :length => 100)
-                end
-              else
-                if repository && User.current.allowed_to?(:browse_repository, project)
-                  name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
-                  path, rev, anchor = $1, $3, $5
-                  link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
-                                                          :path => to_path_param(path),
-                                                          :rev => rev,
-                                                          :anchor => anchor},
-                                                         :class => (prefix == 'export' ? 'source download' : 'source')
-                end
-              end
-              repo_prefix = nil
-            end
-          when 'attachment'
-            attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
-            if attachments && attachment = Attachment.latest_attach(attachments, name)
-              link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
-            end
-          when 'project'
-            if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
-              link = link_to_project(p, {:only_path => only_path}, :class => 'project')
-            end
-          end
-        end
-      end
-      (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}"))
-    end
-  end
-
-  HEADING_RE = /(<h(\d)( [^>]+)?>(.+?)<\/h(\d)>)/i unless const_defined?(:HEADING_RE)
-
-  def parse_sections(text, project, obj, attr, only_path, options)
-    return unless options[:edit_section_links]
-    text.gsub!(HEADING_RE) do
-      heading = $1
-      @current_section += 1
-      if @current_section > 1
-        content_tag('div',
-          link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)),
-          :class => 'contextual',
-          :title => l(:button_edit_section),
-          :id => "section-#{@current_section}") + heading.html_safe
-      else
-        heading
-      end
-    end
-  end
-
-  # Headings and TOC
-  # Adds ids and links to headings unless options[:headings] is set to false
-  def parse_headings(text, project, obj, attr, only_path, options)
-    return if options[:headings] == false
-
-    text.gsub!(HEADING_RE) do
-      level, attrs, content = $2.to_i, $3, $4
-      item = strip_tags(content).strip
-      anchor = sanitize_anchor_name(item)
-      # used for single-file wiki export
-      anchor = "#{obj.page.title}_#{anchor}" if options[:wiki_links] == :anchor && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version))
-      @heading_anchors[anchor] ||= 0
-      idx = (@heading_anchors[anchor] += 1)
-      if idx > 1
-        anchor = "#{anchor}-#{idx}"
-      end
-      @parsed_headings << [level, anchor, item]
-      "<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a></h#{level}>"
-    end
-  end
-
-  MACROS_RE = /(
-                (!)?                        # escaping
-                (
-                \{\{                        # opening tag
-                ([\w]+)                     # macro name
-                (\(([^\n\r]*?)\))?          # optional arguments
-                ([\n\r].*?[\n\r])?          # optional block of text
-                \}\}                        # closing tag
-                )
-               )/mx unless const_defined?(:MACROS_RE)
-
-  MACRO_SUB_RE = /(
-                  \{\{
-                  macro\((\d+)\)
-                  \}\}
-                  )/x unless const_defined?(:MACRO_SUB_RE)
-
-  # Extracts macros from text
-  def catch_macros(text)
-    macros = {}
-    text.gsub!(MACROS_RE) do
-      all, macro = $1, $4.downcase
-      if macro_exists?(macro) || all =~ MACRO_SUB_RE
-        index = macros.size
-        macros[index] = all
-        "{{macro(#{index})}}"
-      else
-        all
-      end
-    end
-    macros
-  end
-
-  # Executes and replaces macros in text
-  def inject_macros(text, obj, macros, execute=true)
-    text.gsub!(MACRO_SUB_RE) do
-      all, index = $1, $2.to_i
-      orig = macros.delete(index)
-      if execute && orig && orig =~ MACROS_RE
-        esc, all, macro, args, block = $2, $3, $4.downcase, $6.to_s, $7.try(:strip)
-        if esc.nil?
-          h(exec_macro(macro, obj, args, block) || all)
-        else
-          h(all)
-        end
-      elsif orig
-        h(orig)
-      else
-        h(all)
-      end
-    end
-  end
-
-  TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
-
-  # Renders the TOC with given headings
-  def replace_toc(text, headings)
-    text.gsub!(TOC_RE) do
-      # Keep only the 4 first levels
-      headings = headings.select{|level, anchor, item| level <= 4}
-      if headings.empty?
-        ''
-      else
-        div_class = 'toc'
-        div_class << ' right' if $1 == '>'
-        div_class << ' left' if $1 == '<'
-        out = "<ul class=\"#{div_class}\"><li>"
-        root = headings.map(&:first).min
-        current = root
-        started = false
-        headings.each do |level, anchor, item|
-          if level > current
-            out << '<ul><li>' * (level - current)
-          elsif level < current
-            out << "</li></ul>\n" * (current - level) + "</li><li>"
-          elsif started
-            out << '</li><li>'
-          end
-          out << "<a href=\"##{anchor}\">#{item}</a>"
-          current = level
-          started = true
-        end
-        out << '</li></ul>' * (current - root)
-        out << '</li></ul>'
-      end
-    end
-  end
-
-  # Same as Rails' simple_format helper without using paragraphs
-  def simple_format_without_paragraph(text)
-    text.to_s.
-      gsub(/\r\n?/, "\n").                    # \r\n and \r -> \n
-      gsub(/\n\n+/, "<br /><br />").          # 2+ newline  -> 2 br
-      gsub(/([^\n]\n)(?=[^\n])/, '\1<br />'). # 1 newline   -> br
-      html_safe
-  end
-
-  def lang_options_for_select(blank=true)
-    (blank ? [["(auto)", ""]] : []) + languages_options
-  end
-
-  def label_tag_for(name, option_tags = nil, options = {})
-    label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
-    content_tag("label", label_text)
-  end
-
-  def labelled_form_for(*args, &proc)
-    args << {} unless args.last.is_a?(Hash)
-    options = args.last
-    if args.first.is_a?(Symbol)
-      options.merge!(:as => args.shift)
-    end
-    options.merge!({:builder => Redmine::Views::LabelledFormBuilder})
-    form_for(*args, &proc)
-  end
-
-  def labelled_fields_for(*args, &proc)
-    args << {} unless args.last.is_a?(Hash)
-    options = args.last
-    options.merge!({:builder => Redmine::Views::LabelledFormBuilder})
-    fields_for(*args, &proc)
-  end
-
-  def labelled_remote_form_for(*args, &proc)
-    ActiveSupport::Deprecation.warn "ApplicationHelper#labelled_remote_form_for is deprecated and will be removed in Redmine 2.2."
-    args << {} unless args.last.is_a?(Hash)
-    options = args.last
-    options.merge!({:builder => Redmine::Views::LabelledFormBuilder, :remote => true})
-    form_for(*args, &proc)
-  end
-
-  def error_messages_for(*objects)
-    html = ""
-    objects = objects.map {|o| o.is_a?(String) ? instance_variable_get("@#{o}") : o}.compact
-    errors = objects.map {|o| o.errors.full_messages}.flatten
-    if errors.any?
-      html << "<div id='errorExplanation'><ul>\n"
-      errors.each do |error|
-        html << "<li>#{h error}</li>\n"
-      end
-      html << "</ul></div>\n"
-    end
-    html.html_safe
-  end
-
-  def delete_link(url, options={})
-    options = {
-      :method => :delete,
-      :data => {:confirm => l(:text_are_you_sure)},
-      :class => 'icon icon-del'
-    }.merge(options)
-
-    link_to l(:button_delete), url, options
-  end
-
-  def preview_link(url, form, target='preview', options={})
-    content_tag 'a', l(:label_preview), {
-        :href => "#",
-        :onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|,
-        :accesskey => accesskey(:preview)
-      }.merge(options)
-  end
-
-  def link_to_function(name, function, html_options={})
-    content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(html_options))
-  end
-
-  # Helper to render JSON in views
-  def raw_json(arg)
-    arg.to_json.to_s.gsub('/', '\/').html_safe
-  end
-
-  def back_url
-    url = params[:back_url]
-    if url.nil? && referer = request.env['HTTP_REFERER']
-      url = CGI.unescape(referer.to_s)
-    end
-    url
-  end
-
-  def back_url_hidden_field_tag
-    url = back_url
-    hidden_field_tag('back_url', url, :id => nil) unless url.blank?
-  end
-
-  def check_all_links(form_name)
-    link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
-    " | ".html_safe +
-    link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
-  end
-
-  def progress_bar(pcts, options={})
-    pcts = [pcts, pcts] unless pcts.is_a?(Array)
-    pcts = pcts.collect(&:round)
-    pcts[1] = pcts[1] - pcts[0]
-    pcts << (100 - pcts[1] - pcts[0])
-    width = options[:width] || '100px;'
-    legend = options[:legend] || ''
-    content_tag('table',
-      content_tag('tr',
-        (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) +
-        (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : ''.html_safe) +
-        (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe)
-      ), :class => "progress progress-#{pcts[0]}", :style => "width: #{width};").html_safe +
-      content_tag('p', legend, :class => 'percent').html_safe
-  end
-
-  def checked_image(checked=true)
-    if checked
-      image_tag 'toggle_check.png'
-    end
-  end
-
-  def context_menu(url)
-    unless @context_menu_included
-      content_for :header_tags do
-        javascript_include_tag('context_menu') +
-          stylesheet_link_tag('context_menu')
-      end
-      if l(:direction) == 'rtl'
-        content_for :header_tags do
-          stylesheet_link_tag('context_menu_rtl')
-        end
-      end
-      @context_menu_included = true
-    end
-    javascript_tag "contextMenuInit('#{ url_for(url) }')"
-  end
-
-  def calendar_for(field_id)
-    include_calendar_headers_tags
-    javascript_tag("$(function() { $('##{field_id}').datepicker(datepickerOptions); });")
-  end
-
-  def include_calendar_headers_tags
-    unless @calendar_headers_tags_included
-      tags = javascript_include_tag("datepicker")
-      @calendar_headers_tags_included = true
-      content_for :header_tags do
-        start_of_week = Setting.start_of_week
-        start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank?
-        # Redmine uses 1..7 (monday..sunday) in settings and locales
-        # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0
-        start_of_week = start_of_week.to_i % 7
-        tags << javascript_tag(
-                   "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " +
-                     "showOn: 'button', buttonImageOnly: true, buttonImage: '" +
-                     path_to_image('/images/calendar.png') +
-                     "', showButtonPanel: true, showWeek: true, showOtherMonths: true, " +
-                     "selectOtherMonths: true, changeMonth: true, changeYear: true, " +
-                     "beforeShow: beforeShowDatePicker};")
-        jquery_locale = l('jquery.locale', :default => current_language.to_s)
-        unless jquery_locale == 'en'
-          tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js")
-        end
-        tags
-      end
-    end
-  end
-
-  # Overrides Rails' stylesheet_link_tag with themes and plugins support.
-  # Examples:
-  #   stylesheet_link_tag('styles') # => picks styles.css from the current theme or defaults
-  #   stylesheet_link_tag('styles', :plugin => 'foo) # => picks styles.css from plugin's assets
-  #
-  def stylesheet_link_tag(*sources)
-    options = sources.last.is_a?(Hash) ? sources.pop : {}
-    plugin = options.delete(:plugin)
-    sources = sources.map do |source|
-      if plugin
-        "/plugin_assets/#{plugin}/stylesheets/#{source}"
-      elsif current_theme && current_theme.stylesheets.include?(source)
-        current_theme.stylesheet_path(source)
-      else
-        source
-      end
-    end
-    super sources, options
-  end
-
-  # Overrides Rails' image_tag with themes and plugins support.
-  # Examples:
-  #   image_tag('image.png') # => picks image.png from the current theme or defaults
-  #   image_tag('image.png', :plugin => 'foo) # => picks image.png from plugin's assets
-  #
-  def image_tag(source, options={})
-    if plugin = options.delete(:plugin)
-      source = "/plugin_assets/#{plugin}/images/#{source}"
-    elsif current_theme && current_theme.images.include?(source)
-      source = current_theme.image_path(source)
-    end
-    super source, options
-  end
-
-  # Overrides Rails' javascript_include_tag with plugins support
-  # Examples:
-  #   javascript_include_tag('scripts') # => picks scripts.js from defaults
-  #   javascript_include_tag('scripts', :plugin => 'foo) # => picks scripts.js from plugin's assets
-  #
-  def javascript_include_tag(*sources)
-    options = sources.last.is_a?(Hash) ? sources.pop : {}
-    if plugin = options.delete(:plugin)
-      sources = sources.map do |source|
-        if plugin
-          "/plugin_assets/#{plugin}/javascripts/#{source}"
-        else
-          source
-        end
-      end
-    end
-    super sources, options
-  end
-
-  # TODO: remove this in 2.5.0
-  def has_content?(name)
-    content_for?(name)
-  end
-
-  def sidebar_content?
-    content_for?(:sidebar) || view_layouts_base_sidebar_hook_response.present?
-  end
-
-  def view_layouts_base_sidebar_hook_response
-    @view_layouts_base_sidebar_hook_response ||= call_hook(:view_layouts_base_sidebar)
-  end
-
-  def email_delivery_enabled?
-    !!ActionMailer::Base.perform_deliveries
-  end
-
-  # Returns the avatar image tag for the given +user+ if avatars are enabled
-  # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>')
-  def avatar(user, options = { })
-    if Setting.gravatar_enabled?
-      options.merge!({:ssl => (request && request.ssl?), :default => Setting.gravatar_default})
-      email = nil
-      if user.respond_to?(:mail)
-        email = user.mail
-      elsif user.to_s =~ %r{<(.+?)>}
-        email = $1
-      end
-      return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil
-    else
-      ''
-    end
-  end
-
-  def sanitize_anchor_name(anchor)
-    if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java'
-      anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
-    else
-      # TODO: remove when ruby1.8 is no longer supported
-      anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
-    end
-  end
-
-  # Returns the javascript tags that are included in the html layout head
-  def javascript_heads
-    tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'application')
-    unless User.current.pref.warn_on_leaving_unsaved == '0'
-      tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });")
-    end
-    tags
-  end
-
-  def favicon
-    "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />".html_safe
-  end
-
-  def robot_exclusion_tag
-    '<meta name="robots" content="noindex,follow,noarchive" />'.html_safe
-  end
-
-  # Returns true if arg is expected in the API response
-  def include_in_api_response?(arg)
-    unless @included_in_api_response
-      param = params[:include]
-      @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',')
-      @included_in_api_response.collect!(&:strip)
-    end
-    @included_in_api_response.include?(arg.to_s)
-  end
-
-  # Returns options or nil if nometa param or X-Redmine-Nometa header
-  # was set in the request
-  def api_meta(options)
-    if params[:nometa].present? || request.headers['X-Redmine-Nometa']
-      # compatibility mode for activeresource clients that raise
-      # an error when unserializing an array with attributes
-      nil
-    else
-      options
-    end
-  end
-
-  private
-
-  def wiki_helper
-    helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
-    extend helper
-    return self
-  end
-
-  def link_to_content_update(text, url_params = {}, html_options = {})
-    link_to(text, url_params, html_options)
-  end
-end
--- a/.svn/pristine/f6/f6ef1fd188a246198832677eccb65f1bec39a729.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingAuthSourcesTest < ActionController::IntegrationTest
-  def test_auth_sources
-    assert_routing(
-        { :method => 'get', :path => "/auth_sources" },
-        { :controller => 'auth_sources', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/auth_sources/new" },
-        { :controller => 'auth_sources', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/auth_sources" },
-        { :controller => 'auth_sources', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/auth_sources/1234/edit" },
-        { :controller => 'auth_sources', :action => 'edit',
-          :id => '1234' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/auth_sources/1234" },
-        { :controller => 'auth_sources', :action => 'update',
-          :id => '1234' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/auth_sources/1234" },
-        { :controller => 'auth_sources', :action => 'destroy',
-          :id => '1234' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/auth_sources/1234/test_connection" },
-        { :controller => 'auth_sources', :action => 'test_connection',
-          :id => '1234' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/auth_sources/autocomplete_for_new_user" },
-        { :controller => 'auth_sources', :action => 'autocomplete_for_new_user' }
-      )
-  end
-end
--- a/.svn/pristine/f7/f75cc0973adb64fe86bec853f1ce941fdd75f24d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class SearchController < ApplicationController
-  before_filter :find_optional_project
-
-  def index
-    @question = params[:q] || ""
-    @question.strip!
-    @all_words = params[:all_words] ? params[:all_words].present? : true
-    @titles_only = params[:titles_only] ? params[:titles_only].present? : false
-
-    projects_to_search =
-      case params[:scope]
-      when 'all'
-        nil
-      when 'my_projects'
-        User.current.memberships.collect(&:project)
-      when 'subprojects'
-        @project ? (@project.self_and_descendants.active.all) : nil
-      else
-        @project
-      end
-
-    offset = nil
-    begin; offset = params[:offset].to_time if params[:offset]; rescue; end
-
-    # quick jump to an issue
-    if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
-      redirect_to issue_path(issue)
-      return
-    end
-
-    @object_types = Redmine::Search.available_search_types.dup
-    if projects_to_search.is_a? Project
-      # don't search projects
-      @object_types.delete('projects')
-      # only show what the user is allowed to view
-      @object_types = @object_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, projects_to_search)}
-    end
-
-    @scope = @object_types.select {|t| params[t]}
-    @scope = @object_types if @scope.empty?
-
-    # extract tokens from the question
-    # eg. hello "bye bye" => ["hello", "bye bye"]
-    @tokens = @question.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}).collect {|m| m.first.gsub(%r{(^\s*"\s*|\s*"\s*$)}, '')}
-    # tokens must be at least 2 characters long
-    @tokens = @tokens.uniq.select {|w| w.length > 1 }
-
-    if !@tokens.empty?
-      # no more than 5 tokens to search for
-      @tokens.slice! 5..-1 if @tokens.size > 5
-
-      @results = []
-      @results_by_type = Hash.new {|h,k| h[k] = 0}
-
-      limit = 10
-      @scope.each do |s|
-        r, c = s.singularize.camelcase.constantize.search(@tokens, projects_to_search,
-          :all_words => @all_words,
-          :titles_only => @titles_only,
-          :limit => (limit+1),
-          :offset => offset,
-          :before => params[:previous].nil?)
-        @results += r
-        @results_by_type[s] += c
-      end
-      @results = @results.sort {|a,b| b.event_datetime <=> a.event_datetime}
-      if params[:previous].nil?
-        @pagination_previous_date = @results[0].event_datetime if offset && @results[0]
-        if @results.size > limit
-          @pagination_next_date = @results[limit-1].event_datetime
-          @results = @results[0, limit]
-        end
-      else
-        @pagination_next_date = @results[-1].event_datetime if offset && @results[-1]
-        if @results.size > limit
-          @pagination_previous_date = @results[-(limit)].event_datetime
-          @results = @results[-(limit), limit]
-        end
-      end
-    else
-      @question = ""
-    end
-    render :layout => false if request.xhr?
-  end
-
-private
-  def find_optional_project
-    return true unless params[:id]
-    @project = Project.find(params[:id])
-    check_project_privacy
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-end
--- a/.svn/pristine/f7/f78ddc144c31f10580290509649e50dda2f4e570.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class JournalObserverTest < ActiveSupport::TestCase
-  fixtures :issues, :issue_statuses, :journals, :journal_details, :projects,
-           :projects_trackers, :trackers, :enabled_modules, :enumerations,
-           :users, :roles
-
-  def setup
-    ActionMailer::Base.deliveries.clear
-    @journal = Journal.find 1
-  end
-
-  # context: issue_updated notified_events
-  def test_create_should_send_email_notification_with_issue_updated
-    issue = Issue.first
-    user = User.first
-    journal = issue.init_journal(user, issue)
-
-    with_settings :notified_events => %w(issue_updated) do
-      assert journal.save
-    end
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_create_should_not_send_email_notification_with_notify_set_to_false
-    issue = Issue.first
-    user = User.first
-    journal = issue.init_journal(user, issue)
-    journal.notify = false
-
-    with_settings :notified_events => %w(issue_updated) do
-      assert journal.save
-    end
-    assert_equal 0, ActionMailer::Base.deliveries.size
-  end
-
-  def test_create_should_not_send_email_notification_without_issue_updated
-    issue = Issue.first
-    user = User.first
-    journal = issue.init_journal(user, issue)
-
-    with_settings :notified_events => [] do
-      assert journal.save
-    end
-    assert_equal 0, ActionMailer::Base.deliveries.size
-  end
-
-  # context: issue_note_added notified_events
-  def test_create_should_send_email_notification_with_issue_note_added
-    issue = Issue.first
-    user = User.first
-    journal = issue.init_journal(user, issue)
-    journal.notes = 'This update has a note'
-
-    with_settings :notified_events => %w(issue_note_added) do
-      assert journal.save
-    end
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_create_should_not_send_email_notification_without_issue_note_added
-    issue = Issue.first
-    user = User.first
-    journal = issue.init_journal(user, issue)
-    journal.notes = 'This update has a note'
-
-    with_settings :notified_events => [] do
-      assert journal.save
-    end
-    assert_equal 0, ActionMailer::Base.deliveries.size
-  end
-
-  # context: issue_status_updated notified_events
-  def test_create_should_send_email_notification_with_issue_status_updated
-    issue = Issue.first
-    user = User.first
-    issue.init_journal(user, issue)
-    issue.status = IssueStatus.last
-
-    with_settings :notified_events => %w(issue_status_updated) do
-      assert issue.save
-    end
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_create_should_not_send_email_notification_without_issue_status_updated
-    issue = Issue.first
-    user = User.first
-    issue.init_journal(user, issue)
-    issue.status = IssueStatus.last
-
-    with_settings :notified_events => [] do
-      assert issue.save
-    end
-    assert_equal 0, ActionMailer::Base.deliveries.size
-  end
-
-  # context: issue_priority_updated notified_events
-  def test_create_should_send_email_notification_with_issue_priority_updated
-    issue = Issue.first
-    user = User.first
-    issue.init_journal(user, issue)
-    issue.priority = IssuePriority.last
-
-    with_settings :notified_events => %w(issue_priority_updated) do
-      assert issue.save
-    end
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_create_should_not_send_email_notification_without_issue_priority_updated
-    issue = Issue.first
-    user = User.first
-    issue.init_journal(user, issue)
-    issue.priority = IssuePriority.last
-
-    with_settings :notified_events => [] do
-      assert issue.save
-    end
-    assert_equal 0, ActionMailer::Base.deliveries.size
-  end
-end
--- a/.svn/pristine/f8/f846004b3958b5cdd097fb7a9fa2ca8d32fef589.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,297 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class TimelogController < ApplicationController
-  menu_item :issues
-
-  before_filter :find_project_for_new_time_entry, :only => [:create]
-  before_filter :find_time_entry, :only => [:show, :edit, :update]
-  before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
-  before_filter :authorize, :except => [:new, :index, :report]
-
-  before_filter :find_optional_project, :only => [:index, :report]
-  before_filter :find_optional_project_for_new_time_entry, :only => [:new]
-  before_filter :authorize_global, :only => [:new, :index, :report]
-
-  accept_rss_auth :index
-  accept_api_auth :index, :show, :create, :update, :destroy
-
-  rescue_from Query::StatementInvalid, :with => :query_statement_invalid
-
-  helper :sort
-  include SortHelper
-  helper :issues
-  include TimelogHelper
-  helper :custom_fields
-  include CustomFieldsHelper
-  helper :queries
-  include QueriesHelper
-
-  def index
-    @query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_')
-
-    sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria)
-    sort_update(@query.sortable_columns)
-    scope = time_entry_scope(:order => sort_clause).
-      includes(:project, :user, :issue).
-      preload(:issue => [:project, :tracker, :status, :assigned_to, :priority])
-
-    respond_to do |format|
-      format.html {
-        @entry_count = scope.count
-        @entry_pages = Paginator.new @entry_count, per_page_option, params['page']
-        @entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).all
-        @total_hours = scope.sum(:hours).to_f
-
-        render :layout => !request.xhr?
-      }
-      format.api  {
-        @entry_count = scope.count
-        @offset, @limit = api_offset_and_limit
-        @entries = scope.offset(@offset).limit(@limit).preload(:custom_values => :custom_field).all
-      }
-      format.atom {
-        entries = scope.limit(Setting.feeds_limit.to_i).reorder("#{TimeEntry.table_name}.created_on DESC").all
-        render_feed(entries, :title => l(:label_spent_time))
-      }
-      format.csv {
-        # Export all entries
-        @entries = scope.all
-        send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'timelog.csv')
-      }
-    end
-  end
-
-  def report
-    @query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_')
-    scope = time_entry_scope
-
-    @report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], scope)
-
-    respond_to do |format|
-      format.html { render :layout => !request.xhr? }
-      format.csv  { send_data(report_to_csv(@report), :type => 'text/csv; header=present', :filename => 'timelog.csv') }
-    end
-  end
-
-  def show
-    respond_to do |format|
-      # TODO: Implement html response
-      format.html { render :nothing => true, :status => 406 }
-      format.api
-    end
-  end
-
-  def new
-    @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
-    @time_entry.safe_attributes = params[:time_entry]
-  end
-
-  def create
-    @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
-    @time_entry.safe_attributes = params[:time_entry]
-
-    call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
-
-    if @time_entry.save
-      respond_to do |format|
-        format.html {
-          flash[:notice] = l(:notice_successful_create)
-          if params[:continue]
-            if params[:project_id]
-              options = {
-                :time_entry => {:issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
-                :back_url => params[:back_url]
-              }
-              if @time_entry.issue
-                redirect_to new_project_issue_time_entry_path(@time_entry.project, @time_entry.issue, options)
-              else
-                redirect_to new_project_time_entry_path(@time_entry.project, options)
-              end
-            else
-              options = {
-                :time_entry => {:project_id => @time_entry.project_id, :issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
-                :back_url => params[:back_url]
-              }
-              redirect_to new_time_entry_path(options)
-            end
-          else
-            redirect_back_or_default project_time_entries_path(@time_entry.project)
-          end
-        }
-        format.api  { render :action => 'show', :status => :created, :location => time_entry_url(@time_entry) }
-      end
-    else
-      respond_to do |format|
-        format.html { render :action => 'new' }
-        format.api  { render_validation_errors(@time_entry) }
-      end
-    end
-  end
-
-  def edit
-    @time_entry.safe_attributes = params[:time_entry]
-  end
-
-  def update
-    @time_entry.safe_attributes = params[:time_entry]
-
-    call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
-
-    if @time_entry.save
-      respond_to do |format|
-        format.html {
-          flash[:notice] = l(:notice_successful_update)
-          redirect_back_or_default project_time_entries_path(@time_entry.project)
-        }
-        format.api  { render_api_ok }
-      end
-    else
-      respond_to do |format|
-        format.html { render :action => 'edit' }
-        format.api  { render_validation_errors(@time_entry) }
-      end
-    end
-  end
-
-  def bulk_edit
-    @available_activities = TimeEntryActivity.shared.active
-    @custom_fields = TimeEntry.first.available_custom_fields
-  end
-
-  def bulk_update
-    attributes = parse_params_for_bulk_time_entry_attributes(params)
-
-    unsaved_time_entry_ids = []
-    @time_entries.each do |time_entry|
-      time_entry.reload
-      time_entry.safe_attributes = attributes
-      call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry })
-      unless time_entry.save
-        logger.info "time entry could not be updated: #{time_entry.errors.full_messages}" if logger && logger.info
-        # Keep unsaved time_entry ids to display them in flash error
-        unsaved_time_entry_ids << time_entry.id
-      end
-    end
-    set_flash_from_bulk_time_entry_save(@time_entries, unsaved_time_entry_ids)
-    redirect_back_or_default project_time_entries_path(@projects.first)
-  end
-
-  def destroy
-    destroyed = TimeEntry.transaction do
-      @time_entries.each do |t|
-        unless t.destroy && t.destroyed?
-          raise ActiveRecord::Rollback
-        end
-      end
-    end
-
-    respond_to do |format|
-      format.html {
-        if destroyed
-          flash[:notice] = l(:notice_successful_delete)
-        else
-          flash[:error] = l(:notice_unable_delete_time_entry)
-        end
-        redirect_back_or_default project_time_entries_path(@projects.first)
-      }
-      format.api  {
-        if destroyed
-          render_api_ok
-        else
-          render_validation_errors(@time_entries)
-        end
-      }
-    end
-  end
-
-private
-  def find_time_entry
-    @time_entry = TimeEntry.find(params[:id])
-    unless @time_entry.editable_by?(User.current)
-      render_403
-      return false
-    end
-    @project = @time_entry.project
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def find_time_entries
-    @time_entries = TimeEntry.find_all_by_id(params[:id] || params[:ids])
-    raise ActiveRecord::RecordNotFound if @time_entries.empty?
-    @projects = @time_entries.collect(&:project).compact.uniq
-    @project = @projects.first if @projects.size == 1
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def set_flash_from_bulk_time_entry_save(time_entries, unsaved_time_entry_ids)
-    if unsaved_time_entry_ids.empty?
-      flash[:notice] = l(:notice_successful_update) unless time_entries.empty?
-    else
-      flash[:error] = l(:notice_failed_to_save_time_entries,
-                        :count => unsaved_time_entry_ids.size,
-                        :total => time_entries.size,
-                        :ids => '#' + unsaved_time_entry_ids.join(', #'))
-    end
-  end
-
-  def find_optional_project_for_new_time_entry
-    if (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present?
-      @project = Project.find(project_id)
-    end
-    if (issue_id = (params[:issue_id] || params[:time_entry] && params[:time_entry][:issue_id])).present?
-      @issue = Issue.find(issue_id)
-      @project ||= @issue.project
-    end
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def find_project_for_new_time_entry
-    find_optional_project_for_new_time_entry
-    if @project.nil?
-      render_404
-    end
-  end
-
-  def find_optional_project
-    if !params[:issue_id].blank?
-      @issue = Issue.find(params[:issue_id])
-      @project = @issue.project
-    elsif !params[:project_id].blank?
-      @project = Project.find(params[:project_id])
-    end
-  end
-
-  # Returns the TimeEntry scope for index and report actions
-  def time_entry_scope(options={})
-    scope = @query.results_scope(options)
-    if @issue
-      scope = scope.on_issue(@issue)
-    end
-    scope
-  end
-
-  def parse_params_for_bulk_time_entry_attributes(params)
-    attributes = (params[:time_entry] || {}).reject {|k,v| v.blank?}
-    attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
-    attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
-    attributes
-  end
-end
--- a/.svn/pristine/f8/f868e11e49aa1ebab883f07d048bd42ffcb7e3b1.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class WikiRedirect < ActiveRecord::Base
-  belongs_to :wiki
-
-  validates_presence_of :title, :redirects_to
-  validates_length_of :title, :redirects_to, :maximum => 255
-end
--- a/.svn/pristine/f8/f8e3393c3af527d599685daf189e7b5311a95a64.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::JsonpTest < Redmine::ApiTest::Base
-  fixtures :trackers
-
-  def test_should_ignore_jsonp_callback_with_jsonp_disabled
-    with_settings :jsonp_enabled => '0' do
-      get '/trackers.json?jsonp=handler'
-    end
-
-    assert_response :success
-    assert_match %r{^\{"trackers":.+\}$}, response.body
-    assert_equal 'application/json; charset=utf-8', response.headers['Content-Type']
-  end
-
-  def test_jsonp_should_accept_callback_param
-    with_settings :jsonp_enabled => '1' do
-      get '/trackers.json?callback=handler'
-    end
-
-    assert_response :success
-    assert_match %r{^handler\(\{"trackers":.+\}\)$}, response.body
-    assert_equal 'application/javascript; charset=utf-8', response.headers['Content-Type']
-  end
-
-  def test_jsonp_should_accept_jsonp_param
-    with_settings :jsonp_enabled => '1' do
-      get '/trackers.json?jsonp=handler'
-    end
-
-    assert_response :success
-    assert_match %r{^handler\(\{"trackers":.+\}\)$}, response.body
-    assert_equal 'application/javascript; charset=utf-8', response.headers['Content-Type']
-  end
-
-  def test_jsonp_should_strip_invalid_characters_from_callback
-    with_settings :jsonp_enabled => '1' do
-      get '/trackers.json?callback=+-aA$1_'
-    end
-
-    assert_response :success
-    assert_match %r{^aA1_\(\{"trackers":.+\}\)$}, response.body
-    assert_equal 'application/javascript; charset=utf-8', response.headers['Content-Type']
-  end
-
-  def test_jsonp_without_callback_should_return_json
-    with_settings :jsonp_enabled => '1' do
-      get '/trackers.json?callback='
-    end
-
-    assert_response :success
-    assert_match %r{^\{"trackers":.+\}$}, response.body
-    assert_equal 'application/json; charset=utf-8', response.headers['Content-Type']
-  end
-end
--- a/.svn/pristine/f9/f992af412d2338b0910671c99f9c86c6772cdf7c.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'redmine/views/builders/structure'
-
-module Redmine
-  module Views
-    module Builders
-      class Json < Structure
-        attr_accessor :jsonp
-
-        def initialize(request, response)
-          super
-          callback = request.params[:callback] || request.params[:jsonp]
-          if callback && Setting.jsonp_enabled?
-            self.jsonp = callback.to_s.gsub(/[^a-zA-Z0-9_]/, '')
-          end
-        end
-
-        def output
-          json = @struct.first.to_json
-          if jsonp.present?
-            json = "#{jsonp}(#{json})"
-            response.content_type = 'application/javascript'
-          end
-          json
-        end
-      end
-    end
-  end
-end
--- a/.svn/pristine/fa/faa06e26aeea9f7627ae814543492f9d35051460.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-module Redmine
-  module SyntaxHighlighting
-
-    class << self
-      attr_reader :highlighter
-      delegate :highlight_by_filename, :highlight_by_language, :to => :highlighter
-
-      def highlighter=(name)
-        if name.is_a?(Module)
-          @highlighter = name
-        else
-          @highlighter = const_get(name)
-        end
-      end
-    end
-
-    module CodeRay
-      require 'coderay'
-
-      class << self
-        # Highlights +text+ as the content of +filename+
-        # Should not return line numbers nor outer pre tag
-        def highlight_by_filename(text, filename)
-          language = ::CodeRay::FileType[filename]
-          language ? ::CodeRay.scan(text, language).html(:break_lines => true) : ERB::Util.h(text)
-        end
-
-        # Highlights +text+ using +language+ syntax
-        # Should not return outer pre tag
-        def highlight_by_language(text, language)
-          ::CodeRay.scan(text, language).html(:wrap => :span)
-        end
-      end
-    end
-  end
-
-  SyntaxHighlighting.highlighter = 'CodeRay'
-end
--- a/.svn/pristine/fa/fab553c0a3c9a998f2e8320cf6ed96e7fb3e898d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class TimeEntryActivity < Enumeration
-  has_many :time_entries, :foreign_key => 'activity_id'
-
-  OptionName = :enumeration_activities
-
-  def option_name
-    OptionName
-  end
-
-  def objects
-    TimeEntry.where(:activity_id => self_and_descendants(1).map(&:id))
-  end
-
-  def objects_count
-    objects.count
-  end
-
-  def transfer_relations(to)
-    objects.update_all(:activity_id => to.id)
-  end
-end
--- a/.svn/pristine/fa/fae6aa29a415564c269ced790046953485df6633.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::InfoTest < ActiveSupport::TestCase
-  def test_environment
-    env = Redmine::Info.environment
-
-    assert_kind_of String, env
-    assert_match 'Redmine version', env
-  end
-end
--- a/.svn/pristine/fb/fb0370610c36e942e95f18248151b66c8bb1d28d.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class JournalsControllerTest < ActionController::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles, :issues, :journals, :journal_details, :enabled_modules,
-    :trackers, :issue_statuses, :enumerations, :custom_fields, :custom_values, :custom_fields_projects
-
-  def setup
-    User.current = nil
-  end
-
-  def test_index
-    get :index, :project_id => 1
-    assert_response :success
-    assert_not_nil assigns(:journals)
-    assert_equal 'application/atom+xml', @response.content_type
-  end
-
-  def test_index_should_return_privates_notes_with_permission_only
-    journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
-    @request.session[:user_id] = 2
-
-    get :index, :project_id => 1
-    assert_response :success
-    assert_include journal, assigns(:journals)
-
-    Role.find(1).remove_permission! :view_private_notes
-    get :index, :project_id => 1
-    assert_response :success
-    assert_not_include journal, assigns(:journals)
-  end
-
-  def test_diff
-    get :diff, :id => 3, :detail_id => 4
-    assert_response :success
-    assert_template 'diff'
-
-    assert_tag 'span',
-      :attributes => {:class => 'diff_out'},
-      :content => /removed/
-    assert_tag 'span',
-      :attributes => {:class => 'diff_in'},
-      :content => /added/
-  end
-
-  def test_reply_to_issue
-    @request.session[:user_id] = 2
-    xhr :get, :new, :id => 6
-    assert_response :success
-    assert_template 'new'
-    assert_equal 'text/javascript', response.content_type
-    assert_include '> This is an issue', response.body
-  end
-
-  def test_reply_to_issue_without_permission
-    @request.session[:user_id] = 7
-    xhr :get, :new, :id => 6
-    assert_response 403
-  end
-
-  def test_reply_to_note
-    @request.session[:user_id] = 2
-    xhr :get, :new, :id => 6, :journal_id => 4
-    assert_response :success
-    assert_template 'new'
-    assert_equal 'text/javascript', response.content_type
-    assert_include '> A comment with a private version', response.body
-  end
-
-  def test_reply_to_private_note_should_fail_without_permission
-    journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true)
-    @request.session[:user_id] = 2
-
-    xhr :get, :new, :id => 2, :journal_id => journal.id
-    assert_response :success
-    assert_template 'new'
-    assert_equal 'text/javascript', response.content_type
-    assert_include '> Privates notes', response.body
-
-    Role.find(1).remove_permission! :view_private_notes
-    xhr :get, :new, :id => 2, :journal_id => journal.id
-    assert_response 404
-  end
-
-  def test_edit_xhr
-    @request.session[:user_id] = 1
-    xhr :get, :edit, :id => 2
-    assert_response :success
-    assert_template 'edit'
-    assert_equal 'text/javascript', response.content_type
-    assert_include 'textarea', response.body
-  end
-
-  def test_edit_private_note_should_fail_without_permission
-    journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true)
-    @request.session[:user_id] = 2
-    Role.find(1).add_permission! :edit_issue_notes
-
-    xhr :get, :edit, :id => journal.id
-    assert_response :success
-    assert_template 'edit'
-    assert_equal 'text/javascript', response.content_type
-    assert_include 'textarea', response.body
-
-    Role.find(1).remove_permission! :view_private_notes
-    xhr :get, :edit, :id => journal.id
-    assert_response 404
-  end
-
-  def test_update_xhr
-    @request.session[:user_id] = 1
-    xhr :post, :edit, :id => 2, :notes => 'Updated notes'
-    assert_response :success
-    assert_template 'update'
-    assert_equal 'text/javascript', response.content_type
-    assert_equal 'Updated notes', Journal.find(2).notes
-    assert_include 'journal-2-notes', response.body
-  end
-
-  def test_update_xhr_with_empty_notes_should_delete_the_journal
-    @request.session[:user_id] = 1
-    assert_difference 'Journal.count', -1 do
-      xhr :post, :edit, :id => 2, :notes => ''
-      assert_response :success
-      assert_template 'update'
-      assert_equal 'text/javascript', response.content_type
-    end
-    assert_nil Journal.find_by_id(2)
-    assert_include 'change-2', response.body
-  end
-end
--- a/.svn/pristine/fc/fc770db4db5a22614ed5ce3040fd496687aca860.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingTimelogsTest < ActionController::IntegrationTest
-  def test_timelogs_global
-    assert_routing(
-        { :method => 'get', :path => "/time_entries" },
-        { :controller => 'timelog', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/time_entries.csv" },
-        { :controller => 'timelog', :action => 'index', :format => 'csv' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/time_entries.atom" },
-        { :controller => 'timelog', :action => 'index', :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/time_entries/new" },
-        { :controller => 'timelog', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/time_entries/22/edit" },
-        { :controller => 'timelog', :action => 'edit', :id => '22' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/time_entries" },
-        { :controller => 'timelog', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/time_entries/22" },
-        { :controller => 'timelog', :action => 'update', :id => '22' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/time_entries/55" },
-        { :controller => 'timelog', :action => 'destroy', :id => '55' }
-      )
-  end
-
-  def test_timelogs_scoped_under_project
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/time_entries" },
-        { :controller => 'timelog', :action => 'index', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/time_entries.csv" },
-        { :controller => 'timelog', :action => 'index', :project_id => '567',
-          :format => 'csv' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/time_entries.atom" },
-        { :controller => 'timelog', :action => 'index', :project_id => '567',
-          :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/time_entries/new" },
-        { :controller => 'timelog', :action => 'new', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/projects/567/time_entries/22/edit" },
-        { :controller => 'timelog', :action => 'edit',
-          :id => '22', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/projects/567/time_entries" },
-        { :controller => 'timelog', :action => 'create',
-          :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/projects/567/time_entries/22" },
-        { :controller => 'timelog', :action => 'update',
-          :id => '22', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/projects/567/time_entries/55" },
-        { :controller => 'timelog', :action => 'destroy',
-          :id => '55', :project_id => '567' }
-      )
-  end
-
-  def test_timelogs_scoped_under_issues
-    assert_routing(
-        { :method => 'get', :path => "/issues/234/time_entries" },
-        { :controller => 'timelog', :action => 'index', :issue_id => '234' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/234/time_entries.csv" },
-        { :controller => 'timelog', :action => 'index', :issue_id => '234',
-          :format => 'csv' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/234/time_entries.atom" },
-        { :controller => 'timelog', :action => 'index', :issue_id => '234',
-          :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/234/time_entries/new" },
-        { :controller => 'timelog', :action => 'new', :issue_id => '234' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/issues/234/time_entries/22/edit" },
-        { :controller => 'timelog', :action => 'edit', :id => '22',
-          :issue_id => '234' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/issues/234/time_entries" },
-        { :controller => 'timelog', :action => 'create', :issue_id => '234' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/issues/234/time_entries/22" },
-        { :controller => 'timelog', :action => 'update', :id => '22',
-          :issue_id => '234' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/issues/234/time_entries/55" },
-        { :controller => 'timelog', :action => 'destroy', :id => '55',
-          :issue_id => '234' }
-      )
-  end
-
-  def test_timelogs_scoped_under_project_and_issues
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/ecookbook/issues/234/time_entries" },
-        { :controller => 'timelog', :action => 'index',
-          :issue_id => '234', :project_id => 'ecookbook' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/ecookbook/issues/234/time_entries.csv" },
-        { :controller => 'timelog', :action => 'index',
-          :issue_id => '234', :project_id => 'ecookbook', :format => 'csv' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/ecookbook/issues/234/time_entries.atom" },
-        { :controller => 'timelog', :action => 'index',
-          :issue_id => '234', :project_id => 'ecookbook', :format => 'atom' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/ecookbook/issues/234/time_entries/new" },
-        { :controller => 'timelog', :action => 'new',
-          :issue_id => '234', :project_id => 'ecookbook' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/ecookbook/issues/234/time_entries/22/edit" },
-        { :controller => 'timelog', :action => 'edit', :id => '22',
-          :issue_id => '234', :project_id => 'ecookbook' }
-      )
-    assert_routing(
-        { :method => 'post',
-          :path => "/projects/ecookbook/issues/234/time_entries" },
-        { :controller => 'timelog', :action => 'create',
-          :issue_id => '234', :project_id => 'ecookbook' }
-      )
-    assert_routing(
-        { :method => 'put',
-          :path => "/projects/ecookbook/issues/234/time_entries/22" },
-        { :controller => 'timelog', :action => 'update', :id => '22',
-          :issue_id => '234', :project_id => 'ecookbook' }
-      )
-    assert_routing(
-        { :method => 'delete',
-          :path => "/projects/ecookbook/issues/234/time_entries/55" },
-        { :controller => 'timelog', :action => 'destroy', :id => '55',
-          :issue_id => '234', :project_id => 'ecookbook' }
-      )
-  end
-
-  def test_timelogs_report
-    assert_routing(
-        { :method => 'get',
-          :path => "/time_entries/report" },
-        { :controller => 'timelog', :action => 'report' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/time_entries/report.csv" },
-        { :controller => 'timelog', :action => 'report', :format => 'csv' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/issues/234/time_entries/report" },
-        { :controller => 'timelog', :action => 'report', :issue_id => '234' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/issues/234/time_entries/report.csv" },
-        { :controller => 'timelog', :action => 'report', :issue_id => '234',
-          :format => 'csv' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/567/time_entries/report" },
-        { :controller => 'timelog', :action => 'report', :project_id => '567' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/projects/567/time_entries/report.csv" },
-        { :controller => 'timelog', :action => 'report', :project_id => '567',
-          :format => 'csv' }
-      )
-  end
-
-  def test_timelogs_bulk_edit
-    assert_routing(
-        { :method => 'delete',
-          :path => "/time_entries/destroy" },
-        { :controller => 'timelog', :action => 'destroy' }
-      )
-    assert_routing(
-        { :method => 'post',
-          :path => "/time_entries/bulk_update" },
-        { :controller => 'timelog', :action => 'bulk_update' }
-      )
-    assert_routing(
-        { :method => 'get',
-          :path => "/time_entries/bulk_edit" },
-        { :controller => 'timelog', :action => 'bulk_edit' }
-      )
-  end
-end
--- a/.svn/pristine/fc/fc954db436a100775650d80a4eca7f8ba87c8867.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,477 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-class IssuesController < ApplicationController
-  menu_item :new_issue, :only => [:new, :create]
-  default_search_scope :issues
-
-  before_filter :find_issue, :only => [:show, :edit, :update]
-  before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :destroy]
-  before_filter :find_project, :only => [:new, :create, :update_form]
-  before_filter :authorize, :except => [:index]
-  before_filter :find_optional_project, :only => [:index]
-  before_filter :check_for_default_issue_status, :only => [:new, :create]
-  before_filter :build_new_issue_from_params, :only => [:new, :create, :update_form]
-  accept_rss_auth :index, :show
-  accept_api_auth :index, :show, :create, :update, :destroy
-
-  rescue_from Query::StatementInvalid, :with => :query_statement_invalid
-
-  helper :journals
-  helper :projects
-  include ProjectsHelper
-  helper :custom_fields
-  include CustomFieldsHelper
-  helper :issue_relations
-  include IssueRelationsHelper
-  helper :watchers
-  include WatchersHelper
-  helper :attachments
-  include AttachmentsHelper
-  helper :queries
-  include QueriesHelper
-  helper :repositories
-  include RepositoriesHelper
-  helper :sort
-  include SortHelper
-  include IssuesHelper
-  helper :timelog
-  include Redmine::Export::PDF
-
-  def index
-    retrieve_query
-    sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
-    sort_update(@query.sortable_columns)
-    @query.sort_criteria = sort_criteria.to_a
-
-    if @query.valid?
-      case params[:format]
-      when 'csv', 'pdf'
-        @limit = Setting.issues_export_limit.to_i
-      when 'atom'
-        @limit = Setting.feeds_limit.to_i
-      when 'xml', 'json'
-        @offset, @limit = api_offset_and_limit
-      else
-        @limit = per_page_option
-      end
-
-      @issue_count = @query.issue_count
-      @issue_pages = Paginator.new @issue_count, @limit, params['page']
-      @offset ||= @issue_pages.offset
-      @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
-                              :order => sort_clause,
-                              :offset => @offset,
-                              :limit => @limit)
-      @issue_count_by_group = @query.issue_count_by_group
-
-      respond_to do |format|
-        format.html { render :template => 'issues/index', :layout => !request.xhr? }
-        format.api  {
-          Issue.load_visible_relations(@issues) if include_in_api_response?('relations')
-        }
-        format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
-        format.csv  { send_data(query_to_csv(@issues, @query, params), :type => 'text/csv; header=present', :filename => 'issues.csv') }
-        format.pdf  { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'issues.pdf') }
-      end
-    else
-      respond_to do |format|
-        format.html { render(:template => 'issues/index', :layout => !request.xhr?) }
-        format.any(:atom, :csv, :pdf) { render(:nothing => true) }
-        format.api { render_validation_errors(@query) }
-      end
-    end
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def show
-    @journals = @issue.journals.includes(:user, :details).reorder("#{Journal.table_name}.id ASC").all
-    @journals.each_with_index {|j,i| j.indice = i+1}
-    @journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
-    Journal.preload_journals_details_custom_fields(@journals)
-    # TODO: use #select! when ruby1.8 support is dropped
-    @journals.reject! {|journal| !journal.notes? && journal.visible_details.empty?}
-    @journals.reverse! if User.current.wants_comments_in_reverse_order?
-
-    @changesets = @issue.changesets.visible.all
-    @changesets.reverse! if User.current.wants_comments_in_reverse_order?
-
-    @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
-    @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
-    @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
-    @priorities = IssuePriority.active
-    @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
-    @relation = IssueRelation.new
-
-    respond_to do |format|
-      format.html {
-        retrieve_previous_and_next_issue_ids
-        render :template => 'issues/show'
-      }
-      format.api
-      format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
-      format.pdf  {
-        pdf = issue_to_pdf(@issue, :journals => @journals)
-        send_data(pdf, :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf")
-      }
-    end
-  end
-
-  # Add a new issue
-  # The new issue will be created from an existing one if copy_from parameter is given
-  def new
-    respond_to do |format|
-      format.html { render :action => 'new', :layout => !request.xhr? }
-    end
-  end
-
-  def create
-    call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
-    @issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
-    if @issue.save
-      call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
-      respond_to do |format|
-        format.html {
-          render_attachment_warning_if_needed(@issue)
-          flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("##{@issue.id}", issue_path(@issue), :title => @issue.subject))
-          if params[:continue]
-            attrs = {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?}
-            redirect_to new_project_issue_path(@issue.project, :issue => attrs)
-          else
-            redirect_to issue_path(@issue)
-          end
-        }
-        format.api  { render :action => 'show', :status => :created, :location => issue_url(@issue) }
-      end
-      return
-    else
-      respond_to do |format|
-        format.html { render :action => 'new' }
-        format.api  { render_validation_errors(@issue) }
-      end
-    end
-  end
-
-  def edit
-    return unless update_issue_from_params
-
-    respond_to do |format|
-      format.html { }
-      format.xml  { }
-    end
-  end
-
-  def update
-    return unless update_issue_from_params
-    @issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
-    saved = false
-    begin
-      saved = save_issue_with_child_records
-    rescue ActiveRecord::StaleObjectError
-      @conflict = true
-      if params[:last_journal_id]
-        @conflict_journals = @issue.journals_after(params[:last_journal_id]).all
-        @conflict_journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
-      end
-    end
-
-    if saved
-      render_attachment_warning_if_needed(@issue)
-      flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
-
-      respond_to do |format|
-        format.html { redirect_back_or_default issue_path(@issue) }
-        format.api  { render_api_ok }
-      end
-    else
-      respond_to do |format|
-        format.html { render :action => 'edit' }
-        format.api  { render_validation_errors(@issue) }
-      end
-    end
-  end
-
-  # Updates the issue form when changing the project, status or tracker
-  # on issue creation/update
-  def update_form
-  end
-
-  # Bulk edit/copy a set of issues
-  def bulk_edit
-    @issues.sort!
-    @copy = params[:copy].present?
-    @notes = params[:notes]
-
-    if User.current.allowed_to?(:move_issues, @projects)
-      @allowed_projects = Issue.allowed_target_projects_on_move
-      if params[:issue]
-        @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:issue][:project_id].to_s}
-        if @target_project
-          target_projects = [@target_project]
-        end
-      end
-    end
-    target_projects ||= @projects
-
-    if @copy
-      @available_statuses = [IssueStatus.default]
-    else
-      @available_statuses = @issues.map(&:new_statuses_allowed_to).reduce(:&)
-    end
-    @custom_fields = target_projects.map{|p|p.all_issue_custom_fields.visible}.reduce(:&)
-    @assignables = target_projects.map(&:assignable_users).reduce(:&)
-    @trackers = target_projects.map(&:trackers).reduce(:&)
-    @versions = target_projects.map {|p| p.shared_versions.open}.reduce(:&)
-    @categories = target_projects.map {|p| p.issue_categories}.reduce(:&)
-    if @copy
-      @attachments_present = @issues.detect {|i| i.attachments.any?}.present?
-      @subtasks_present = @issues.detect {|i| !i.leaf?}.present?
-    end
-
-    @safe_attributes = @issues.map(&:safe_attribute_names).reduce(:&)
-
-    @issue_params = params[:issue] || {}
-    @issue_params[:custom_field_values] ||= {}
-  end
-
-  def bulk_update
-    @issues.sort!
-    @copy = params[:copy].present?
-    attributes = parse_params_for_bulk_issue_attributes(params)
-
-    unsaved_issues = []
-    saved_issues = []
-
-    if @copy && params[:copy_subtasks].present?
-      # Descendant issues will be copied with the parent task
-      # Don't copy them twice
-      @issues.reject! {|issue| @issues.detect {|other| issue.is_descendant_of?(other)}}
-    end
-
-    @issues.each do |orig_issue|
-      orig_issue.reload
-      if @copy
-        issue = orig_issue.copy({},
-          :attachments => params[:copy_attachments].present?,
-          :subtasks => params[:copy_subtasks].present?
-        )
-      else
-        issue = orig_issue
-      end
-      journal = issue.init_journal(User.current, params[:notes])
-      issue.safe_attributes = attributes
-      call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
-      if issue.save
-        saved_issues << issue
-      else
-        unsaved_issues << orig_issue
-      end
-    end
-
-    if unsaved_issues.empty?
-      flash[:notice] = l(:notice_successful_update) unless saved_issues.empty?
-      if params[:follow]
-        if @issues.size == 1 && saved_issues.size == 1
-          redirect_to issue_path(saved_issues.first)
-        elsif saved_issues.map(&:project).uniq.size == 1
-          redirect_to project_issues_path(saved_issues.map(&:project).first)
-        end
-      else
-        redirect_back_or_default _project_issues_path(@project)
-      end
-    else
-      @saved_issues = @issues
-      @unsaved_issues = unsaved_issues
-      @issues = Issue.visible.find_all_by_id(@unsaved_issues.map(&:id))
-      bulk_edit
-      render :action => 'bulk_edit'
-    end
-  end
-
-  def destroy
-    @hours = TimeEntry.where(:issue_id => @issues.map(&:id)).sum(:hours).to_f
-    if @hours > 0
-      case params[:todo]
-      when 'destroy'
-        # nothing to do
-      when 'nullify'
-        TimeEntry.update_all('issue_id = NULL', ['issue_id IN (?)', @issues])
-      when 'reassign'
-        reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
-        if reassign_to.nil?
-          flash.now[:error] = l(:error_issue_not_found_in_project)
-          return
-        else
-          TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
-        end
-      else
-        # display the destroy form if it's a user request
-        return unless api_request?
-      end
-    end
-    @issues.each do |issue|
-      begin
-        issue.reload.destroy
-      rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
-        # nothing to do, issue was already deleted (eg. by a parent)
-      end
-    end
-    respond_to do |format|
-      format.html { redirect_back_or_default _project_issues_path(@project) }
-      format.api  { render_api_ok }
-    end
-  end
-
-  private
-
-  def find_project
-    project_id = params[:project_id] || (params[:issue] && params[:issue][:project_id])
-    @project = Project.find(project_id)
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def retrieve_previous_and_next_issue_ids
-    retrieve_query_from_session
-    if @query
-      sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
-      sort_update(@query.sortable_columns, 'issues_index_sort')
-      limit = 500
-      issue_ids = @query.issue_ids(:order => sort_clause, :limit => (limit + 1), :include => [:assigned_to, :tracker, :priority, :category, :fixed_version])
-      if (idx = issue_ids.index(@issue.id)) && idx < limit
-        if issue_ids.size < 500
-          @issue_position = idx + 1
-          @issue_count = issue_ids.size
-        end
-        @prev_issue_id = issue_ids[idx - 1] if idx > 0
-        @next_issue_id = issue_ids[idx + 1] if idx < (issue_ids.size - 1)
-      end
-    end
-  end
-
-  # Used by #edit and #update to set some common instance variables
-  # from the params
-  # TODO: Refactor, not everything in here is needed by #edit
-  def update_issue_from_params
-    @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
-    @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
-    @time_entry.attributes = params[:time_entry]
-
-    @issue.init_journal(User.current)
-
-    issue_attributes = params[:issue]
-    if issue_attributes && params[:conflict_resolution]
-      case params[:conflict_resolution]
-      when 'overwrite'
-        issue_attributes = issue_attributes.dup
-        issue_attributes.delete(:lock_version)
-      when 'add_notes'
-        issue_attributes = issue_attributes.slice(:notes)
-      when 'cancel'
-        redirect_to issue_path(@issue)
-        return false
-      end
-    end
-    @issue.safe_attributes = issue_attributes
-    @priorities = IssuePriority.active
-    @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
-    true
-  end
-
-  # TODO: Refactor, lots of extra code in here
-  # TODO: Changing tracker on an existing issue should not trigger this
-  def build_new_issue_from_params
-    if params[:id].blank?
-      @issue = Issue.new
-      if params[:copy_from]
-        begin
-          @copy_from = Issue.visible.find(params[:copy_from])
-          @copy_attachments = params[:copy_attachments].present? || request.get?
-          @copy_subtasks = params[:copy_subtasks].present? || request.get?
-          @issue.copy_from(@copy_from, :attachments => @copy_attachments, :subtasks => @copy_subtasks)
-        rescue ActiveRecord::RecordNotFound
-          render_404
-          return
-        end
-      end
-      @issue.project = @project
-    else
-      @issue = @project.issues.visible.find(params[:id])
-    end
-
-    @issue.project = @project
-    @issue.author ||= User.current
-    # Tracker must be set before custom field values
-    @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
-    if @issue.tracker.nil?
-      render_error l(:error_no_tracker_in_project)
-      return false
-    end
-    @issue.start_date ||= Date.today if Setting.default_issue_start_date_to_creation_date?
-    @issue.safe_attributes = params[:issue]
-
-    @priorities = IssuePriority.active
-    @allowed_statuses = @issue.new_statuses_allowed_to(User.current, @issue.new_record?)
-    @available_watchers = (@issue.project.users.sort + @issue.watcher_users).uniq
-  end
-
-  def check_for_default_issue_status
-    if IssueStatus.default.nil?
-      render_error l(:error_no_default_issue_status)
-      return false
-    end
-  end
-
-  def parse_params_for_bulk_issue_attributes(params)
-    attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
-    attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
-    if custom = attributes[:custom_field_values]
-      custom.reject! {|k,v| v.blank?}
-      custom.keys.each do |k|
-        if custom[k].is_a?(Array)
-          custom[k] << '' if custom[k].delete('__none__')
-        else
-          custom[k] = '' if custom[k] == '__none__'
-        end
-      end
-    end
-    attributes
-  end
-
-  # Saves @issue and a time_entry from the parameters
-  def save_issue_with_child_records
-    Issue.transaction do
-      if params[:time_entry] && (params[:time_entry][:hours].present? || params[:time_entry][:comments].present?) && User.current.allowed_to?(:log_time, @issue.project)
-        time_entry = @time_entry || TimeEntry.new
-        time_entry.project = @issue.project
-        time_entry.issue = @issue
-        time_entry.user = User.current
-        time_entry.spent_on = User.current.today
-        time_entry.attributes = params[:time_entry]
-        @issue.time_entries << time_entry
-      end
-
-      call_hook(:controller_issues_edit_before_save, { :params => params, :issue => @issue, :time_entry => time_entry, :journal => @issue.current_journal})
-      if @issue.save
-        call_hook(:controller_issues_edit_after_save, { :params => params, :issue => @issue, :time_entry => time_entry, :journal => @issue.current_journal})
-      else
-        raise ActiveRecord::Rollback
-      end
-    end
-  end
-end
--- a/.svn/pristine/fd/fde74b3b9d30225e1a58fe5d703e35242b069eea.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-require 'capybara/rails'
-
-Capybara.default_driver = :selenium
-Capybara.register_driver :selenium do |app|
-  # Use the following driver definition to test locally using Chrome
-  # (also requires chromedriver to be in PATH)
-  # Capybara::Selenium::Driver.new(app, :browser => :chrome)
-  # Add :switches => %w[--lang=en] to force default browser locale to English
-  # Default for Selenium remote driver is to connect to local host on port 4444 
-  # This can be change using :url => 'http://localhost:9195' if necessary
-  # PhantomJS 1.8 now directly supports Webdriver Wire API,
-  # simply run it with `phantomjs --webdriver 4444`
-  # Add :desired_capabilities => Selenium::WebDriver::Remote::Capabilities.internet_explorer)
-  # to run on Selenium Grid Hub with IE
-  Capybara::Selenium::Driver.new(app, :browser => :remote)
-end
-
-# default: 2
-Capybara.default_wait_time = 2
-
-DatabaseCleaner.strategy = :truncation
-
-module Redmine
-  module UiTest
-    # Base class for UI tests
-    class Base < ActionDispatch::IntegrationTest
-      include Capybara::DSL
-
-      # Stop ActiveRecord from wrapping tests in transactions
-      # Transactional fixtures do not work with Selenium tests, because Capybara
-      # uses a separate server thread, which the transactions would be hidden
-      self.use_transactional_fixtures = false
-
-      # Should not depend on locale since Redmine displays login page
-      # using default browser locale which depend on system locale for "real" browsers drivers
-      def log_user(login, password)
-        visit '/my/page'
-        assert_equal '/login', current_path
-        within('#login-form form') do
-          fill_in 'username', :with => login
-          fill_in 'password', :with => password
-          find('input[name=login]').click
-        end
-        assert_equal '/my/page', current_path
-      end
-
-      teardown do
-        Capybara.reset_sessions!    # Forget the (simulated) browser state
-        Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver
-        DatabaseCleaner.clean
-      end
-    end
-  end
-end
--- a/.svn/pristine/fe/fe48a02cf4f3380a268baa6d0b7204b03f3af240.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,345 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WorkflowsControllerTest < ActionController::TestCase
-  fixtures :roles, :trackers, :workflows, :users, :issue_statuses
-
-  def setup
-    User.current = nil
-    @request.session[:user_id] = 1 # admin
-  end
-
-  def test_index
-    get :index
-    assert_response :success
-    assert_template 'index'
-
-    count = WorkflowTransition.where(:role_id => 1, :tracker_id => 2).count
-    assert_tag :tag => 'a', :content => count.to_s,
-                            :attributes => { :href => '/workflows/edit?role_id=1&amp;tracker_id=2' }
-  end
-
-  def test_get_edit
-    get :edit
-    assert_response :success
-    assert_template 'edit'
-    assert_not_nil assigns(:roles)
-    assert_not_nil assigns(:trackers)
-  end
-
-  def test_get_edit_with_role_and_tracker
-    WorkflowTransition.delete_all
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 2, :new_status_id => 3)
-    WorkflowTransition.create!(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 5)
-
-    get :edit, :role_id => 2, :tracker_id => 1
-    assert_response :success
-    assert_template 'edit'
-
-    # used status only
-    assert_not_nil assigns(:statuses)
-    assert_equal [2, 3, 5], assigns(:statuses).collect(&:id)
-
-    # allowed transitions
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'issue_status[3][5][]',
-                                                 :value => 'always',
-                                                 :checked => 'checked' }
-    # not allowed
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'issue_status[3][2][]',
-                                                 :value => 'always',
-                                                 :checked => nil }
-    # unused
-    assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                    :name => 'issue_status[1][1][]' }
-  end
-
-  def test_get_edit_with_role_and_tracker_and_all_statuses
-    WorkflowTransition.delete_all
-
-    get :edit, :role_id => 2, :tracker_id => 1, :used_statuses_only => '0'
-    assert_response :success
-    assert_template 'edit'
-
-    assert_not_nil assigns(:statuses)
-    assert_equal IssueStatus.count, assigns(:statuses).size
-
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'issue_status[1][1][]',
-                                                 :value => 'always',
-                                                 :checked => nil }
-  end
-
-  def test_post_edit
-    post :edit, :role_id => 2, :tracker_id => 1,
-      :issue_status => {
-        '4' => {'5' => ['always']},
-        '3' => {'1' => ['always'], '2' => ['always']}
-      }
-    assert_redirected_to '/workflows/edit?role_id=2&tracker_id=1'
-
-    assert_equal 3, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count
-    assert_not_nil  WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2).first
-    assert_nil      WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4).first
-  end
-
-  def test_post_edit_with_additional_transitions
-    post :edit, :role_id => 2, :tracker_id => 1,
-      :issue_status => {
-        '4' => {'5' => ['always']},
-        '3' => {'1' => ['author'], '2' => ['assignee'], '4' => ['author', 'assignee']}
-      }
-    assert_redirected_to '/workflows/edit?role_id=2&tracker_id=1'
-
-    assert_equal 4, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count
-
-    w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 4, :new_status_id => 5).first
-    assert ! w.author
-    assert ! w.assignee
-    w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 1).first
-    assert w.author
-    assert ! w.assignee
-    w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2).first
-    assert ! w.author
-    assert w.assignee
-    w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 4).first
-    assert w.author
-    assert w.assignee
-  end
-
-  def test_clear_workflow
-    assert WorkflowTransition.where(:role_id => 1, :tracker_id => 2).count > 0
-
-    post :edit, :role_id => 1, :tracker_id => 2
-    assert_equal 0, WorkflowTransition.where(:role_id => 1, :tracker_id => 2).count
-  end
-
-  def test_get_permissions
-    get :permissions
-
-    assert_response :success
-    assert_template 'permissions'
-    assert_not_nil assigns(:roles)
-    assert_not_nil assigns(:trackers)
-  end
-
-  def test_get_permissions_with_role_and_tracker
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'assigned_to_id', :rule => 'required')
-    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'fixed_version_id', :rule => 'required')
-    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 3, :field_name => 'fixed_version_id', :rule => 'readonly')
-
-    get :permissions, :role_id => 1, :tracker_id => 2
-    assert_response :success
-    assert_template 'permissions'
-
-    assert_select 'input[name=role_id][value=1]'
-    assert_select 'input[name=tracker_id][value=2]'
-
-    # Required field
-    assert_select 'select[name=?]', 'permissions[assigned_to_id][2]' do
-      assert_select 'option[value=]'
-      assert_select 'option[value=][selected=selected]', 0
-      assert_select 'option[value=readonly]', :text => 'Read-only'
-      assert_select 'option[value=readonly][selected=selected]', 0
-      assert_select 'option[value=required]', :text => 'Required'
-      assert_select 'option[value=required][selected=selected]'
-    end
-
-    # Read-only field
-    assert_select 'select[name=?]', 'permissions[fixed_version_id][3]' do
-      assert_select 'option[value=]'
-      assert_select 'option[value=][selected=selected]', 0
-      assert_select 'option[value=readonly]', :text => 'Read-only'
-      assert_select 'option[value=readonly][selected=selected]'
-      assert_select 'option[value=required]', :text => 'Required'
-      assert_select 'option[value=required][selected=selected]', 0
-    end
-
-    # Other field
-    assert_select 'select[name=?]', 'permissions[due_date][3]' do
-      assert_select 'option[value=]'
-      assert_select 'option[value=][selected=selected]', 0
-      assert_select 'option[value=readonly]', :text => 'Read-only'
-      assert_select 'option[value=readonly][selected=selected]', 0
-      assert_select 'option[value=required]', :text => 'Required'
-      assert_select 'option[value=required][selected=selected]', 0
-    end
-  end
-
-  def test_get_permissions_with_required_custom_field_should_not_show_required_option
-    cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :tracker_ids => [1], :is_required => true)
-
-    get :permissions, :role_id => 1, :tracker_id => 1
-    assert_response :success
-    assert_template 'permissions'
-
-    # Custom field that is always required
-    # The default option is "(Required)"
-    assert_select 'select[name=?]', "permissions[#{cf.id}][3]" do
-      assert_select 'option[value=]'
-      assert_select 'option[value=readonly]', :text => 'Read-only'
-      assert_select 'option[value=required]', 0
-    end
-  end
-
-  def test_get_permissions_should_disable_hidden_custom_fields
-    cf1 = IssueCustomField.generate!(:tracker_ids => [1], :visible => true)
-    cf2 = IssueCustomField.generate!(:tracker_ids => [1], :visible => false, :role_ids => [1])
-    cf3 = IssueCustomField.generate!(:tracker_ids => [1], :visible => false, :role_ids => [1, 2])
-
-    get :permissions, :role_id => 2, :tracker_id => 1
-    assert_response :success
-    assert_template 'permissions'
-
-    assert_select 'select[name=?]:not(.disabled)', "permissions[#{cf1.id}][1]"
-    assert_select 'select[name=?]:not(.disabled)', "permissions[#{cf3.id}][1]"
-
-    assert_select 'select[name=?][disabled=disabled]', "permissions[#{cf2.id}][1]" do
-      assert_select 'option[value=][selected=selected]', :text => 'Hidden'
-    end
-  end
-
-  def test_get_permissions_with_role_and_tracker_and_all_statuses
-    WorkflowTransition.delete_all
-
-    get :permissions, :role_id => 1, :tracker_id => 2, :used_statuses_only => '0'
-    assert_response :success
-    assert_equal IssueStatus.sorted.all, assigns(:statuses)
-  end
-
-  def test_post_permissions
-    WorkflowPermission.delete_all
-
-    post :permissions, :role_id => 1, :tracker_id => 2, :permissions => {
-      'assigned_to_id' => {'1' => '', '2' => 'readonly', '3' => ''},
-      'fixed_version_id' => {'1' => 'required', '2' => 'readonly', '3' => ''},
-      'due_date' => {'1' => '', '2' => '', '3' => ''},
-    }
-    assert_redirected_to '/workflows/permissions?role_id=1&tracker_id=2'
-
-    workflows = WorkflowPermission.all
-    assert_equal 3, workflows.size
-    workflows.each do |workflow|
-      assert_equal 1, workflow.role_id
-      assert_equal 2, workflow.tracker_id
-    end
-    assert workflows.detect {|wf| wf.old_status_id == 2 && wf.field_name == 'assigned_to_id' && wf.rule == 'readonly'}
-    assert workflows.detect {|wf| wf.old_status_id == 1 && wf.field_name == 'fixed_version_id' && wf.rule == 'required'}
-    assert workflows.detect {|wf| wf.old_status_id == 2 && wf.field_name == 'fixed_version_id' && wf.rule == 'readonly'}
-  end
-
-  def test_post_permissions_should_clear_permissions
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'assigned_to_id', :rule => 'required')
-    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'fixed_version_id', :rule => 'required')
-    wf1 = WorkflowPermission.create!(:role_id => 1, :tracker_id => 3, :old_status_id => 2, :field_name => 'fixed_version_id', :rule => 'required')
-    wf2 = WorkflowPermission.create!(:role_id => 2, :tracker_id => 2, :old_status_id => 3, :field_name => 'fixed_version_id', :rule => 'readonly')
-
-    post :permissions, :role_id => 1, :tracker_id => 2
-    assert_redirected_to '/workflows/permissions?role_id=1&tracker_id=2'
-
-    workflows = WorkflowPermission.all
-    assert_equal 2, workflows.size
-    assert wf1.reload
-    assert wf2.reload
-  end
-
-  def test_get_copy
-    get :copy
-    assert_response :success
-    assert_template 'copy'
-    assert_select 'select[name=source_tracker_id]' do
-      assert_select 'option[value=1]', :text => 'Bug'
-    end
-    assert_select 'select[name=source_role_id]' do
-      assert_select 'option[value=2]', :text => 'Developer'
-    end
-    assert_select 'select[name=?]', 'target_tracker_ids[]' do
-      assert_select 'option[value=3]', :text => 'Support request'
-    end
-    assert_select 'select[name=?]', 'target_role_ids[]' do
-      assert_select 'option[value=1]', :text => 'Manager'
-    end
-  end
-
-  def test_post_copy_one_to_one
-    source_transitions = status_transitions(:tracker_id => 1, :role_id => 2)
-
-    post :copy, :source_tracker_id => '1', :source_role_id => '2',
-                :target_tracker_ids => ['3'], :target_role_ids => ['1']
-    assert_response 302
-    assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 1)
-  end
-
-  def test_post_copy_one_to_many
-    source_transitions = status_transitions(:tracker_id => 1, :role_id => 2)
-
-    post :copy, :source_tracker_id => '1', :source_role_id => '2',
-                :target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3']
-    assert_response 302
-    assert_equal source_transitions, status_transitions(:tracker_id => 2, :role_id => 1)
-    assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 1)
-    assert_equal source_transitions, status_transitions(:tracker_id => 2, :role_id => 3)
-    assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 3)
-  end
-
-  def test_post_copy_many_to_many
-    source_t2 = status_transitions(:tracker_id => 2, :role_id => 2)
-    source_t3 = status_transitions(:tracker_id => 3, :role_id => 2)
-
-    post :copy, :source_tracker_id => 'any', :source_role_id => '2',
-                :target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3']
-    assert_response 302
-    assert_equal source_t2, status_transitions(:tracker_id => 2, :role_id => 1)
-    assert_equal source_t3, status_transitions(:tracker_id => 3, :role_id => 1)
-    assert_equal source_t2, status_transitions(:tracker_id => 2, :role_id => 3)
-    assert_equal source_t3, status_transitions(:tracker_id => 3, :role_id => 3)
-  end
-
-  def test_post_copy_with_incomplete_source_specification_should_fail
-    assert_no_difference 'WorkflowRule.count' do
-      post :copy,
-        :source_tracker_id => '', :source_role_id => '2',
-        :target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3']
-      assert_response 200
-      assert_select 'div.flash.error', :text => 'Please select a source tracker or role' 
-    end
-  end
-
-  def test_post_copy_with_incomplete_target_specification_should_fail
-    assert_no_difference 'WorkflowRule.count' do
-      post :copy,
-        :source_tracker_id => '1', :source_role_id => '2',
-        :target_tracker_ids => ['2', '3']
-      assert_response 200
-      assert_select 'div.flash.error', :text => 'Please select target tracker(s) and role(s)'
-    end
-  end
-
-  # Returns an array of status transitions that can be compared
-  def status_transitions(conditions)
-    WorkflowTransition.
-      where(conditions).
-      order('tracker_id, role_id, old_status_id, new_status_id').
-      all.
-      collect {|w| [w.old_status, w.new_status_id]}
-  end
-end
--- a/.svn/pristine/fe/fe616c1a4677a1989f6035ef3d43e4954fce98ea.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingEnumerationsTest < ActionController::IntegrationTest
-  def test_enumerations
-    assert_routing(
-        { :method => 'get', :path => "/enumerations" },
-        { :controller => 'enumerations', :action => 'index' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/enumerations/new" },
-        { :controller => 'enumerations', :action => 'new' }
-      )
-    assert_routing(
-        { :method => 'post', :path => "/enumerations" },
-        { :controller => 'enumerations', :action => 'create' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/enumerations/2/edit" },
-        { :controller => 'enumerations', :action => 'edit', :id => '2' }
-      )
-    assert_routing(
-        { :method => 'put', :path => "/enumerations/2" },
-        { :controller => 'enumerations', :action => 'update', :id => '2' }
-      )
-    assert_routing(
-        { :method => 'delete', :path => "/enumerations/2" },
-        { :controller => 'enumerations', :action => 'destroy', :id => '2' }
-      )
-    assert_routing(
-        { :method => 'get', :path => "/enumerations/issue_priorities.xml" },
-        { :controller => 'enumerations', :action => 'index', :type => 'issue_priorities', :format => 'xml' }
-      )
-  end
-end
--- a/.svn/pristine/fe/fe7d0011c363388fa41294d974753444295841f2.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,617 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require 'uri'
-require 'cgi'
-
-class Unauthorized < Exception; end
-
-class ApplicationController < ActionController::Base
-  include Redmine::I18n
-  include Redmine::Pagination
-  include RoutesHelper
-  helper :routes
-
-  class_attribute :accept_api_auth_actions
-  class_attribute :accept_rss_auth_actions
-  class_attribute :model_object
-
-  layout 'base'
-
-  protect_from_forgery
-
-  def verify_authenticity_token
-    unless api_request?
-      super
-    end
-  end
-
-  def handle_unverified_request
-    unless api_request?
-      super
-      cookies.delete(autologin_cookie_name)
-      render_error :status => 422, :message => "Invalid form authenticity token."
-    end
-  end
-
-  before_filter :session_expiration, :user_setup, :check_if_login_required, :check_password_change, :set_localization
-
-  rescue_from ::Unauthorized, :with => :deny_access
-  rescue_from ::ActionView::MissingTemplate, :with => :missing_template
-
-  include Redmine::Search::Controller
-  include Redmine::MenuManager::MenuController
-  helper Redmine::MenuManager::MenuHelper
-
-  def session_expiration
-    if session[:user_id]
-      if session_expired? && !try_to_autologin
-        reset_session
-        flash[:error] = l(:error_session_expired)
-        redirect_to signin_url
-      else
-        session[:atime] = Time.now.utc.to_i
-      end
-    end
-  end
-
-  def session_expired?
-    if Setting.session_lifetime?
-      unless session[:ctime] && (Time.now.utc.to_i - session[:ctime].to_i <= Setting.session_lifetime.to_i * 60)
-        return true
-      end
-    end
-    if Setting.session_timeout?
-      unless session[:atime] && (Time.now.utc.to_i - session[:atime].to_i <= Setting.session_timeout.to_i * 60)
-        return true
-      end
-    end
-    false
-  end
-
-  def start_user_session(user)
-    session[:user_id] = user.id
-    session[:ctime] = Time.now.utc.to_i
-    session[:atime] = Time.now.utc.to_i
-    if user.must_change_password?
-      session[:pwd] = '1'
-    end
-  end
-
-  def user_setup
-    # Check the settings cache for each request
-    Setting.check_cache
-    # Find the current user
-    User.current = find_current_user
-    logger.info("  Current user: " + (User.current.logged? ? "#{User.current.login} (id=#{User.current.id})" : "anonymous")) if logger
-  end
-
-  # Returns the current user or nil if no user is logged in
-  # and starts a session if needed
-  def find_current_user
-    user = nil
-    unless api_request?
-      if session[:user_id]
-        # existing session
-        user = (User.active.find(session[:user_id]) rescue nil)
-      elsif autologin_user = try_to_autologin
-        user = autologin_user
-      elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
-        # RSS key authentication does not start a session
-        user = User.find_by_rss_key(params[:key])
-      end
-    end
-    if user.nil? && Setting.rest_api_enabled? && accept_api_auth?
-      if (key = api_key_from_request)
-        # Use API key
-        user = User.find_by_api_key(key)
-      else
-        # HTTP Basic, either username/password or API key/random
-        authenticate_with_http_basic do |username, password|
-          user = User.try_to_login(username, password) || User.find_by_api_key(username)
-        end
-        if user && user.must_change_password?
-          render_error :message => 'You must change your password', :status => 403
-          return
-        end
-      end
-      # Switch user if requested by an admin user
-      if user && user.admin? && (username = api_switch_user_from_request)
-        su = User.find_by_login(username)
-        if su && su.active?
-          logger.info("  User switched by: #{user.login} (id=#{user.id})") if logger
-          user = su
-        else
-          render_error :message => 'Invalid X-Redmine-Switch-User header', :status => 412
-        end
-      end
-    end
-    user
-  end
-
-  def autologin_cookie_name
-    Redmine::Configuration['autologin_cookie_name'].presence || 'autologin'
-  end
-
-  def try_to_autologin
-    if cookies[autologin_cookie_name] && Setting.autologin?
-      # auto-login feature starts a new session
-      user = User.try_to_autologin(cookies[autologin_cookie_name])
-      if user
-        reset_session
-        start_user_session(user)
-      end
-      user
-    end
-  end
-
-  # Sets the logged in user
-  def logged_user=(user)
-    reset_session
-    if user && user.is_a?(User)
-      User.current = user
-      start_user_session(user)
-    else
-      User.current = User.anonymous
-    end
-  end
-
-  # Logs out current user
-  def logout_user
-    if User.current.logged?
-      cookies.delete(autologin_cookie_name)
-      Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin'])
-      self.logged_user = nil
-    end
-  end
-
-  # check if login is globally required to access the application
-  def check_if_login_required
-    # no check needed if user is already logged in
-    return true if User.current.logged?
-    require_login if Setting.login_required?
-  end
-
-  def check_password_change
-    if session[:pwd]
-      if User.current.must_change_password?
-        redirect_to my_password_path
-      else
-        session.delete(:pwd)
-      end
-    end
-  end
-
-  def set_localization
-    lang = nil
-    if User.current.logged?
-      lang = find_language(User.current.language)
-    end
-    if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
-      accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first
-      if !accept_lang.blank?
-        accept_lang = accept_lang.downcase
-        lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
-      end
-    end
-    lang ||= Setting.default_language
-    set_language_if_valid(lang)
-  end
-
-  def require_login
-    if !User.current.logged?
-      # Extract only the basic url parameters on non-GET requests
-      if request.get?
-        url = url_for(params)
-      else
-        url = url_for(:controller => params[:controller], :action => params[:action], :id => params[:id], :project_id => params[:project_id])
-      end
-      respond_to do |format|
-        format.html {
-          if request.xhr?
-            head :unauthorized
-          else
-            redirect_to :controller => "account", :action => "login", :back_url => url
-          end
-        }
-        format.atom { redirect_to :controller => "account", :action => "login", :back_url => url }
-        format.xml  { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
-        format.js   { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
-        format.json { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
-      end
-      return false
-    end
-    true
-  end
-
-  def require_admin
-    return unless require_login
-    if !User.current.admin?
-      render_403
-      return false
-    end
-    true
-  end
-
-  def deny_access
-    User.current.logged? ? render_403 : require_login
-  end
-
-  # Authorize the user for the requested action
-  def authorize(ctrl = params[:controller], action = params[:action], global = false)
-    allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global)
-    if allowed
-      true
-    else
-      if @project && @project.archived?
-        render_403 :message => :notice_not_authorized_archived_project
-      else
-        deny_access
-      end
-    end
-  end
-
-  # Authorize the user for the requested action outside a project
-  def authorize_global(ctrl = params[:controller], action = params[:action], global = true)
-    authorize(ctrl, action, global)
-  end
-
-  # Find project of id params[:id]
-  def find_project
-    @project = Project.find(params[:id])
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  # Find project of id params[:project_id]
-  def find_project_by_project_id
-    @project = Project.find(params[:project_id])
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  # Find a project based on params[:project_id]
-  # TODO: some subclasses override this, see about merging their logic
-  def find_optional_project
-    @project = Project.find(params[:project_id]) unless params[:project_id].blank?
-    allowed = User.current.allowed_to?({:controller => params[:controller], :action => params[:action]}, @project, :global => true)
-    allowed ? true : deny_access
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  # Finds and sets @project based on @object.project
-  def find_project_from_association
-    render_404 unless @object.present?
-
-    @project = @object.project
-  end
-
-  def find_model_object
-    model = self.class.model_object
-    if model
-      @object = model.find(params[:id])
-      self.instance_variable_set('@' + controller_name.singularize, @object) if @object
-    end
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def self.model_object(model)
-    self.model_object = model
-  end
-
-  # Find the issue whose id is the :id parameter
-  # Raises a Unauthorized exception if the issue is not visible
-  def find_issue
-    # Issue.visible.find(...) can not be used to redirect user to the login form
-    # if the issue actually exists but requires authentication
-    @issue = Issue.find(params[:id])
-    raise Unauthorized unless @issue.visible?
-    @project = @issue.project
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  # Find issues with a single :id param or :ids array param
-  # Raises a Unauthorized exception if one of the issues is not visible
-  def find_issues
-    @issues = Issue.where(:id => (params[:id] || params[:ids])).preload(:project, :status, :tracker, :priority, :author, :assigned_to, :relations_to).to_a
-    raise ActiveRecord::RecordNotFound if @issues.empty?
-    raise Unauthorized unless @issues.all?(&:visible?)
-    @projects = @issues.collect(&:project).compact.uniq
-    @project = @projects.first if @projects.size == 1
-  rescue ActiveRecord::RecordNotFound
-    render_404
-  end
-
-  def find_attachments
-    if (attachments = params[:attachments]).present?
-      att = attachments.values.collect do |attachment|
-        Attachment.find_by_token( attachment[:token] ) if attachment[:token].present?
-      end
-      att.compact!
-    end
-    @attachments = att || []
-  end
-
-  # make sure that the user is a member of the project (or admin) if project is private
-  # used as a before_filter for actions that do not require any particular permission on the project
-  def check_project_privacy
-    if @project && !@project.archived?
-      if @project.visible?
-        true
-      else
-        deny_access
-      end
-    else
-      @project = nil
-      render_404
-      false
-    end
-  end
-
-  def back_url
-    url = params[:back_url]
-    if url.nil? && referer = request.env['HTTP_REFERER']
-      url = CGI.unescape(referer.to_s)
-    end
-    url
-  end
-
-  def redirect_back_or_default(default)
-    back_url = params[:back_url].to_s
-    if back_url.present?
-      begin
-        uri = URI.parse(back_url)
-        # do not redirect user to another host or to the login or register page
-        if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
-          redirect_to(back_url)
-          return
-        end
-      rescue URI::InvalidURIError
-        logger.warn("Could not redirect to invalid URL #{back_url}")
-        # redirect to default
-      end
-    end
-    redirect_to default
-    false
-  end
-
-  # Redirects to the request referer if present, redirects to args or call block otherwise.
-  def redirect_to_referer_or(*args, &block)
-    redirect_to :back
-  rescue ::ActionController::RedirectBackError
-    if args.any?
-      redirect_to *args
-    elsif block_given?
-      block.call
-    else
-      raise "#redirect_to_referer_or takes arguments or a block"
-    end
-  end
-
-  def render_403(options={})
-    @project = nil
-    render_error({:message => :notice_not_authorized, :status => 403}.merge(options))
-    return false
-  end
-
-  def render_404(options={})
-    render_error({:message => :notice_file_not_found, :status => 404}.merge(options))
-    return false
-  end
-
-  # Renders an error response
-  def render_error(arg)
-    arg = {:message => arg} unless arg.is_a?(Hash)
-
-    @message = arg[:message]
-    @message = l(@message) if @message.is_a?(Symbol)
-    @status = arg[:status] || 500
-
-    respond_to do |format|
-      format.html {
-        render :template => 'common/error', :layout => use_layout, :status => @status
-      }
-      format.any { head @status }
-    end
-  end
-
-  # Handler for ActionView::MissingTemplate exception
-  def missing_template
-    logger.warn "Missing template, responding with 404"
-    @project = nil
-    render_404
-  end
-
-  # Filter for actions that provide an API response
-  # but have no HTML representation for non admin users
-  def require_admin_or_api_request
-    return true if api_request?
-    if User.current.admin?
-      true
-    elsif User.current.logged?
-      render_error(:status => 406)
-    else
-      deny_access
-    end
-  end
-
-  # Picks which layout to use based on the request
-  #
-  # @return [boolean, string] name of the layout to use or false for no layout
-  def use_layout
-    request.xhr? ? false : 'base'
-  end
-
-  def render_feed(items, options={})
-    @items = items || []
-    @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
-    @items = @items.slice(0, Setting.feeds_limit.to_i)
-    @title = options[:title] || Setting.app_title
-    render :template => "common/feed", :formats => [:atom], :layout => false,
-           :content_type => 'application/atom+xml'
-  end
-
-  def self.accept_rss_auth(*actions)
-    if actions.any?
-      self.accept_rss_auth_actions = actions
-    else
-      self.accept_rss_auth_actions || []
-    end
-  end
-
-  def accept_rss_auth?(action=action_name)
-    self.class.accept_rss_auth.include?(action.to_sym)
-  end
-
-  def self.accept_api_auth(*actions)
-    if actions.any?
-      self.accept_api_auth_actions = actions
-    else
-      self.accept_api_auth_actions || []
-    end
-  end
-
-  def accept_api_auth?(action=action_name)
-    self.class.accept_api_auth.include?(action.to_sym)
-  end
-
-  # Returns the number of objects that should be displayed
-  # on the paginated list
-  def per_page_option
-    per_page = nil
-    if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i)
-      per_page = params[:per_page].to_s.to_i
-      session[:per_page] = per_page
-    elsif session[:per_page]
-      per_page = session[:per_page]
-    else
-      per_page = Setting.per_page_options_array.first || 25
-    end
-    per_page
-  end
-
-  # Returns offset and limit used to retrieve objects
-  # for an API response based on offset, limit and page parameters
-  def api_offset_and_limit(options=params)
-    if options[:offset].present?
-      offset = options[:offset].to_i
-      if offset < 0
-        offset = 0
-      end
-    end
-    limit = options[:limit].to_i
-    if limit < 1
-      limit = 25
-    elsif limit > 100
-      limit = 100
-    end
-    if offset.nil? && options[:page].present?
-      offset = (options[:page].to_i - 1) * limit
-      offset = 0 if offset < 0
-    end
-    offset ||= 0
-
-    [offset, limit]
-  end
-
-  # qvalues http header parser
-  # code taken from webrick
-  def parse_qvalues(value)
-    tmp = []
-    if value
-      parts = value.split(/,\s*/)
-      parts.each {|part|
-        if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
-          val = m[1]
-          q = (m[2] or 1).to_f
-          tmp.push([val, q])
-        end
-      }
-      tmp = tmp.sort_by{|val, q| -q}
-      tmp.collect!{|val, q| val}
-    end
-    return tmp
-  rescue
-    nil
-  end
-
-  # Returns a string that can be used as filename value in Content-Disposition header
-  def filename_for_content_disposition(name)
-    request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
-  end
-
-  def api_request?
-    %w(xml json).include? params[:format]
-  end
-
-  # Returns the API key present in the request
-  def api_key_from_request
-    if params[:key].present?
-      params[:key].to_s
-    elsif request.headers["X-Redmine-API-Key"].present?
-      request.headers["X-Redmine-API-Key"].to_s
-    end
-  end
-
-  # Returns the API 'switch user' value if present
-  def api_switch_user_from_request
-    request.headers["X-Redmine-Switch-User"].to_s.presence
-  end
-
-  # Renders a warning flash if obj has unsaved attachments
-  def render_attachment_warning_if_needed(obj)
-    flash[:warning] = l(:warning_attachments_not_saved, obj.unsaved_attachments.size) if obj.unsaved_attachments.present?
-  end
-
-  # Rescues an invalid query statement. Just in case...
-  def query_statement_invalid(exception)
-    logger.error "Query::StatementInvalid: #{exception.message}" if logger
-    session.delete(:query)
-    sort_clear if respond_to?(:sort_clear)
-    render_error "An error occurred while executing the query and has been logged. Please report this error to your Redmine administrator."
-  end
-
-  # Renders a 200 response for successfull updates or deletions via the API
-  def render_api_ok
-    render_api_head :ok
-  end
-
-  # Renders a head API response
-  def render_api_head(status)
-    # #head would return a response body with one space
-    render :text => '', :status => status, :layout => nil
-  end
-
-  # Renders API response on validation failure
-  def render_validation_errors(objects)
-    if objects.is_a?(Array)
-      @error_messages = objects.map {|object| object.errors.full_messages}.flatten
-    else
-      @error_messages = objects.errors.full_messages
-    end
-    render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => nil
-  end
-
-  # Overrides #_include_layout? so that #render with no arguments
-  # doesn't use the layout for api requests
-  def _include_layout?(*args)
-    api_request? ? false : super
-  end
-end
--- a/.svn/pristine/ff/ff099fd1cfab1c76b1d3707b9f9509ca80e11c2a.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3967 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class IssuesControllerTest < ActionController::TestCase
-  fixtures :projects,
-           :users,
-           :roles,
-           :members,
-           :member_roles,
-           :issues,
-           :issue_statuses,
-           :versions,
-           :trackers,
-           :projects_trackers,
-           :issue_categories,
-           :enabled_modules,
-           :enumerations,
-           :attachments,
-           :workflows,
-           :custom_fields,
-           :custom_values,
-           :custom_fields_projects,
-           :custom_fields_trackers,
-           :time_entries,
-           :journals,
-           :journal_details,
-           :queries,
-           :repositories,
-           :changesets
-
-  include Redmine::I18n
-
-  def setup
-    User.current = nil
-  end
-
-  def test_index
-    with_settings :default_language => "en" do
-      get :index
-      assert_response :success
-      assert_template 'index'
-      assert_not_nil assigns(:issues)
-      assert_nil assigns(:project)
-
-      # links to visible issues
-      assert_select 'a[href=/issues/1]', :text => /Can&#x27;t print recipes/
-      assert_select 'a[href=/issues/5]', :text => /Subproject issue/
-      # private projects hidden
-      assert_select 'a[href=/issues/6]', 0
-      assert_select 'a[href=/issues/4]', 0
-      # project column
-      assert_select 'th', :text => /Project/
-    end
-  end
-
-  def test_index_should_not_list_issues_when_module_disabled
-    EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
-    get :index
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-    assert_nil assigns(:project)
-
-    assert_select 'a[href=/issues/1]', 0
-    assert_select 'a[href=/issues/5]', :text => /Subproject issue/
-  end
-
-  def test_index_should_list_visible_issues_only
-    get :index, :per_page => 100
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert_nil assigns(:issues).detect {|issue| !issue.visible?}
-  end
-
-  def test_index_with_project
-    Setting.display_subprojects_issues = 0
-    get :index, :project_id => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-
-    assert_select 'a[href=/issues/1]', :text => /Can&#x27;t print recipes/
-    assert_select 'a[href=/issues/5]', 0
-  end
-
-  def test_index_with_project_and_subprojects
-    Setting.display_subprojects_issues = 1
-    get :index, :project_id => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-
-    assert_select 'a[href=/issues/1]', :text => /Can&#x27;t print recipes/
-    assert_select 'a[href=/issues/5]', :text => /Subproject issue/
-    assert_select 'a[href=/issues/6]', 0
-  end
-
-  def test_index_with_project_and_subprojects_should_show_private_subprojects_with_permission
-    @request.session[:user_id] = 2
-    Setting.display_subprojects_issues = 1
-    get :index, :project_id => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-
-    assert_select 'a[href=/issues/1]', :text => /Can&#x27;t print recipes/
-    assert_select 'a[href=/issues/5]', :text => /Subproject issue/
-    assert_select 'a[href=/issues/6]', :text => /Issue of a private subproject/
-  end
-
-  def test_index_with_project_and_default_filter
-    get :index, :project_id => 1, :set_filter => 1
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-
-    query = assigns(:query)
-    assert_not_nil query
-    # default filter
-    assert_equal({'status_id' => {:operator => 'o', :values => ['']}}, query.filters)
-  end
-
-  def test_index_with_project_and_filter
-    get :index, :project_id => 1, :set_filter => 1,
-      :f => ['tracker_id'],
-      :op => {'tracker_id' => '='},
-      :v => {'tracker_id' => ['1']}
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-
-    query = assigns(:query)
-    assert_not_nil query
-    assert_equal({'tracker_id' => {:operator => '=', :values => ['1']}}, query.filters)
-  end
-
-  def test_index_with_short_filters
-    to_test = {
-      'status_id' => {
-        'o' => { :op => 'o', :values => [''] },
-        'c' => { :op => 'c', :values => [''] },
-        '7' => { :op => '=', :values => ['7'] },
-        '7|3|4' => { :op => '=', :values => ['7', '3', '4'] },
-        '=7' => { :op => '=', :values => ['7'] },
-        '!3' => { :op => '!', :values => ['3'] },
-        '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }},
-      'subject' => {
-        'This is a subject' => { :op => '=', :values => ['This is a subject'] },
-        'o' => { :op => '=', :values => ['o'] },
-        '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] },
-        '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }},
-      'tracker_id' => {
-        '3' => { :op => '=', :values => ['3'] },
-        '=3' => { :op => '=', :values => ['3'] }},
-      'start_date' => {
-        '2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
-        '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
-        '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
-        '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] },
-        '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] },
-        '<t+2' => { :op => '<t+', :values => ['2'] },
-        '>t+2' => { :op => '>t+', :values => ['2'] },
-        't+2' => { :op => 't+', :values => ['2'] },
-        't' => { :op => 't', :values => [''] },
-        'w' => { :op => 'w', :values => [''] },
-        '>t-2' => { :op => '>t-', :values => ['2'] },
-        '<t-2' => { :op => '<t-', :values => ['2'] },
-        't-2' => { :op => 't-', :values => ['2'] }},
-      'created_on' => {
-        '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
-        '<t-2' => { :op => '<t-', :values => ['2'] },
-        '>t-2' => { :op => '>t-', :values => ['2'] },
-        't-2' => { :op => 't-', :values => ['2'] }},
-      'cf_1' => {
-        'c' => { :op => '=', :values => ['c'] },
-        '!c' => { :op => '!', :values => ['c'] },
-        '!*' => { :op => '!*', :values => [''] },
-        '*' => { :op => '*', :values => [''] }},
-      'estimated_hours' => {
-        '=13.4' => { :op => '=', :values => ['13.4'] },
-        '>=45' => { :op => '>=', :values => ['45'] },
-        '<=125' => { :op => '<=', :values => ['125'] },
-        '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] },
-        '!*' => { :op => '!*', :values => [''] },
-        '*' => { :op => '*', :values => [''] }}
-    }
-
-    default_filter = { 'status_id' => {:operator => 'o', :values => [''] }}
-
-    to_test.each do |field, expression_and_expected|
-      expression_and_expected.each do |filter_expression, expected|
-
-        get :index, :set_filter => 1, field => filter_expression
-
-        assert_response :success
-        assert_template 'index'
-        assert_not_nil assigns(:issues)
-
-        query = assigns(:query)
-        assert_not_nil query
-        assert query.has_filter?(field)
-        assert_equal(default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}}), query.filters)
-      end
-    end
-  end
-
-  def test_index_with_project_and_empty_filters
-    get :index, :project_id => 1, :set_filter => 1, :fields => ['']
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-
-    query = assigns(:query)
-    assert_not_nil query
-    # no filter
-    assert_equal({}, query.filters)
-  end
-
-  def test_index_with_project_custom_field_filter
-    field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
-    CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
-    CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
-    filter_name = "project.cf_#{field.id}"
-    @request.session[:user_id] = 1
-
-    get :index, :set_filter => 1,
-      :f => [filter_name],
-      :op => {filter_name => '='},
-      :v => {filter_name => ['Foo']}
-    assert_response :success
-    assert_template 'index'
-    assert_equal [3, 5], assigns(:issues).map(&:project_id).uniq.sort
-  end
-
-  def test_index_with_query
-    get :index, :project_id => 1, :query_id => 5
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-    assert_nil assigns(:issue_count_by_group)
-  end
-
-  def test_index_with_query_grouped_by_tracker
-    get :index, :project_id => 1, :query_id => 6
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-    assert_not_nil assigns(:issue_count_by_group)
-  end
-
-  def test_index_with_query_grouped_by_list_custom_field
-    get :index, :project_id => 1, :query_id => 9
-    assert_response :success
-    assert_template 'index'
-    assert_not_nil assigns(:issues)
-    assert_not_nil assigns(:issue_count_by_group)
-  end
-
-  def test_index_with_query_grouped_by_user_custom_field
-    cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
-
-    get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
-    assert_response :success
-
-    assert_select 'tr.group', 3
-    assert_select 'tr.group' do
-      assert_select 'a', :text => 'John Smith'
-      assert_select 'span.count', :text => '1'
-    end
-    assert_select 'tr.group' do
-      assert_select 'a', :text => 'Dave Lopper'
-      assert_select 'span.count', :text => '2'
-    end
-  end
-
-  def test_index_with_query_grouped_by_tracker_in_normal_order
-    3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
-
-    get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc'
-    assert_response :success
-
-    trackers = assigns(:issues).map(&:tracker).uniq
-    assert_equal [1, 2, 3], trackers.map(&:id)
-  end
-
-  def test_index_with_query_grouped_by_tracker_in_reverse_order
-    3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
-
-    get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc,tracker:desc'
-    assert_response :success
-
-    trackers = assigns(:issues).map(&:tracker).uniq
-    assert_equal [3, 2, 1], trackers.map(&:id)
-  end
-
-  def test_index_with_query_id_and_project_id_should_set_session_query
-    get :index, :project_id => 1, :query_id => 4
-    assert_response :success
-    assert_kind_of Hash, session[:query]
-    assert_equal 4, session[:query][:id]
-    assert_equal 1, session[:query][:project_id]
-  end
-
-  def test_index_with_invalid_query_id_should_respond_404
-    get :index, :project_id => 1, :query_id => 999
-    assert_response 404
-  end
-
-  def test_index_with_cross_project_query_in_session_should_show_project_issues
-    q = IssueQuery.create!(:name => "test", :user_id => 2, :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
-    @request.session[:query] = {:id => q.id, :project_id => 1}
-
-    with_settings :display_subprojects_issues => '0' do
-      get :index, :project_id => 1
-    end
-    assert_response :success
-    assert_not_nil assigns(:query)
-    assert_equal q.id, assigns(:query).id
-    assert_equal 1, assigns(:query).project_id
-    assert_equal [1], assigns(:issues).map(&:project_id).uniq
-  end
-
-  def test_private_query_should_not_be_available_to_other_users
-    q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
-    @request.session[:user_id] = 3
-
-    get :index, :query_id => q.id
-    assert_response 403
-  end
-
-  def test_private_query_should_be_available_to_its_user
-    q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
-    @request.session[:user_id] = 2
-
-    get :index, :query_id => q.id
-    assert_response :success
-  end
-
-  def test_public_query_should_be_available_to_other_users
-    q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PUBLIC, :project => nil)
-    @request.session[:user_id] = 3
-
-    get :index, :query_id => q.id
-    assert_response :success
-  end
-
-  def test_index_should_omit_page_param_in_export_links
-    get :index, :page => 2
-    assert_response :success
-    assert_select 'a.atom[href=/issues.atom]'
-    assert_select 'a.csv[href=/issues.csv]'
-    assert_select 'a.pdf[href=/issues.pdf]'
-    assert_select 'form#csv-export-form[action=/issues.csv]'
-  end
-
-  def test_index_csv
-    get :index, :format => 'csv'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert_equal 'text/csv; header=present', @response.content_type
-    assert @response.body.starts_with?("#,")
-    lines = @response.body.chomp.split("\n")
-    assert_equal assigns(:query).columns.size, lines[0].split(',').size
-  end
-
-  def test_index_csv_with_project
-    get :index, :project_id => 1, :format => 'csv'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert_equal 'text/csv; header=present', @response.content_type
-  end
-
-  def test_index_csv_with_description
-    Issue.generate!(:description => 'test_index_csv_with_description')
-
-    with_settings :default_language => 'en' do
-      get :index, :format => 'csv', :description => '1'
-      assert_response :success
-      assert_not_nil assigns(:issues)
-    end
-
-    assert_equal 'text/csv; header=present', response.content_type
-    headers = response.body.chomp.split("\n").first.split(',')
-    assert_include 'Description', headers
-    assert_include 'test_index_csv_with_description', response.body
-  end
-
-  def test_index_csv_with_spent_time_column
-    issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column', :author_id => 2)
-    TimeEntry.create!(:project => issue.project, :issue => issue, :hours => 7.33, :user => User.find(2), :spent_on => Date.today)
-
-    get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
-    assert_response :success
-    assert_equal 'text/csv; header=present', @response.content_type
-    lines = @response.body.chomp.split("\n")
-    assert_include "#{issue.id},#{issue.subject},7.33", lines
-  end
-
-  def test_index_csv_with_all_columns
-    get :index, :format => 'csv', :columns => 'all'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert_equal 'text/csv; header=present', @response.content_type
-    assert_match /\A#,/, response.body
-    lines = response.body.chomp.split("\n")
-    assert_equal assigns(:query).available_inline_columns.size, lines[0].split(',').size
-  end
-
-  def test_index_csv_with_multi_column_field
-    CustomField.find(1).update_attribute :multiple, true
-    issue = Issue.find(1)
-    issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
-    issue.save!
-
-    get :index, :format => 'csv', :columns => 'all'
-    assert_response :success
-    lines = @response.body.chomp.split("\n")
-    assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
-  end
-
-  def test_index_csv_should_format_float_custom_fields_with_csv_decimal_separator
-    field = IssueCustomField.create!(:name => 'Float', :is_for_all => true, :tracker_ids => [1], :field_format => 'float')
-    issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id => '185.6'})
-
-    with_settings :default_language => 'fr' do
-      get :index, :format => 'csv', :columns => 'all'
-      assert_response :success
-      issue_line = response.body.chomp.split("\n").map {|line| line.split(';')}.detect {|line| line[0]==issue.id.to_s}
-      assert_include '185,60', issue_line
-    end
-
-    with_settings :default_language => 'en' do
-      get :index, :format => 'csv', :columns => 'all'
-      assert_response :success
-      issue_line = response.body.chomp.split("\n").map {|line| line.split(',')}.detect {|line| line[0]==issue.id.to_s}
-      assert_include '185.60', issue_line
-    end
-  end
-
-  def test_index_csv_big_5
-    with_settings :default_language => "zh-TW" do
-      str_utf8  = "\xe4\xb8\x80\xe6\x9c\x88"
-      str_big5  = "\xa4@\xa4\xeb"
-      if str_utf8.respond_to?(:force_encoding)
-        str_utf8.force_encoding('UTF-8')
-        str_big5.force_encoding('Big5')
-      end
-      issue = Issue.generate!(:subject => str_utf8)
-
-      get :index, :project_id => 1, 
-                  :f => ['subject'], 
-                  :op => '=', :values => [str_utf8],
-                  :format => 'csv'
-      assert_equal 'text/csv; header=present', @response.content_type
-      lines = @response.body.chomp.split("\n")
-      s1 = "\xaa\xac\xbaA"
-      if str_utf8.respond_to?(:force_encoding)
-        s1.force_encoding('Big5')
-      end
-      assert_include s1, lines[0]
-      assert_include str_big5, lines[1]
-    end
-  end
-
-  def test_index_csv_cannot_convert_should_be_replaced_big_5
-    with_settings :default_language => "zh-TW" do
-      str_utf8  = "\xe4\xbb\xa5\xe5\x86\x85"
-      if str_utf8.respond_to?(:force_encoding)
-        str_utf8.force_encoding('UTF-8')
-      end
-      issue = Issue.generate!(:subject => str_utf8)
-
-      get :index, :project_id => 1, 
-                  :f => ['subject'], 
-                  :op => '=', :values => [str_utf8],
-                  :c => ['status', 'subject'],
-                  :format => 'csv',
-                  :set_filter => 1
-      assert_equal 'text/csv; header=present', @response.content_type
-      lines = @response.body.chomp.split("\n")
-      s1 = "\xaa\xac\xbaA" # status
-      if str_utf8.respond_to?(:force_encoding)
-        s1.force_encoding('Big5')
-      end
-      assert lines[0].include?(s1)
-      s2 = lines[1].split(",")[2]
-      if s1.respond_to?(:force_encoding)
-        s3 = "\xa5H?" # subject
-        s3.force_encoding('Big5')
-        assert_equal s3, s2
-      elsif RUBY_PLATFORM == 'java'
-        assert_equal "??", s2
-      else
-        assert_equal "\xa5H???", s2
-      end
-    end
-  end
-
-  def test_index_csv_tw
-    with_settings :default_language => "zh-TW" do
-      str1  = "test_index_csv_tw"
-      issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
-
-      get :index, :project_id => 1, 
-                  :f => ['subject'], 
-                  :op => '=', :values => [str1],
-                  :c => ['estimated_hours', 'subject'],
-                  :format => 'csv',
-                  :set_filter => 1
-      assert_equal 'text/csv; header=present', @response.content_type
-      lines = @response.body.chomp.split("\n")
-      assert_equal "#{issue.id},1234.50,#{str1}", lines[1]
-    end
-  end
-
-  def test_index_csv_fr
-    with_settings :default_language => "fr" do
-      str1  = "test_index_csv_fr"
-      issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
-
-      get :index, :project_id => 1, 
-                  :f => ['subject'], 
-                  :op => '=', :values => [str1],
-                  :c => ['estimated_hours', 'subject'],
-                  :format => 'csv',
-                  :set_filter => 1
-      assert_equal 'text/csv; header=present', @response.content_type
-      lines = @response.body.chomp.split("\n")
-      assert_equal "#{issue.id};1234,50;#{str1}", lines[1]
-    end
-  end
-
-  def test_index_pdf
-    ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
-      with_settings :default_language => lang do
-
-        get :index
-        assert_response :success
-        assert_template 'index'
-
-        if lang == "ja"
-          if RUBY_PLATFORM != 'java'
-            assert_equal "CP932", l(:general_pdf_encoding)
-          end
-          if RUBY_PLATFORM == 'java' && l(:general_pdf_encoding) == "CP932"
-            next
-          end
-        end
-
-        get :index, :format => 'pdf'
-        assert_response :success
-        assert_not_nil assigns(:issues)
-        assert_equal 'application/pdf', @response.content_type
-
-        get :index, :project_id => 1, :format => 'pdf'
-        assert_response :success
-        assert_not_nil assigns(:issues)
-        assert_equal 'application/pdf', @response.content_type
-
-        get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
-        assert_response :success
-        assert_not_nil assigns(:issues)
-        assert_equal 'application/pdf', @response.content_type
-      end
-    end
-  end
-
-  def test_index_pdf_with_query_grouped_by_list_custom_field
-    get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
-    assert_response :success
-    assert_not_nil assigns(:issues)
-    assert_not_nil assigns(:issue_count_by_group)
-    assert_equal 'application/pdf', @response.content_type
-  end
-
-  def test_index_atom
-    get :index, :project_id => 'ecookbook', :format => 'atom'
-    assert_response :success
-    assert_template 'common/feed'
-    assert_equal 'application/atom+xml', response.content_type
-
-    assert_select 'feed' do
-      assert_select 'link[rel=self][href=?]', 'http://test.host/projects/ecookbook/issues.atom'
-      assert_select 'link[rel=alternate][href=?]', 'http://test.host/projects/ecookbook/issues'
-      assert_select 'entry link[href=?]', 'http://test.host/issues/1'
-    end
-  end
-
-  def test_index_sort
-    get :index, :sort => 'tracker,id:desc'
-    assert_response :success
-
-    sort_params = @request.session['issues_index_sort']
-    assert sort_params.is_a?(String)
-    assert_equal 'tracker,id:desc', sort_params
-
-    issues = assigns(:issues)
-    assert_not_nil issues
-    assert !issues.empty?
-    assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
-  end
-
-  def test_index_sort_by_field_not_included_in_columns
-    Setting.issue_list_default_columns = %w(subject author)
-    get :index, :sort => 'tracker'
-  end
-  
-  def test_index_sort_by_assigned_to
-    get :index, :sort => 'assigned_to'
-    assert_response :success
-    assignees = assigns(:issues).collect(&:assigned_to).compact
-    assert_equal assignees.sort, assignees
-  end
-  
-  def test_index_sort_by_assigned_to_desc
-    get :index, :sort => 'assigned_to:desc'
-    assert_response :success
-    assignees = assigns(:issues).collect(&:assigned_to).compact
-    assert_equal assignees.sort.reverse, assignees
-  end
-  
-  def test_index_group_by_assigned_to
-    get :index, :group_by => 'assigned_to', :sort => 'priority'
-    assert_response :success
-  end
-  
-  def test_index_sort_by_author
-    get :index, :sort => 'author'
-    assert_response :success
-    authors = assigns(:issues).collect(&:author)
-    assert_equal authors.sort, authors
-  end
-  
-  def test_index_sort_by_author_desc
-    get :index, :sort => 'author:desc'
-    assert_response :success
-    authors = assigns(:issues).collect(&:author)
-    assert_equal authors.sort.reverse, authors
-  end
-  
-  def test_index_group_by_author
-    get :index, :group_by => 'author', :sort => 'priority'
-    assert_response :success
-  end
-  
-  def test_index_sort_by_spent_hours
-    get :index, :sort => 'spent_hours:desc'
-    assert_response :success
-    hours = assigns(:issues).collect(&:spent_hours)
-    assert_equal hours.sort.reverse, hours
-  end
-
-  def test_index_sort_by_user_custom_field
-    cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
-
-    get :index, :project_id => 1, :set_filter => 1, :sort => "cf_#{cf.id},id"
-    assert_response :success
-
-    assert_equal [2, 3, 1], assigns(:issues).select {|issue| issue.custom_field_value(cf).present?}.map(&:id)
-  end
-
-  def test_index_with_columns
-    columns = ['tracker', 'subject', 'assigned_to']
-    get :index, :set_filter => 1, :c => columns
-    assert_response :success
-
-    # query should use specified columns
-    query = assigns(:query)
-    assert_kind_of IssueQuery, query
-    assert_equal columns, query.column_names.map(&:to_s)
-
-    # columns should be stored in session
-    assert_kind_of Hash, session[:query]
-    assert_kind_of Array, session[:query][:column_names]
-    assert_equal columns, session[:query][:column_names].map(&:to_s)
-
-    # ensure only these columns are kept in the selected columns list
-    assert_select 'select#selected_columns option' do
-      assert_select 'option', 3
-      assert_select 'option[value=tracker]'
-      assert_select 'option[value=project]', 0
-    end
-  end
-
-  def test_index_without_project_should_implicitly_add_project_column_to_default_columns
-    Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
-    get :index, :set_filter => 1
-
-    # query should use specified columns
-    query = assigns(:query)
-    assert_kind_of IssueQuery, query
-    assert_equal [:id, :project, :tracker, :subject, :assigned_to], query.columns.map(&:name)
-  end
-
-  def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
-    Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
-    columns = ['id', 'tracker', 'subject', 'assigned_to']
-    get :index, :set_filter => 1, :c => columns
-
-    # query should use specified columns
-    query = assigns(:query)
-    assert_kind_of IssueQuery, query
-    assert_equal columns.map(&:to_sym), query.columns.map(&:name)
-  end
-
-  def test_index_with_custom_field_column
-    columns = %w(tracker subject cf_2)
-    get :index, :set_filter => 1, :c => columns
-    assert_response :success
-
-    # query should use specified columns
-    query = assigns(:query)
-    assert_kind_of IssueQuery, query
-    assert_equal columns, query.column_names.map(&:to_s)
-
-    assert_select 'table.issues td.cf_2.string'
-  end
-
-  def test_index_with_multi_custom_field_column
-    field = CustomField.find(1)
-    field.update_attribute :multiple, true
-    issue = Issue.find(1)
-    issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
-    issue.save!
-
-    get :index, :set_filter => 1, :c => %w(tracker subject cf_1)
-    assert_response :success
-
-    assert_select 'table.issues td.cf_1', :text => 'MySQL, Oracle'
-  end
-
-  def test_index_with_multi_user_custom_field_column
-    field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
-      :tracker_ids => [1], :is_for_all => true)
-    issue = Issue.find(1)
-    issue.custom_field_values = {field.id => ['2', '3']}
-    issue.save!
-
-    get :index, :set_filter => 1, :c => ['tracker', 'subject', "cf_#{field.id}"]
-    assert_response :success
-
-    assert_select "table.issues td.cf_#{field.id}" do
-      assert_select 'a', 2
-      assert_select 'a[href=?]', '/users/2', :text => 'John Smith'
-      assert_select 'a[href=?]', '/users/3', :text => 'Dave Lopper'
-    end
-  end
-
-  def test_index_with_date_column
-    with_settings :date_format => '%d/%m/%Y' do
-      Issue.find(1).update_attribute :start_date, '1987-08-24'
-      get :index, :set_filter => 1, :c => %w(start_date)
-      assert_select "table.issues td.start_date", :text => '24/08/1987'
-    end
-  end
-
-  def test_index_with_done_ratio_column
-    Issue.find(1).update_attribute :done_ratio, 40
-    get :index, :set_filter => 1, :c => %w(done_ratio)
-    assert_select 'table.issues td.done_ratio' do
-      assert_select 'table.progress' do
-        assert_select 'td.closed[style=?]', 'width: 40%;'
-      end
-    end
-  end
-
-  def test_index_with_spent_hours_column
-    get :index, :set_filter => 1, :c => %w(subject spent_hours)
-    assert_select 'table.issues tr#issue-3 td.spent_hours', :text => '1.00'
-  end
-
-  def test_index_should_not_show_spent_hours_column_without_permission
-    Role.anonymous.remove_permission! :view_time_entries
-    get :index, :set_filter => 1, :c => %w(subject spent_hours)
-    assert_select 'td.spent_hours', 0
-  end
-
-  def test_index_with_fixed_version_column
-    get :index, :set_filter => 1, :c => %w(fixed_version)
-    assert_select 'table.issues td.fixed_version' do
-      assert_select 'a[href=?]', '/versions/2', :text => '1.0'
-    end
-  end
-
-  def test_index_with_relations_column
-    IssueRelation.delete_all
-    IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(7))
-    IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(8), :issue_to => Issue.find(1))
-    IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(1), :issue_to => Issue.find(11))
-    IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(12), :issue_to => Issue.find(2))
-
-    get :index, :set_filter => 1, :c => %w(subject relations)
-    assert_response :success
-    assert_select "tr#issue-1 td.relations" do
-      assert_select "span", 3
-      assert_select "span", :text => "Related to #7"
-      assert_select "span", :text => "Related to #8"
-      assert_select "span", :text => "Blocks #11"
-    end
-    assert_select "tr#issue-2 td.relations" do
-      assert_select "span", 1
-      assert_select "span", :text => "Blocked by #12"
-    end
-    assert_select "tr#issue-3 td.relations" do
-      assert_select "span", 0
-    end
-
-    get :index, :set_filter => 1, :c => %w(relations), :format => 'csv'
-    assert_response :success
-    assert_equal 'text/csv; header=present', response.content_type
-    lines = response.body.chomp.split("\n")
-    assert_include '1,"Related to #7, Related to #8, Blocks #11"', lines
-    assert_include '2,Blocked by #12', lines
-    assert_include '3,""', lines
-
-    get :index, :set_filter => 1, :c => %w(subject relations), :format => 'pdf'
-    assert_response :success
-    assert_equal 'application/pdf', response.content_type
-  end
-
-  def test_index_with_description_column
-    get :index, :set_filter => 1, :c => %w(subject description)
-
-    assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
-    assert_select 'td.description[colspan=3]', :text => 'Unable to print recipes'
-
-    get :index, :set_filter => 1, :c => %w(subject description), :format => 'pdf'
-    assert_response :success
-    assert_equal 'application/pdf', response.content_type
-  end
-
-  def test_index_send_html_if_query_is_invalid
-    get :index, :f => ['start_date'], :op => {:start_date => '='}
-    assert_equal 'text/html', @response.content_type
-    assert_template 'index'
-  end
-
-  def test_index_send_nothing_if_query_is_invalid
-    get :index, :f => ['start_date'], :op => {:start_date => '='}, :format => 'csv'
-    assert_equal 'text/csv', @response.content_type
-    assert @response.body.blank?
-  end
-
-  def test_show_by_anonymous
-    get :show, :id => 1
-    assert_response :success
-    assert_template 'show'
-    assert_equal Issue.find(1), assigns(:issue)
-    assert_select 'div.issue div.description', :text => /Unable to print recipes/
-    # anonymous role is allowed to add a note
-    assert_select 'form#issue-form' do
-      assert_select 'fieldset' do
-        assert_select 'legend', :text => 'Notes'
-        assert_select 'textarea[name=?]', 'issue[notes]'
-      end
-    end
-    assert_select 'title', :text => "Bug #1: Can&#x27;t print recipes - eCookbook - Redmine"
-  end
-
-  def test_show_by_manager
-    @request.session[:user_id] = 2
-    get :show, :id => 1
-    assert_response :success
-    assert_select 'a', :text => /Quote/
-    assert_select 'form#issue-form' do
-      assert_select 'fieldset' do
-        assert_select 'legend', :text => 'Change properties'
-        assert_select 'input[name=?]', 'issue[subject]'
-      end
-      assert_select 'fieldset' do
-        assert_select 'legend', :text => 'Log time'
-        assert_select 'input[name=?]', 'time_entry[hours]'
-      end
-      assert_select 'fieldset' do
-        assert_select 'legend', :text => 'Notes'
-        assert_select 'textarea[name=?]', 'issue[notes]'
-      end
-    end
-  end
-
-  def test_show_should_display_update_form
-    @request.session[:user_id] = 2
-    get :show, :id => 1
-    assert_response :success
-
-    assert_select 'form#issue-form' do
-      assert_select 'input[name=?]', 'issue[is_private]'
-      assert_select 'select[name=?]', 'issue[project_id]'
-      assert_select 'select[name=?]', 'issue[tracker_id]'
-      assert_select 'input[name=?]', 'issue[subject]'
-      assert_select 'textarea[name=?]', 'issue[description]'
-      assert_select 'select[name=?]', 'issue[status_id]'
-      assert_select 'select[name=?]', 'issue[priority_id]'
-      assert_select 'select[name=?]', 'issue[assigned_to_id]'
-      assert_select 'select[name=?]', 'issue[category_id]'
-      assert_select 'select[name=?]', 'issue[fixed_version_id]'
-      assert_select 'input[name=?]', 'issue[parent_issue_id]'
-      assert_select 'input[name=?]', 'issue[start_date]'
-      assert_select 'input[name=?]', 'issue[due_date]'
-      assert_select 'select[name=?]', 'issue[done_ratio]'
-      assert_select 'input[name=?]', 'issue[custom_field_values][2]'
-      assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
-      assert_select 'textarea[name=?]', 'issue[notes]'
-    end
-  end
-
-  def test_show_should_display_update_form_with_minimal_permissions
-    Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
-    WorkflowTransition.delete_all :role_id => 1
-
-    @request.session[:user_id] = 2
-    get :show, :id => 1
-    assert_response :success
-
-    assert_select 'form#issue-form' do
-      assert_select 'input[name=?]', 'issue[is_private]', 0
-      assert_select 'select[name=?]', 'issue[project_id]', 0
-      assert_select 'select[name=?]', 'issue[tracker_id]', 0
-      assert_select 'input[name=?]', 'issue[subject]', 0
-      assert_select 'textarea[name=?]', 'issue[description]', 0
-      assert_select 'select[name=?]', 'issue[status_id]', 0
-      assert_select 'select[name=?]', 'issue[priority_id]', 0
-      assert_select 'select[name=?]', 'issue[assigned_to_id]', 0
-      assert_select 'select[name=?]', 'issue[category_id]', 0
-      assert_select 'select[name=?]', 'issue[fixed_version_id]', 0
-      assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
-      assert_select 'input[name=?]', 'issue[start_date]', 0
-      assert_select 'input[name=?]', 'issue[due_date]', 0
-      assert_select 'select[name=?]', 'issue[done_ratio]', 0
-      assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
-      assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
-      assert_select 'textarea[name=?]', 'issue[notes]'
-    end
-  end
-
-  def test_show_should_display_update_form_with_workflow_permissions
-    Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
-
-    @request.session[:user_id] = 2
-    get :show, :id => 1
-    assert_response :success
-
-    assert_select 'form#issue-form' do
-      assert_select 'input[name=?]', 'issue[is_private]', 0
-      assert_select 'select[name=?]', 'issue[project_id]', 0
-      assert_select 'select[name=?]', 'issue[tracker_id]', 0
-      assert_select 'input[name=?]', 'issue[subject]', 0
-      assert_select 'textarea[name=?]', 'issue[description]', 0
-      assert_select 'select[name=?]', 'issue[status_id]'
-      assert_select 'select[name=?]', 'issue[priority_id]', 0
-      assert_select 'select[name=?]', 'issue[assigned_to_id]'
-      assert_select 'select[name=?]', 'issue[category_id]', 0
-      assert_select 'select[name=?]', 'issue[fixed_version_id]'
-      assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
-      assert_select 'input[name=?]', 'issue[start_date]', 0
-      assert_select 'input[name=?]', 'issue[due_date]', 0
-      assert_select 'select[name=?]', 'issue[done_ratio]'
-      assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
-      assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
-      assert_select 'textarea[name=?]', 'issue[notes]'
-    end
-  end
-
-  def test_show_should_not_display_update_form_without_permissions
-    Role.find(1).update_attribute :permissions, [:view_issues]
-
-    @request.session[:user_id] = 2
-    get :show, :id => 1
-    assert_response :success
-
-    assert_select 'form#issue-form', 0
-  end
-
-  def test_update_form_should_not_display_inactive_enumerations
-    assert !IssuePriority.find(15).active?
-
-    @request.session[:user_id] = 2
-    get :show, :id => 1
-    assert_response :success
-
-    assert_select 'form#issue-form' do
-      assert_select 'select[name=?]', 'issue[priority_id]' do
-        assert_select 'option[value=4]'
-        assert_select 'option[value=15]', 0
-      end
-    end
-  end
-
-  def test_update_form_should_allow_attachment_upload
-    @request.session[:user_id] = 2
-    get :show, :id => 1
-
-    assert_select 'form#issue-form[method=post][enctype=multipart/form-data]' do
-      assert_select 'input[type=file][name=?]', 'attachments[dummy][file]'
-    end
-  end
-
-  def test_show_should_deny_anonymous_access_without_permission
-    Role.anonymous.remove_permission!(:view_issues)
-    get :show, :id => 1
-    assert_response :redirect
-  end
-
-  def test_show_should_deny_anonymous_access_to_private_issue
-    Issue.update_all(["is_private = ?", true], "id = 1")
-    get :show, :id => 1
-    assert_response :redirect
-  end
-
-  def test_show_should_deny_non_member_access_without_permission
-    Role.non_member.remove_permission!(:view_issues)
-    @request.session[:user_id] = 9
-    get :show, :id => 1
-    assert_response 403
-  end
-
-  def test_show_should_deny_non_member_access_to_private_issue
-    Issue.update_all(["is_private = ?", true], "id = 1")
-    @request.session[:user_id] = 9
-    get :show, :id => 1
-    assert_response 403
-  end
-
-  def test_show_should_deny_member_access_without_permission
-    Role.find(1).remove_permission!(:view_issues)
-    @request.session[:user_id] = 2
-    get :show, :id => 1
-    assert_response 403
-  end
-
-  def test_show_should_deny_member_access_to_private_issue_without_permission
-    Issue.update_all(["is_private = ?", true], "id = 1")
-    @request.session[:user_id] = 3
-    get :show, :id => 1
-    assert_response 403
-  end
-
-  def test_show_should_allow_author_access_to_private_issue
-    Issue.update_all(["is_private = ?, author_id = 3", true], "id = 1")
-    @request.session[:user_id] = 3
-    get :show, :id => 1
-    assert_response :success
-  end
-
-  def test_show_should_allow_assignee_access_to_private_issue
-    Issue.update_all(["is_private = ?, assigned_to_id = 3", true], "id = 1")
-    @request.session[:user_id] = 3
-    get :show, :id => 1
-    assert_response :success
-  end
-
-  def test_show_should_allow_member_access_to_private_issue_with_permission
-    Issue.update_all(["is_private = ?", true], "id = 1")
-    User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
-    @request.session[:user_id] = 3
-    get :show, :id => 1
-    assert_response :success
-  end
-
-  def test_show_should_not_disclose_relations_to_invisible_issues
-    Setting.cross_project_issue_relations = '1'
-    IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
-    # Relation to a private project issue
-    IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
-
-    get :show, :id => 1
-    assert_response :success
-
-    assert_select 'div#relations' do
-      assert_select 'a', :text => /#2$/
-      assert_select 'a', :text => /#4$/, :count => 0
-    end
-  end
-
-  def test_show_should_list_subtasks
-    Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
-
-    get :show, :id => 1
-    assert_response :success
-
-    assert_select 'div#issue_tree' do
-      assert_select 'td.subject', :text => /Child Issue/
-    end
-  end
-
-  def test_show_should_list_parents
-    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
-
-    get :show, :id => issue.id
-    assert_response :success
-
-    assert_select 'div.subject' do
-      assert_select 'h3', 'Child Issue'
-      assert_select 'a[href=/issues/1]'
-    end
-  end
-
-  def test_show_should_not_display_prev_next_links_without_query_in_session
-    get :show, :id => 1
-    assert_response :success
-    assert_nil assigns(:prev_issue_id)
-    assert_nil assigns(:next_issue_id)
-
-    assert_select 'div.next-prev-links', 0
-  end
-
-  def test_show_should_display_prev_next_links_with_query_in_session
-    @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
-    @request.session['issues_index_sort'] = 'id'
-
-    with_settings :display_subprojects_issues => '0' do
-      get :show, :id => 3
-    end
-
-    assert_response :success
-    # Previous and next issues for all projects
-    assert_equal 2, assigns(:prev_issue_id)
-    assert_equal 5, assigns(:next_issue_id)
-
-    count = Issue.open.visible.count
-
-    assert_select 'div.next-prev-links' do
-      assert_select 'a[href=/issues/2]', :text => /Previous/
-      assert_select 'a[href=/issues/5]', :text => /Next/
-      assert_select 'span.position', :text => "3 of #{count}"
-    end
-  end
-
-  def test_show_should_display_prev_next_links_with_saved_query_in_session
-    query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC,  :user_id => 1,
-      :filters => {'status_id' => {:values => ['5'], :operator => '='}},
-      :sort_criteria => [['id', 'asc']])
-    @request.session[:query] = {:id => query.id, :project_id => nil}
-
-    get :show, :id => 11
-
-    assert_response :success
-    assert_equal query, assigns(:query)
-    # Previous and next issues for all projects
-    assert_equal 8, assigns(:prev_issue_id)
-    assert_equal 12, assigns(:next_issue_id)
-
-    assert_select 'div.next-prev-links' do
-      assert_select 'a[href=/issues/8]', :text => /Previous/
-      assert_select 'a[href=/issues/12]', :text => /Next/
-    end
-  end
-
-  def test_show_should_display_prev_next_links_with_query_and_sort_on_association
-    @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
-    
-    %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
-      @request.session['issues_index_sort'] = assoc_sort
-
-      get :show, :id => 3
-      assert_response :success, "Wrong response status for #{assoc_sort} sort"
-
-      assert_select 'div.next-prev-links' do
-        assert_select 'a', :text => /(Previous|Next)/
-      end
-    end
-  end
-
-  def test_show_should_display_prev_next_links_with_project_query_in_session
-    @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
-    @request.session['issues_index_sort'] = 'id'
-
-    with_settings :display_subprojects_issues => '0' do
-      get :show, :id => 3
-    end
-
-    assert_response :success
-    # Previous and next issues inside project
-    assert_equal 2, assigns(:prev_issue_id)
-    assert_equal 7, assigns(:next_issue_id)
-
-    assert_select 'div.next-prev-links' do
-      assert_select 'a[href=/issues/2]', :text => /Previous/
-      assert_select 'a[href=/issues/7]', :text => /Next/
-    end
-  end
-
-  def test_show_should_not_display_prev_link_for_first_issue
-    @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
-    @request.session['issues_index_sort'] = 'id'
-
-    with_settings :display_subprojects_issues => '0' do
-      get :show, :id => 1
-    end
-
-    assert_response :success
-    assert_nil assigns(:prev_issue_id)
-    assert_equal 2, assigns(:next_issue_id)
-
-    assert_select 'div.next-prev-links' do
-      assert_select 'a', :text => /Previous/, :count => 0
-      assert_select 'a[href=/issues/2]', :text => /Next/
-    end
-  end
-
-  def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
-    @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1}
-    @request.session['issues_index_sort'] = 'id'
-
-    get :show, :id => 1
-
-    assert_response :success
-    assert_nil assigns(:prev_issue_id)
-    assert_nil assigns(:next_issue_id)
-
-    assert_select 'a', :text => /Previous/, :count => 0
-    assert_select 'a', :text => /Next/, :count => 0
-  end
-
-  def test_show_show_should_display_prev_next_links_with_query_sort_by_user_custom_field
-    cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
-    CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
-
-    query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC,  :user_id => 1, :filters => {},
-      :sort_criteria => [["cf_#{cf.id}", 'asc'], ['id', 'asc']])
-    @request.session[:query] = {:id => query.id, :project_id => nil}
-
-    get :show, :id => 3
-    assert_response :success
-
-    assert_equal 2, assigns(:prev_issue_id)
-    assert_equal 1, assigns(:next_issue_id)
-
-    assert_select 'div.next-prev-links' do
-      assert_select 'a[href=/issues/2]', :text => /Previous/
-      assert_select 'a[href=/issues/1]', :text => /Next/
-    end
-  end
-
-  def test_show_should_display_link_to_the_assignee
-    get :show, :id => 2
-    assert_response :success
-    assert_select '.assigned-to' do
-      assert_select 'a[href=/users/3]'
-    end
-  end
-
-  def test_show_should_display_visible_changesets_from_other_projects
-    project = Project.find(2)
-    issue = project.issues.first
-    issue.changeset_ids = [102]
-    issue.save!
-    # changesets from other projects should be displayed even if repository
-    # is disabled on issue's project
-    project.disable_module! :repository
-
-    @request.session[:user_id] = 2
-    get :show, :id => issue.id
-
-    assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/3'
-  end
-
-  def test_show_should_display_watchers
-    @request.session[:user_id] = 2
-    Issue.find(1).add_watcher User.find(2)
-
-    get :show, :id => 1
-    assert_select 'div#watchers ul' do
-      assert_select 'li' do
-        assert_select 'a[href=/users/2]'
-        assert_select 'a img[alt=Delete]'
-      end
-    end
-  end
-
-  def test_show_should_display_watchers_with_gravatars
-    @request.session[:user_id] = 2
-    Issue.find(1).add_watcher User.find(2)
-
-    with_settings :gravatar_enabled => '1' do
-      get :show, :id => 1
-    end
-
-    assert_select 'div#watchers ul' do
-      assert_select 'li' do
-        assert_select 'img.gravatar'
-        assert_select 'a[href=/users/2]'
-        assert_select 'a img[alt=Delete]'
-      end
-    end
-  end
-
-  def test_show_with_thumbnails_enabled_should_display_thumbnails
-    @request.session[:user_id] = 2
-
-    with_settings :thumbnails_enabled => '1' do
-      get :show, :id => 14
-      assert_response :success
-    end
-
-    assert_select 'div.thumbnails' do
-      assert_select 'a[href=/attachments/16/testfile.png]' do
-        assert_select 'img[src=/attachments/thumbnail/16]'
-      end
-    end
-  end
-
-  def test_show_with_thumbnails_disabled_should_not_display_thumbnails
-    @request.session[:user_id] = 2
-
-    with_settings :thumbnails_enabled => '0' do
-      get :show, :id => 14
-      assert_response :success
-    end
-
-    assert_select 'div.thumbnails', 0
-  end
-
-  def test_show_with_multi_custom_field
-    field = CustomField.find(1)
-    field.update_attribute :multiple, true
-    issue = Issue.find(1)
-    issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
-    issue.save!
-
-    get :show, :id => 1
-    assert_response :success
-
-    assert_select 'td', :text => 'MySQL, Oracle'
-  end
-
-  def test_show_with_multi_user_custom_field
-    field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
-      :tracker_ids => [1], :is_for_all => true)
-    issue = Issue.find(1)
-    issue.custom_field_values = {field.id => ['2', '3']}
-    issue.save!
-
-    get :show, :id => 1
-    assert_response :success
-
-    # TODO: should display links
-    assert_select 'td', :text => 'Dave Lopper, John Smith'
-  end
-
-  def test_show_should_display_private_notes_with_permission_only
-    journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
-    @request.session[:user_id] = 2
-
-    get :show, :id => 2
-    assert_response :success
-    assert_include journal, assigns(:journals)
-
-    Role.find(1).remove_permission! :view_private_notes
-    get :show, :id => 2
-    assert_response :success
-    assert_not_include journal, assigns(:journals)
-  end
-
-  def test_show_atom
-    get :show, :id => 2, :format => 'atom'
-    assert_response :success
-    assert_template 'journals/index'
-    # Inline image
-    assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
-  end
-
-  def test_show_export_to_pdf
-    get :show, :id => 3, :format => 'pdf'
-    assert_response :success
-    assert_equal 'application/pdf', @response.content_type
-    assert @response.body.starts_with?('%PDF')
-    assert_not_nil assigns(:issue)
-  end
-
-  def test_show_export_to_pdf_with_ancestors
-    issue = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
-
-    get :show, :id => issue.id, :format => 'pdf'
-    assert_response :success
-    assert_equal 'application/pdf', @response.content_type
-    assert @response.body.starts_with?('%PDF')
-  end
-
-  def test_show_export_to_pdf_with_descendants
-    c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
-    c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
-    c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => c1.id)
-
-    get :show, :id => 1, :format => 'pdf'
-    assert_response :success
-    assert_equal 'application/pdf', @response.content_type
-    assert @response.body.starts_with?('%PDF')
-  end
-
-  def test_show_export_to_pdf_with_journals
-    get :show, :id => 1, :format => 'pdf'
-    assert_response :success
-    assert_equal 'application/pdf', @response.content_type
-    assert @response.body.starts_with?('%PDF')
-  end
-
-  def test_show_export_to_pdf_with_changesets
-    Issue.find(3).changesets = Changeset.find_all_by_id(100, 101, 102)
-
-    get :show, :id => 3, :format => 'pdf'
-    assert_response :success
-    assert_equal 'application/pdf', @response.content_type
-    assert @response.body.starts_with?('%PDF')
-  end
-
-  def test_show_invalid_should_respond_with_404
-    get :show, :id => 999
-    assert_response 404
-  end
-
-  def test_get_new
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :tracker_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'form#issue-form' do
-      assert_select 'input[name=?]', 'issue[is_private]'
-      assert_select 'select[name=?]', 'issue[project_id]', 0
-      assert_select 'select[name=?]', 'issue[tracker_id]'
-      assert_select 'input[name=?]', 'issue[subject]'
-      assert_select 'textarea[name=?]', 'issue[description]'
-      assert_select 'select[name=?]', 'issue[status_id]'
-      assert_select 'select[name=?]', 'issue[priority_id]'
-      assert_select 'select[name=?]', 'issue[assigned_to_id]'
-      assert_select 'select[name=?]', 'issue[category_id]'
-      assert_select 'select[name=?]', 'issue[fixed_version_id]'
-      assert_select 'input[name=?]', 'issue[parent_issue_id]'
-      assert_select 'input[name=?]', 'issue[start_date]'
-      assert_select 'input[name=?]', 'issue[due_date]'
-      assert_select 'select[name=?]', 'issue[done_ratio]'
-      assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
-      assert_select 'input[name=?]', 'issue[watcher_user_ids][]'
-    end
-
-    # Be sure we don't display inactive IssuePriorities
-    assert ! IssuePriority.find(15).active?
-    assert_select 'select[name=?]', 'issue[priority_id]' do
-      assert_select 'option[value=15]', 0
-    end
-  end
-
-  def test_get_new_with_minimal_permissions
-    Role.find(1).update_attribute :permissions, [:add_issues]
-    WorkflowTransition.delete_all :role_id => 1
-
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :tracker_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'form#issue-form' do
-      assert_select 'input[name=?]', 'issue[is_private]', 0
-      assert_select 'select[name=?]', 'issue[project_id]', 0
-      assert_select 'select[name=?]', 'issue[tracker_id]'
-      assert_select 'input[name=?]', 'issue[subject]'
-      assert_select 'textarea[name=?]', 'issue[description]'
-      assert_select 'select[name=?]', 'issue[status_id]'
-      assert_select 'select[name=?]', 'issue[priority_id]'
-      assert_select 'select[name=?]', 'issue[assigned_to_id]'
-      assert_select 'select[name=?]', 'issue[category_id]'
-      assert_select 'select[name=?]', 'issue[fixed_version_id]'
-      assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
-      assert_select 'input[name=?]', 'issue[start_date]'
-      assert_select 'input[name=?]', 'issue[due_date]'
-      assert_select 'select[name=?]', 'issue[done_ratio]'
-      assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
-      assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
-    end
-  end
-
-  def test_get_new_with_list_custom_field
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :tracker_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'select.list_cf[name=?]', 'issue[custom_field_values][1]' do
-      assert_select 'option', 4
-      assert_select 'option[value=MySQL]', :text => 'MySQL'
-    end
-  end
-
-  def test_get_new_with_multi_custom_field
-    field = IssueCustomField.find(1)
-    field.update_attribute :multiple, true
-
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :tracker_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
-      assert_select 'option', 3
-      assert_select 'option[value=MySQL]', :text => 'MySQL'
-    end
-    assert_select 'input[name=?][type=hidden][value=?]', 'issue[custom_field_values][1][]', ''
-  end
-
-  def test_get_new_with_multi_user_custom_field
-    field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
-      :tracker_ids => [1], :is_for_all => true)
-
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :tracker_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'select[name=?][multiple=multiple]', "issue[custom_field_values][#{field.id}][]" do
-      assert_select 'option', Project.find(1).users.count
-      assert_select 'option[value=2]', :text => 'John Smith'
-    end
-    assert_select 'input[name=?][type=hidden][value=?]', "issue[custom_field_values][#{field.id}][]", ''
-  end
-
-  def test_get_new_with_date_custom_field
-    field = IssueCustomField.create!(:name => 'Date', :field_format => 'date', :tracker_ids => [1], :is_for_all => true)
-
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :tracker_id => 1
-    assert_response :success
-
-    assert_select 'input[name=?]', "issue[custom_field_values][#{field.id}]"
-  end
-
-  def test_get_new_with_text_custom_field
-    field = IssueCustomField.create!(:name => 'Text', :field_format => 'text', :tracker_ids => [1], :is_for_all => true)
-
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :tracker_id => 1
-    assert_response :success
-
-    assert_select 'textarea[name=?]', "issue[custom_field_values][#{field.id}]"
-  end
-
-  def test_get_new_without_default_start_date_is_creation_date
-    with_settings :default_issue_start_date_to_creation_date  => 0 do
-      @request.session[:user_id] = 2
-      get :new, :project_id => 1, :tracker_id => 1
-      assert_response :success
-      assert_template 'new'
-      assert_select 'input[name=?]', 'issue[start_date]'
-      assert_select 'input[name=?][value]', 'issue[start_date]', 0
-    end
-  end
-
-  def test_get_new_with_default_start_date_is_creation_date
-    with_settings :default_issue_start_date_to_creation_date  => 1 do
-      @request.session[:user_id] = 2
-      get :new, :project_id => 1, :tracker_id => 1
-      assert_response :success
-      assert_template 'new'
-      assert_select 'input[name=?][value=?]', 'issue[start_date]',
-                    Date.today.to_s
-    end
-  end
-
-  def test_get_new_form_should_allow_attachment_upload
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :tracker_id => 1
-
-    assert_select 'form[id=issue-form][method=post][enctype=multipart/form-data]' do
-      assert_select 'input[name=?][type=file]', 'attachments[dummy][file]'
-    end
-  end
-
-  def test_get_new_should_prefill_the_form_from_params
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1,
-      :issue => {:tracker_id => 3, :description => 'Prefilled', :custom_field_values => {'2' => 'Custom field value'}}
-
-    issue = assigns(:issue)
-    assert_equal 3, issue.tracker_id
-    assert_equal 'Prefilled', issue.description
-    assert_equal 'Custom field value', issue.custom_field_value(2)
-
-    assert_select 'select[name=?]', 'issue[tracker_id]' do
-      assert_select 'option[value=3][selected=selected]'
-    end
-    assert_select 'textarea[name=?]', 'issue[description]', :text => /Prefilled/
-    assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Custom field value'
-  end
-
-  def test_get_new_should_mark_required_fields
-    cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
-    cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
-    @request.session[:user_id] = 2
-
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'label[for=issue_start_date]' do
-      assert_select 'span[class=required]', 0
-    end
-    assert_select 'label[for=issue_due_date]' do
-      assert_select 'span[class=required]'
-    end
-    assert_select 'label[for=?]', "issue_custom_field_values_#{cf1.id}" do
-      assert_select 'span[class=required]', 0
-    end
-    assert_select 'label[for=?]', "issue_custom_field_values_#{cf2.id}" do
-      assert_select 'span[class=required]'
-    end
-  end
-
-  def test_get_new_should_not_display_readonly_fields
-    cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
-    cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
-    @request.session[:user_id] = 2
-
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'input[name=?]', 'issue[start_date]'
-    assert_select 'input[name=?]', 'issue[due_date]', 0
-    assert_select 'input[name=?]', "issue[custom_field_values][#{cf1.id}]"
-    assert_select 'input[name=?]', "issue[custom_field_values][#{cf2.id}]", 0
-  end
-
-  def test_get_new_without_tracker_id
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1
-    assert_response :success
-    assert_template 'new'
-
-    issue = assigns(:issue)
-    assert_not_nil issue
-    assert_equal Project.find(1).trackers.first, issue.tracker
-  end
-
-  def test_get_new_with_no_default_status_should_display_an_error
-    @request.session[:user_id] = 2
-    IssueStatus.delete_all
-
-    get :new, :project_id => 1
-    assert_response 500
-    assert_error_tag :content => /No default issue/
-  end
-
-  def test_get_new_with_no_tracker_should_display_an_error
-    @request.session[:user_id] = 2
-    Tracker.delete_all
-
-    get :new, :project_id => 1
-    assert_response 500
-    assert_error_tag :content => /No tracker/
-  end
-
-  def test_update_form_for_new_issue
-    @request.session[:user_id] = 2
-    xhr :post, :update_form, :project_id => 1,
-                     :issue => {:tracker_id => 2,
-                                :subject => 'This is the test_new issue',
-                                :description => 'This is the description',
-                                :priority_id => 5}
-    assert_response :success
-    assert_template 'update_form'
-    assert_template 'form'
-    assert_equal 'text/javascript', response.content_type
-
-    issue = assigns(:issue)
-    assert_kind_of Issue, issue
-    assert_equal 1, issue.project_id
-    assert_equal 2, issue.tracker_id
-    assert_equal 'This is the test_new issue', issue.subject
-  end
-
-  def test_update_form_for_new_issue_should_propose_transitions_based_on_initial_status
-    @request.session[:user_id] = 2
-    WorkflowTransition.delete_all
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4)
-
-    xhr :post, :update_form, :project_id => 1,
-                     :issue => {:tracker_id => 1,
-                                :status_id => 5,
-                                :subject => 'This is an issue'}
-
-    assert_equal 5, assigns(:issue).status_id
-    assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
-  end
-
-  def test_post_create
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 3,
-                            :status_id => 2,
-                            :subject => 'This is the test_new issue',
-                            :description => 'This is the description',
-                            :priority_id => 5,
-                            :start_date => '2010-11-07',
-                            :estimated_hours => '',
-                            :custom_field_values => {'2' => 'Value for field 2'}}
-    end
-    assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
-
-    issue = Issue.find_by_subject('This is the test_new issue')
-    assert_not_nil issue
-    assert_equal 2, issue.author_id
-    assert_equal 3, issue.tracker_id
-    assert_equal 2, issue.status_id
-    assert_equal Date.parse('2010-11-07'), issue.start_date
-    assert_nil issue.estimated_hours
-    v = issue.custom_values.where(:custom_field_id => 2).first
-    assert_not_nil v
-    assert_equal 'Value for field 2', v.value
-  end
-
-  def test_post_new_with_group_assignment
-    group = Group.find(11)
-    project = Project.find(1)
-    project.members << Member.new(:principal => group, :roles => [Role.givable.first])
-
-    with_settings :issue_group_assignment => '1' do
-      @request.session[:user_id] = 2
-      assert_difference 'Issue.count' do
-        post :create, :project_id => project.id,
-                      :issue => {:tracker_id => 3,
-                                 :status_id => 1,
-                                 :subject => 'This is the test_new_with_group_assignment issue',
-                                 :assigned_to_id => group.id}
-      end
-    end
-    assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
-
-    issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
-    assert_not_nil issue
-    assert_equal group, issue.assigned_to
-  end
-
-  def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
-    with_settings :default_issue_start_date_to_creation_date  => 0 do
-      @request.session[:user_id] = 2
-      assert_difference 'Issue.count' do
-        post :create, :project_id => 1,
-                 :issue => {:tracker_id => 3,
-                            :status_id => 2,
-                            :subject => 'This is the test_new issue',
-                            :description => 'This is the description',
-                            :priority_id => 5,
-                            :estimated_hours => '',
-                            :custom_field_values => {'2' => 'Value for field 2'}}
-      end
-      assert_redirected_to :controller => 'issues', :action => 'show',
-                           :id => Issue.last.id
-      issue = Issue.find_by_subject('This is the test_new issue')
-      assert_not_nil issue
-      assert_nil issue.start_date
-    end
-  end
-
-  def test_post_create_without_start_date_and_default_start_date_is_creation_date
-    with_settings :default_issue_start_date_to_creation_date  => 1 do
-      @request.session[:user_id] = 2
-      assert_difference 'Issue.count' do
-        post :create, :project_id => 1,
-                 :issue => {:tracker_id => 3,
-                            :status_id => 2,
-                            :subject => 'This is the test_new issue',
-                            :description => 'This is the description',
-                            :priority_id => 5,
-                            :estimated_hours => '',
-                            :custom_field_values => {'2' => 'Value for field 2'}}
-      end
-      assert_redirected_to :controller => 'issues', :action => 'show',
-                           :id => Issue.last.id
-      issue = Issue.find_by_subject('This is the test_new issue')
-      assert_not_nil issue
-      assert_equal Date.today, issue.start_date
-    end
-  end
-
-  def test_post_create_and_continue
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-        :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5},
-        :continue => ''
-    end
-
-    issue = Issue.first(:order => 'id DESC')
-    assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3}
-    assert_not_nil flash[:notice], "flash was not set"
-    assert_include %|<a href="/issues/#{issue.id}" title="This is first issue">##{issue.id}</a>|, flash[:notice], "issue link not found in the flash message"
-  end
-
-  def test_post_create_without_custom_fields_param
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is the test_new issue',
-                            :description => 'This is the description',
-                            :priority_id => 5}
-    end
-    assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
-  end
-
-  def test_post_create_with_multi_custom_field
-    field = IssueCustomField.find_by_name('Database')
-    field.update_attribute(:multiple, true)
-
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is the test_new issue',
-                            :description => 'This is the description',
-                            :priority_id => 5,
-                            :custom_field_values => {'1' => ['', 'MySQL', 'Oracle']}}
-    end
-    assert_response 302
-    issue = Issue.first(:order => 'id DESC')
-    assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
-  end
-
-  def test_post_create_with_empty_multi_custom_field
-    field = IssueCustomField.find_by_name('Database')
-    field.update_attribute(:multiple, true)
-
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is the test_new issue',
-                            :description => 'This is the description',
-                            :priority_id => 5,
-                            :custom_field_values => {'1' => ['']}}
-    end
-    assert_response 302
-    issue = Issue.first(:order => 'id DESC')
-    assert_equal [''], issue.custom_field_value(1).sort
-  end
-
-  def test_post_create_with_multi_user_custom_field
-    field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
-      :tracker_ids => [1], :is_for_all => true)
-
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is the test_new issue',
-                            :description => 'This is the description',
-                            :priority_id => 5,
-                            :custom_field_values => {field.id.to_s => ['', '2', '3']}}
-    end
-    assert_response 302
-    issue = Issue.first(:order => 'id DESC')
-    assert_equal ['2', '3'], issue.custom_field_value(field).sort
-  end
-
-  def test_post_create_with_required_custom_field_and_without_custom_fields_param
-    field = IssueCustomField.find_by_name('Database')
-    field.update_attribute(:is_required, true)
-
-    @request.session[:user_id] = 2
-    assert_no_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is the test_new issue',
-                            :description => 'This is the description',
-                            :priority_id => 5}
-    end
-    assert_response :success
-    assert_template 'new'
-    issue = assigns(:issue)
-    assert_not_nil issue
-    assert_error_tag :content => /Database can&#x27;t be blank/
-  end
-
-  def test_create_should_validate_required_fields
-    cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
-    cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'required')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Issue.count' do
-      post :create, :project_id => 1, :issue => {
-        :tracker_id => 2,
-        :status_id => 1,
-        :subject => 'Test',
-        :start_date => '',
-        :due_date => '',
-        :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ''}
-      }
-      assert_response :success
-      assert_template 'new'
-    end
-
-    assert_error_tag :content => /Due date can&#x27;t be blank/i
-    assert_error_tag :content => /Bar can&#x27;t be blank/i
-  end
-
-  def test_create_should_ignore_readonly_fields
-    cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
-    cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
-    WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1, :issue => {
-        :tracker_id => 2,
-        :status_id => 1,
-        :subject => 'Test',
-        :start_date => '2012-07-14',
-        :due_date => '2012-07-16',
-        :custom_field_values => {cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'}
-      }
-      assert_response 302
-    end
-
-    issue = Issue.first(:order => 'id DESC')
-    assert_equal Date.parse('2012-07-14'), issue.start_date
-    assert_nil issue.due_date
-    assert_equal 'value1', issue.custom_field_value(cf1)
-    assert_nil issue.custom_field_value(cf2)
-  end
-
-  def test_post_create_with_watchers
-    @request.session[:user_id] = 2
-    ActionMailer::Base.deliveries.clear
-
-    assert_difference 'Watcher.count', 2 do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is a new issue with watchers',
-                            :description => 'This is the description',
-                            :priority_id => 5,
-                            :watcher_user_ids => ['2', '3']}
-    end
-    issue = Issue.find_by_subject('This is a new issue with watchers')
-    assert_not_nil issue
-    assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
-
-    # Watchers added
-    assert_equal [2, 3], issue.watcher_user_ids.sort
-    assert issue.watched_by?(User.find(3))
-    # Watchers notified
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
-  end
-
-  def test_post_create_subissue
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is a child issue',
-                            :parent_issue_id => '2'}
-      assert_response 302
-    end
-    issue = Issue.order('id DESC').first
-    assert_equal Issue.find(2), issue.parent
-  end
-
-  def test_post_create_subissue_with_sharp_parent_id
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is a child issue',
-                            :parent_issue_id => '#2'}
-      assert_response 302
-    end
-    issue = Issue.order('id DESC').first
-    assert_equal Issue.find(2), issue.parent
-  end
-
-  def test_post_create_subissue_with_non_visible_parent_id_should_not_validate
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is a child issue',
-                            :parent_issue_id => '4'}
-
-      assert_response :success
-      assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '4'
-      assert_error_tag :content => /Parent task is invalid/i
-    end
-  end
-
-  def test_post_create_subissue_with_non_numeric_parent_id_should_not_validate
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is a child issue',
-                            :parent_issue_id => '01ABC'}
-
-      assert_response :success
-      assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '01ABC'
-      assert_error_tag :content => /Parent task is invalid/i
-    end
-  end
-
-  def test_post_create_private
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is a private issue',
-                            :is_private => '1'}
-    end
-    issue = Issue.first(:order => 'id DESC')
-    assert issue.is_private?
-  end
-
-  def test_post_create_private_with_set_own_issues_private_permission
-    role = Role.find(1)
-    role.remove_permission! :set_issues_private
-    role.add_permission! :set_own_issues_private
-
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 1,
-                            :subject => 'This is a private issue',
-                            :is_private => '1'}
-    end
-    issue = Issue.first(:order => 'id DESC')
-    assert issue.is_private?
-  end
-
-  def test_post_create_should_send_a_notification
-    ActionMailer::Base.deliveries.clear
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1,
-                 :issue => {:tracker_id => 3,
-                            :subject => 'This is the test_new issue',
-                            :description => 'This is the description',
-                            :priority_id => 5,
-                            :estimated_hours => '',
-                            :custom_field_values => {'2' => 'Value for field 2'}}
-    end
-    assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
-
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_post_create_should_preserve_fields_values_on_validation_failure
-    @request.session[:user_id] = 2
-    post :create, :project_id => 1,
-               :issue => {:tracker_id => 1,
-                          # empty subject
-                          :subject => '',
-                          :description => 'This is a description',
-                          :priority_id => 6,
-                          :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'textarea[name=?]', 'issue[description]', :text => 'This is a description'
-    assert_select 'select[name=?]', 'issue[priority_id]' do
-      assert_select 'option[value=6][selected=selected]', :text => 'High'
-    end
-    # Custom fields
-    assert_select 'select[name=?]', 'issue[custom_field_values][1]' do
-      assert_select 'option[value=Oracle][selected=selected]', :text => 'Oracle'
-    end
-    assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Value for field 2'
-  end
-
-  def test_post_create_with_failure_should_preserve_watchers
-    assert !User.find(8).member_of?(Project.find(1))
-
-    @request.session[:user_id] = 2
-    post :create, :project_id => 1,
-         :issue => {:tracker_id => 1,
-                    :watcher_user_ids => ['3', '8']}
-    assert_response :success
-    assert_template 'new'
-
-    assert_select 'input[name=?][value=2]:not(checked)', 'issue[watcher_user_ids][]'
-    assert_select 'input[name=?][value=3][checked=checked]', 'issue[watcher_user_ids][]'
-    assert_select 'input[name=?][value=8][checked=checked]', 'issue[watcher_user_ids][]'
-  end
-
-  def test_post_create_should_ignore_non_safe_attributes
-    @request.session[:user_id] = 2
-    assert_nothing_raised do
-      post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
-    end
-  end
-
-  def test_post_create_with_attachment
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count' do
-      assert_difference 'Attachment.count' do
-        post :create, :project_id => 1,
-          :issue => { :tracker_id => '1', :subject => 'With attachment' },
-          :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
-      end
-    end
-
-    issue = Issue.first(:order => 'id DESC')
-    attachment = Attachment.first(:order => 'id DESC')
-
-    assert_equal issue, attachment.container
-    assert_equal 2, attachment.author_id
-    assert_equal 'testfile.txt', attachment.filename
-    assert_equal 'text/plain', attachment.content_type
-    assert_equal 'test file', attachment.description
-    assert_equal 59, attachment.filesize
-    assert File.exists?(attachment.diskfile)
-    assert_equal 59, File.size(attachment.diskfile)
-  end
-
-  def test_post_create_with_attachment_should_notify_with_attachments
-    ActionMailer::Base.deliveries.clear
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-
-    with_settings :host_name => 'mydomain.foo', :protocol => 'http' do
-      assert_difference 'Issue.count' do
-        post :create, :project_id => 1,
-          :issue => { :tracker_id => '1', :subject => 'With attachment' },
-          :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
-      end
-    end
-
-    assert_not_nil ActionMailer::Base.deliveries.last
-    assert_select_email do
-      assert_select 'a[href^=?]', 'http://mydomain.foo/attachments/download', 'testfile.txt'
-    end
-  end
-
-  def test_post_create_with_failure_should_save_attachments
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Issue.count' do
-      assert_difference 'Attachment.count' do
-        post :create, :project_id => 1,
-          :issue => { :tracker_id => '1', :subject => '' },
-          :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
-        assert_response :success
-        assert_template 'new'
-      end
-    end
-
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_equal 'testfile.txt', attachment.filename
-    assert File.exists?(attachment.diskfile)
-    assert_nil attachment.container
-
-    assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
-    assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
-  end
-
-  def test_post_create_with_failure_should_keep_saved_attachments
-    set_tmp_attachments_directory
-    attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Issue.count' do
-      assert_no_difference 'Attachment.count' do
-        post :create, :project_id => 1,
-          :issue => { :tracker_id => '1', :subject => '' },
-          :attachments => {'p0' => {'token' => attachment.token}}
-        assert_response :success
-        assert_template 'new'
-      end
-    end
-
-    assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
-    assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
-  end
-
-  def test_post_create_should_attach_saved_attachments
-    set_tmp_attachments_directory
-    attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count' do
-      assert_no_difference 'Attachment.count' do
-        post :create, :project_id => 1,
-          :issue => { :tracker_id => '1', :subject => 'Saved attachments' },
-          :attachments => {'p0' => {'token' => attachment.token}}
-        assert_response 302
-      end
-    end
-
-    issue = Issue.first(:order => 'id DESC')
-    assert_equal 1, issue.attachments.count
-
-    attachment.reload
-    assert_equal issue, attachment.container
-  end
-
-  context "without workflow privilege" do
-    setup do
-      WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
-      Role.anonymous.add_permission! :add_issues, :add_issue_notes
-    end
-
-    context "#new" do
-      should "propose default status only" do
-        get :new, :project_id => 1
-        assert_response :success
-        assert_template 'new'
-        assert_select 'select[name=?]', 'issue[status_id]' do
-          assert_select 'option', 1
-          assert_select 'option[value=?]', IssueStatus.default.id.to_s
-        end
-      end
-
-      should "accept default status" do
-        assert_difference 'Issue.count' do
-          post :create, :project_id => 1,
-                     :issue => {:tracker_id => 1,
-                                :subject => 'This is an issue',
-                                :status_id => 1}
-        end
-        issue = Issue.last(:order => 'id')
-        assert_equal IssueStatus.default, issue.status
-      end
-
-      should "ignore unauthorized status" do
-        assert_difference 'Issue.count' do
-          post :create, :project_id => 1,
-                     :issue => {:tracker_id => 1,
-                                :subject => 'This is an issue',
-                                :status_id => 3}
-        end
-        issue = Issue.last(:order => 'id')
-        assert_equal IssueStatus.default, issue.status
-      end
-    end
-
-    context "#update" do
-      should "ignore status change" do
-        assert_difference 'Journal.count' do
-          put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
-        end
-        assert_equal 1, Issue.find(1).status_id
-      end
-
-      should "ignore attributes changes" do
-        assert_difference 'Journal.count' do
-          put :update, :id => 1, :issue => {:subject => 'changed', :assigned_to_id => 2, :notes => 'just trying'}
-        end
-        issue = Issue.find(1)
-        assert_equal "Can't print recipes", issue.subject
-        assert_nil issue.assigned_to
-      end
-    end
-  end
-
-  context "with workflow privilege" do
-    setup do
-      WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
-      WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
-      WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4)
-      Role.anonymous.add_permission! :add_issues, :add_issue_notes
-    end
-
-    context "#update" do
-      should "accept authorized status" do
-        assert_difference 'Journal.count' do
-          put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
-        end
-        assert_equal 3, Issue.find(1).status_id
-      end
-
-      should "ignore unauthorized status" do
-        assert_difference 'Journal.count' do
-          put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
-        end
-        assert_equal 1, Issue.find(1).status_id
-      end
-
-      should "accept authorized attributes changes" do
-        assert_difference 'Journal.count' do
-          put :update, :id => 1, :issue => {:assigned_to_id => 2, :notes => 'just trying'}
-        end
-        issue = Issue.find(1)
-        assert_equal 2, issue.assigned_to_id
-      end
-
-      should "ignore unauthorized attributes changes" do
-        assert_difference 'Journal.count' do
-          put :update, :id => 1, :issue => {:subject => 'changed', :notes => 'just trying'}
-        end
-        issue = Issue.find(1)
-        assert_equal "Can't print recipes", issue.subject
-      end
-    end
-
-    context "and :edit_issues permission" do
-      setup do
-        Role.anonymous.add_permission! :add_issues, :edit_issues
-      end
-
-      should "accept authorized status" do
-        assert_difference 'Journal.count' do
-          put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
-        end
-        assert_equal 3, Issue.find(1).status_id
-      end
-
-      should "ignore unauthorized status" do
-        assert_difference 'Journal.count' do
-          put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
-        end
-        assert_equal 1, Issue.find(1).status_id
-      end
-
-      should "accept authorized attributes changes" do
-        assert_difference 'Journal.count' do
-          put :update, :id => 1, :issue => {:subject => 'changed', :assigned_to_id => 2, :notes => 'just trying'}
-        end
-        issue = Issue.find(1)
-        assert_equal "changed", issue.subject
-        assert_equal 2, issue.assigned_to_id
-      end
-    end
-  end
-
-  def test_new_as_copy
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :copy_from => 1
-
-    assert_response :success
-    assert_template 'new'
-
-    assert_not_nil assigns(:issue)
-    orig = Issue.find(1)
-    assert_equal 1, assigns(:issue).project_id
-    assert_equal orig.subject, assigns(:issue).subject
-    assert assigns(:issue).copy?
-
-    assert_select 'form[id=issue-form][action=/projects/ecookbook/issues]' do
-      assert_select 'select[name=?]', 'issue[project_id]' do
-        assert_select 'option[value=1][selected=selected]', :text => 'eCookbook'
-        assert_select 'option[value=2]:not([selected])', :text => 'OnlineStore'
-      end
-      assert_select 'input[name=copy_from][value=1]'
-    end
-
-    # "New issue" menu item should not link to copy
-    assert_select '#main-menu a.new-issue[href=/projects/ecookbook/issues/new]'
-  end
-
-  def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
-    @request.session[:user_id] = 2
-    issue = Issue.find(3)
-    assert issue.attachments.count > 0
-    get :new, :project_id => 1, :copy_from => 3
-
-    assert_select 'input[name=copy_attachments][type=checkbox][checked=checked][value=1]'
-  end
-
-  def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
-    @request.session[:user_id] = 2
-    issue = Issue.find(3)
-    issue.attachments.delete_all
-    get :new, :project_id => 1, :copy_from => 3
-
-    assert_select 'input[name=copy_attachments]', 0
-  end
-
-  def test_new_as_copy_with_subtasks_should_show_copy_subtasks_checkbox
-    @request.session[:user_id] = 2
-    issue = Issue.generate_with_descendants!
-    get :new, :project_id => 1, :copy_from => issue.id
-
-    assert_select 'input[type=checkbox][name=copy_subtasks][checked=checked][value=1]'
-  end
-
-  def test_new_as_copy_with_invalid_issue_should_respond_with_404
-    @request.session[:user_id] = 2
-    get :new, :project_id => 1, :copy_from => 99999
-    assert_response 404
-  end
-
-  def test_create_as_copy_on_different_project
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1, :copy_from => 1,
-        :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
-
-      assert_not_nil assigns(:issue)
-      assert assigns(:issue).copy?
-    end
-    issue = Issue.first(:order => 'id DESC')
-    assert_redirected_to "/issues/#{issue.id}"
-
-    assert_equal 2, issue.project_id
-    assert_equal 3, issue.tracker_id
-    assert_equal 'Copy', issue.subject
-  end
-
-  def test_create_as_copy_should_copy_attachments
-    @request.session[:user_id] = 2
-    issue = Issue.find(3)
-    count = issue.attachments.count
-    assert count > 0
-    assert_difference 'Issue.count' do
-      assert_difference 'Attachment.count', count do
-        assert_difference 'Journal.count', 2 do
-          post :create, :project_id => 1, :copy_from => 3,
-            :issue => {:project_id => '1', :tracker_id => '3',
-                       :status_id => '1', :subject => 'Copy with attachments'},
-            :copy_attachments => '1'
-        end
-      end
-    end
-    copy = Issue.first(:order => 'id DESC')
-    assert_equal count, copy.attachments.count
-    assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
-  end
-
-  def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
-    @request.session[:user_id] = 2
-    issue = Issue.find(3)
-    count = issue.attachments.count
-    assert count > 0
-    assert_difference 'Issue.count' do
-      assert_no_difference 'Attachment.count' do
-        assert_difference 'Journal.count', 2 do
-          post :create, :project_id => 1, :copy_from => 3,
-            :issue => {:project_id => '1', :tracker_id => '3',
-                       :status_id => '1', :subject => 'Copy with attachments'}
-        end
-      end
-    end
-    copy = Issue.first(:order => 'id DESC')
-    assert_equal 0, copy.attachments.count
-  end
-
-  def test_create_as_copy_with_attachments_should_add_new_files
-    @request.session[:user_id] = 2
-    issue = Issue.find(3)
-    count = issue.attachments.count
-    assert count > 0
-    assert_difference 'Issue.count' do
-      assert_difference 'Attachment.count', count + 1 do
-        assert_difference 'Journal.count', 2 do
-          post :create, :project_id => 1, :copy_from => 3,
-            :issue => {:project_id => '1', :tracker_id => '3',
-                       :status_id => '1', :subject => 'Copy with attachments'},
-            :copy_attachments => '1',
-            :attachments => {'1' =>
-                   {'file' => uploaded_test_file('testfile.txt', 'text/plain'),
-                    'description' => 'test file'}}
-        end
-      end
-    end
-    copy = Issue.first(:order => 'id DESC')
-    assert_equal count + 1, copy.attachments.count
-  end
-
-  def test_create_as_copy_should_add_relation_with_copied_issue
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count' do
-      assert_difference 'IssueRelation.count' do
-        post :create, :project_id => 1, :copy_from => 1,
-          :issue => {:project_id => '1', :tracker_id => '3',
-                     :status_id => '1', :subject => 'Copy'}
-      end
-    end
-    copy = Issue.first(:order => 'id DESC')
-    assert_equal 1, copy.relations.size
-  end
-
-  def test_create_as_copy_should_copy_subtasks
-    @request.session[:user_id] = 2
-    issue = Issue.generate_with_descendants!
-    count = issue.descendants.count
-    assert_difference 'Issue.count', count + 1 do
-      assert_difference 'Journal.count', (count + 1) * 2 do
-        post :create, :project_id => 1, :copy_from => issue.id,
-          :issue => {:project_id => '1', :tracker_id => '3',
-                     :status_id => '1', :subject => 'Copy with subtasks'},
-          :copy_subtasks => '1'
-      end
-    end
-    copy = Issue.where(:parent_id => nil).first(:order => 'id DESC')
-    assert_equal count, copy.descendants.count
-    assert_equal issue.descendants.map(&:subject).sort, copy.descendants.map(&:subject).sort
-  end
-
-  def test_create_as_copy_without_copy_subtasks_option_should_not_copy_subtasks
-    @request.session[:user_id] = 2
-    issue = Issue.generate_with_descendants!
-    assert_difference 'Issue.count', 1 do
-      assert_difference 'Journal.count', 2 do
-        post :create, :project_id => 1, :copy_from => 3,
-          :issue => {:project_id => '1', :tracker_id => '3',
-                     :status_id => '1', :subject => 'Copy with subtasks'}
-      end
-    end
-    copy = Issue.where(:parent_id => nil).first(:order => 'id DESC')
-    assert_equal 0, copy.descendants.count
-  end
-
-  def test_create_as_copy_with_failure
-    @request.session[:user_id] = 2
-    post :create, :project_id => 1, :copy_from => 1,
-      :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => ''}
-
-    assert_response :success
-    assert_template 'new'
-
-    assert_not_nil assigns(:issue)
-    assert assigns(:issue).copy?
-
-    assert_select 'form#issue-form[action=/projects/ecookbook/issues]' do
-      assert_select 'select[name=?]', 'issue[project_id]' do
-        assert_select 'option[value=1]:not([selected])', :text => 'eCookbook'
-        assert_select 'option[value=2][selected=selected]', :text => 'OnlineStore'
-      end
-      assert_select 'input[name=copy_from][value=1]'
-    end
-  end
-
-  def test_create_as_copy_on_project_without_permission_should_ignore_target_project
-    @request.session[:user_id] = 2
-    assert !User.find(2).member_of?(Project.find(4))
-
-    assert_difference 'Issue.count' do
-      post :create, :project_id => 1, :copy_from => 1,
-        :issue => {:project_id => '4', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
-    end
-    issue = Issue.first(:order => 'id DESC')
-    assert_equal 1, issue.project_id
-  end
-
-  def test_get_edit
-    @request.session[:user_id] = 2
-    get :edit, :id => 1
-    assert_response :success
-    assert_template 'edit'
-    assert_not_nil assigns(:issue)
-    assert_equal Issue.find(1), assigns(:issue)
-
-    # Be sure we don't display inactive IssuePriorities
-    assert ! IssuePriority.find(15).active?
-    assert_select 'select[name=?]', 'issue[priority_id]' do
-      assert_select 'option[value=15]', 0
-    end
-  end
-
-  def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
-    @request.session[:user_id] = 2
-    Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
-    
-    get :edit, :id => 1
-    assert_select 'input[name=?]', 'time_entry[hours]'
-  end
-
-  def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
-    @request.session[:user_id] = 2
-    Role.find_by_name('Manager').remove_permission! :log_time
-    
-    get :edit, :id => 1
-    assert_select 'input[name=?]', 'time_entry[hours]', 0
-  end
-
-  def test_get_edit_with_params
-    @request.session[:user_id] = 2
-    get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
-        :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => 10 }
-    assert_response :success
-    assert_template 'edit'
-
-    issue = assigns(:issue)
-    assert_not_nil issue
-
-    assert_equal 5, issue.status_id
-    assert_select 'select[name=?]', 'issue[status_id]' do
-      assert_select 'option[value=5][selected=selected]', :text => 'Closed'
-    end
-
-    assert_equal 7, issue.priority_id
-    assert_select 'select[name=?]', 'issue[priority_id]' do
-      assert_select 'option[value=7][selected=selected]', :text => 'Urgent'
-    end
-
-    assert_select 'input[name=?][value=2.5]', 'time_entry[hours]'
-    assert_select 'select[name=?]', 'time_entry[activity_id]' do
-      assert_select 'option[value=10][selected=selected]', :text => 'Development'
-    end
-    assert_select 'input[name=?][value=test_get_edit_with_params]', 'time_entry[comments]'
-  end
-
-  def test_get_edit_with_multi_custom_field
-    field = CustomField.find(1)
-    field.update_attribute :multiple, true
-    issue = Issue.find(1)
-    issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
-    issue.save!
-
-    @request.session[:user_id] = 2
-    get :edit, :id => 1
-    assert_response :success
-    assert_template 'edit'
-
-    assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
-      assert_select 'option', 3
-      assert_select 'option[value=MySQL][selected=selected]'
-      assert_select 'option[value=Oracle][selected=selected]'
-      assert_select 'option[value=PostgreSQL]:not([selected])'
-    end
-  end
-
-  def test_update_form_for_existing_issue
-    @request.session[:user_id] = 2
-    xhr :put, :update_form, :project_id => 1,
-                             :id => 1,
-                             :issue => {:tracker_id => 2,
-                                        :subject => 'This is the test_new issue',
-                                        :description => 'This is the description',
-                                        :priority_id => 5}
-    assert_response :success
-    assert_equal 'text/javascript', response.content_type
-    assert_template 'update_form'
-    assert_template 'form'
-
-    issue = assigns(:issue)
-    assert_kind_of Issue, issue
-    assert_equal 1, issue.id
-    assert_equal 1, issue.project_id
-    assert_equal 2, issue.tracker_id
-    assert_equal 'This is the test_new issue', issue.subject
-  end
-
-  def test_update_form_for_existing_issue_should_keep_issue_author
-    @request.session[:user_id] = 3
-    xhr :put, :update_form, :project_id => 1, :id => 1, :issue => {:subject => 'Changed'}
-    assert_response :success
-    assert_equal 'text/javascript', response.content_type
-
-    issue = assigns(:issue)
-    assert_equal User.find(2), issue.author
-    assert_equal 2, issue.author_id
-    assert_not_equal User.current, issue.author
-  end
-
-  def test_update_form_for_existing_issue_should_propose_transitions_based_on_initial_status
-    @request.session[:user_id] = 2
-    WorkflowTransition.delete_all
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
-
-    xhr :put, :update_form, :project_id => 1,
-                    :id => 2,
-                    :issue => {:tracker_id => 2,
-                               :status_id => 5,
-                               :subject => 'This is an issue'}
-
-    assert_equal 5, assigns(:issue).status_id
-    assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
-  end
-
-  def test_update_form_for_existing_issue_with_project_change
-    @request.session[:user_id] = 2
-    xhr :put, :update_form, :project_id => 1,
-                             :id => 1,
-                             :issue => {:project_id => 2,
-                                        :tracker_id => 2,
-                                        :subject => 'This is the test_new issue',
-                                        :description => 'This is the description',
-                                        :priority_id => 5}
-    assert_response :success
-    assert_template 'form'
-
-    issue = assigns(:issue)
-    assert_kind_of Issue, issue
-    assert_equal 1, issue.id
-    assert_equal 2, issue.project_id
-    assert_equal 2, issue.tracker_id
-    assert_equal 'This is the test_new issue', issue.subject
-  end
-
-  def test_update_form_should_propose_default_status_for_existing_issue
-    @request.session[:user_id] = 2
-    WorkflowTransition.delete_all
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
-
-    xhr :put, :update_form, :project_id => 1, :id => 2
-    assert_response :success
-    assert_equal [2,3], assigns(:allowed_statuses).map(&:id).sort
-  end
-
-  def test_put_update_without_custom_fields_param
-    @request.session[:user_id] = 2
-    ActionMailer::Base.deliveries.clear
-
-    issue = Issue.find(1)
-    assert_equal '125', issue.custom_value_for(2).value
-    old_subject = issue.subject
-    new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
-
-    assert_difference('Journal.count') do
-      assert_difference('JournalDetail.count', 2) do
-        put :update, :id => 1, :issue => {:subject => new_subject,
-                                         :priority_id => '6',
-                                         :category_id => '1' # no change
-                                        }
-      end
-    end
-    assert_redirected_to :action => 'show', :id => '1'
-    issue.reload
-    assert_equal new_subject, issue.subject
-    # Make sure custom fields were not cleared
-    assert_equal '125', issue.custom_value_for(2).value
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
-    assert_mail_body_match "Subject changed from #{old_subject} to #{new_subject}", mail
-  end
-
-  def test_put_update_with_project_change
-    @request.session[:user_id] = 2
-    ActionMailer::Base.deliveries.clear
-
-    assert_difference('Journal.count') do
-      assert_difference('JournalDetail.count', 3) do
-        put :update, :id => 1, :issue => {:project_id => '2',
-                                         :tracker_id => '1', # no change
-                                         :priority_id => '6',
-                                         :category_id => '3'
-                                        }
-      end
-    end
-    assert_redirected_to :action => 'show', :id => '1'
-    issue = Issue.find(1)
-    assert_equal 2, issue.project_id
-    assert_equal 1, issue.tracker_id
-    assert_equal 6, issue.priority_id
-    assert_equal 3, issue.category_id
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
-    assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
-  end
-
-  def test_put_update_with_tracker_change
-    @request.session[:user_id] = 2
-    ActionMailer::Base.deliveries.clear
-
-    assert_difference('Journal.count') do
-      assert_difference('JournalDetail.count', 2) do
-        put :update, :id => 1, :issue => {:project_id => '1',
-                                         :tracker_id => '2',
-                                         :priority_id => '6'
-                                        }
-      end
-    end
-    assert_redirected_to :action => 'show', :id => '1'
-    issue = Issue.find(1)
-    assert_equal 1, issue.project_id
-    assert_equal 2, issue.tracker_id
-    assert_equal 6, issue.priority_id
-    assert_equal 1, issue.category_id
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
-    assert_mail_body_match "Tracker changed from Bug to Feature request", mail
-  end
-
-  def test_put_update_with_custom_field_change
-    @request.session[:user_id] = 2
-    issue = Issue.find(1)
-    assert_equal '125', issue.custom_value_for(2).value
-
-    assert_difference('Journal.count') do
-      assert_difference('JournalDetail.count', 3) do
-        put :update, :id => 1, :issue => {:subject => 'Custom field change',
-                                         :priority_id => '6',
-                                         :category_id => '1', # no change
-                                         :custom_field_values => { '2' => 'New custom value' }
-                                        }
-      end
-    end
-    assert_redirected_to :action => 'show', :id => '1'
-    issue.reload
-    assert_equal 'New custom value', issue.custom_value_for(2).value
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_not_nil mail
-    assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
-  end
-
-  def test_put_update_with_multi_custom_field_change
-    field = CustomField.find(1)
-    field.update_attribute :multiple, true
-    issue = Issue.find(1)
-    issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
-    issue.save!
-
-    @request.session[:user_id] = 2
-    assert_difference('Journal.count') do
-      assert_difference('JournalDetail.count', 3) do
-        put :update, :id => 1,
-          :issue => {
-            :subject => 'Custom field change',
-            :custom_field_values => { '1' => ['', 'Oracle', 'PostgreSQL'] }
-          }
-      end
-    end
-    assert_redirected_to :action => 'show', :id => '1'
-    assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
-  end
-
-  def test_put_update_with_status_and_assignee_change
-    issue = Issue.find(1)
-    assert_equal 1, issue.status_id
-    @request.session[:user_id] = 2
-    assert_difference('TimeEntry.count', 0) do
-      put :update,
-           :id => 1,
-           :issue => { :status_id => 2, :assigned_to_id => 3, :notes => 'Assigned to dlopper' },
-           :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
-    end
-    assert_redirected_to :action => 'show', :id => '1'
-    issue.reload
-    assert_equal 2, issue.status_id
-    j = Journal.order('id DESC').first
-    assert_equal 'Assigned to dlopper', j.notes
-    assert_equal 2, j.details.size
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_mail_body_match "Status changed from New to Assigned", mail
-    # subject should contain the new status
-    assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
-  end
-
-  def test_put_update_with_note_only
-    notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
-    # anonymous user
-    put :update,
-         :id => 1,
-         :issue => { :notes => notes }
-    assert_redirected_to :action => 'show', :id => '1'
-    j = Journal.order('id DESC').first
-    assert_equal notes, j.notes
-    assert_equal 0, j.details.size
-    assert_equal User.anonymous, j.user
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_mail_body_match notes, mail
-  end
-
-  def test_put_update_with_private_note_only
-    notes = 'Private note'
-    @request.session[:user_id] = 2
-
-    assert_difference 'Journal.count' do
-      put :update, :id => 1, :issue => {:notes => notes, :private_notes => '1'}
-      assert_redirected_to :action => 'show', :id => '1'
-    end
-
-    j = Journal.order('id DESC').first
-    assert_equal notes, j.notes
-    assert_equal true, j.private_notes
-  end
-
-  def test_put_update_with_private_note_and_changes
-    notes = 'Private note'
-    @request.session[:user_id] = 2
-
-    assert_difference 'Journal.count', 2 do
-      put :update, :id => 1, :issue => {:subject => 'New subject', :notes => notes, :private_notes => '1'}
-      assert_redirected_to :action => 'show', :id => '1'
-    end
-
-    j = Journal.order('id DESC').first
-    assert_equal notes, j.notes
-    assert_equal true, j.private_notes
-    assert_equal 0, j.details.count
-
-    j = Journal.order('id DESC').offset(1).first
-    assert_nil j.notes
-    assert_equal false, j.private_notes
-    assert_equal 1, j.details.count
-  end
-
-  def test_put_update_with_note_and_spent_time
-    @request.session[:user_id] = 2
-    spent_hours_before = Issue.find(1).spent_hours
-    assert_difference('TimeEntry.count') do
-      put :update,
-           :id => 1,
-           :issue => { :notes => '2.5 hours added' },
-           :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
-    end
-    assert_redirected_to :action => 'show', :id => '1'
-
-    issue = Issue.find(1)
-
-    j = Journal.order('id DESC').first
-    assert_equal '2.5 hours added', j.notes
-    assert_equal 0, j.details.size
-
-    t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
-    assert_not_nil t
-    assert_equal 2.5, t.hours
-    assert_equal spent_hours_before + 2.5, issue.spent_hours
-  end
-
-  def test_put_update_should_preserve_parent_issue_even_if_not_visible
-    parent = Issue.generate!(:project_id => 1, :is_private => true)
-    issue = Issue.generate!(:parent_issue_id => parent.id)
-    assert !parent.visible?(User.find(3))
-    @request.session[:user_id] = 3
-
-    get :edit, :id => issue.id
-    assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', parent.id.to_s
-
-    put :update, :id => issue.id, :issue => {:subject => 'New subject', :parent_issue_id => parent.id.to_s}
-    assert_response 302
-    assert_equal parent, issue.parent
-  end
-
-  def test_put_update_with_attachment_only
-    set_tmp_attachments_directory
-
-    # Delete all fixtured journals, a race condition can occur causing the wrong
-    # journal to get fetched in the next find.
-    Journal.delete_all
-
-    # anonymous user
-    assert_difference 'Attachment.count' do
-      put :update, :id => 1,
-        :issue => {:notes => ''},
-        :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
-    end
-
-    assert_redirected_to :action => 'show', :id => '1'
-    j = Issue.find(1).journals.reorder('id DESC').first
-    assert j.notes.blank?
-    assert_equal 1, j.details.size
-    assert_equal 'testfile.txt', j.details.first.value
-    assert_equal User.anonymous, j.user
-
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_equal Issue.find(1), attachment.container
-    assert_equal User.anonymous, attachment.author
-    assert_equal 'testfile.txt', attachment.filename
-    assert_equal 'text/plain', attachment.content_type
-    assert_equal 'test file', attachment.description
-    assert_equal 59, attachment.filesize
-    assert File.exists?(attachment.diskfile)
-    assert_equal 59, File.size(attachment.diskfile)
-
-    mail = ActionMailer::Base.deliveries.last
-    assert_mail_body_match 'testfile.txt', mail
-  end
-
-  def test_put_update_with_failure_should_save_attachments
-    set_tmp_attachments_directory
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Journal.count' do
-      assert_difference 'Attachment.count' do
-        put :update, :id => 1,
-          :issue => { :subject => '' },
-          :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
-        assert_response :success
-        assert_template 'edit'
-      end
-    end
-
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_equal 'testfile.txt', attachment.filename
-    assert File.exists?(attachment.diskfile)
-    assert_nil attachment.container
-
-    assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
-    assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
-  end
-
-  def test_put_update_with_failure_should_keep_saved_attachments
-    set_tmp_attachments_directory
-    attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Journal.count' do
-      assert_no_difference 'Attachment.count' do
-        put :update, :id => 1,
-          :issue => { :subject => '' },
-          :attachments => {'p0' => {'token' => attachment.token}}
-        assert_response :success
-        assert_template 'edit'
-      end
-    end
-
-    assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
-    assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
-  end
-
-  def test_put_update_should_attach_saved_attachments
-    set_tmp_attachments_directory
-    attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
-    @request.session[:user_id] = 2
-
-    assert_difference 'Journal.count' do
-      assert_difference 'JournalDetail.count' do
-        assert_no_difference 'Attachment.count' do
-          put :update, :id => 1,
-            :issue => {:notes => 'Attachment added'},
-            :attachments => {'p0' => {'token' => attachment.token}}
-          assert_redirected_to '/issues/1'
-        end
-      end
-    end
-
-    attachment.reload
-    assert_equal Issue.find(1), attachment.container
-
-    journal = Journal.first(:order => 'id DESC')
-    assert_equal 1, journal.details.size
-    assert_equal 'testfile.txt', journal.details.first.value
-  end
-
-  def test_put_update_with_attachment_that_fails_to_save
-    set_tmp_attachments_directory
-
-    # Delete all fixtured journals, a race condition can occur causing the wrong
-    # journal to get fetched in the next find.
-    Journal.delete_all
-
-    # Mock out the unsaved attachment
-    Attachment.any_instance.stubs(:create).returns(Attachment.new)
-
-    # anonymous user
-    put :update,
-         :id => 1,
-         :issue => {:notes => ''},
-         :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
-    assert_redirected_to :action => 'show', :id => '1'
-    assert_equal '1 file(s) could not be saved.', flash[:warning]
-  end
-
-  def test_put_update_with_no_change
-    issue = Issue.find(1)
-    issue.journals.clear
-    ActionMailer::Base.deliveries.clear
-
-    put :update,
-         :id => 1,
-         :issue => {:notes => ''}
-    assert_redirected_to :action => 'show', :id => '1'
-
-    issue.reload
-    assert issue.journals.empty?
-    # No email should be sent
-    assert ActionMailer::Base.deliveries.empty?
-  end
-
-  def test_put_update_should_send_a_notification
-    @request.session[:user_id] = 2
-    ActionMailer::Base.deliveries.clear
-    issue = Issue.find(1)
-    old_subject = issue.subject
-    new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
-
-    put :update, :id => 1, :issue => {:subject => new_subject,
-                                     :priority_id => '6',
-                                     :category_id => '1' # no change
-                                    }
-    assert_equal 1, ActionMailer::Base.deliveries.size
-  end
-
-  def test_put_update_with_invalid_spent_time_hours_only
-    @request.session[:user_id] = 2
-    notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
-
-    assert_no_difference('Journal.count') do
-      put :update,
-           :id => 1,
-           :issue => {:notes => notes},
-           :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
-    end
-    assert_response :success
-    assert_template 'edit'
-
-    assert_error_tag :descendant => {:content => /Activity can&#x27;t be blank/}
-    assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
-    assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2z'
-  end
-
-  def test_put_update_with_invalid_spent_time_comments_only
-    @request.session[:user_id] = 2
-    notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
-
-    assert_no_difference('Journal.count') do
-      put :update,
-           :id => 1,
-           :issue => {:notes => notes},
-           :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""}
-    end
-    assert_response :success
-    assert_template 'edit'
-
-    assert_error_tag :descendant => {:content => /Activity can&#x27;t be blank/}
-    assert_error_tag :descendant => {:content => /Hours can&#x27;t be blank/}
-    assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
-    assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'this is my comment'
-  end
-
-  def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
-    issue = Issue.find(2)
-    @request.session[:user_id] = 2
-
-    put :update,
-         :id => issue.id,
-         :issue => {
-           :fixed_version_id => 4
-         }
-
-    assert_response :redirect
-    issue.reload
-    assert_equal 4, issue.fixed_version_id
-    assert_not_equal issue.project_id, issue.fixed_version.project_id
-  end
-
-  def test_put_update_should_redirect_back_using_the_back_url_parameter
-    issue = Issue.find(2)
-    @request.session[:user_id] = 2
-
-    put :update,
-         :id => issue.id,
-         :issue => {
-           :fixed_version_id => 4
-         },
-         :back_url => '/issues'
-
-    assert_response :redirect
-    assert_redirected_to '/issues'
-  end
-
-  def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
-    issue = Issue.find(2)
-    @request.session[:user_id] = 2
-
-    put :update,
-         :id => issue.id,
-         :issue => {
-           :fixed_version_id => 4
-         },
-         :back_url => 'http://google.com'
-
-    assert_response :redirect
-    assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
-  end
-
-  def test_get_bulk_edit
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 2]
-    assert_response :success
-    assert_template 'bulk_edit'
-
-    assert_select 'ul#bulk-selection' do
-      assert_select 'li', 2
-      assert_select 'li a', :text => 'Bug #1'
-    end
-
-    assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
-      assert_select 'input[name=?]', 'ids[]', 2
-      assert_select 'input[name=?][value=1][type=hidden]', 'ids[]'
-
-      assert_select 'select[name=?]', 'issue[project_id]'
-      assert_select 'input[name=?]', 'issue[parent_issue_id]'
-  
-      # Project specific custom field, date type
-      field = CustomField.find(9)
-      assert !field.is_for_all?
-      assert_equal 'date', field.field_format
-      assert_select 'input[name=?]', 'issue[custom_field_values][9]'
-  
-      # System wide custom field
-      assert CustomField.find(1).is_for_all?
-      assert_select 'select[name=?]', 'issue[custom_field_values][1]'
-  
-      # Be sure we don't display inactive IssuePriorities
-      assert ! IssuePriority.find(15).active?
-      assert_select 'select[name=?]', 'issue[priority_id]' do
-        assert_select 'option[value=15]', 0
-      end
-    end
-  end
-
-  def test_get_bulk_edit_on_different_projects
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 2, 6]
-    assert_response :success
-    assert_template 'bulk_edit'
-
-    # Can not set issues from different projects as children of an issue
-    assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
-
-    # Project specific custom field, date type
-    field = CustomField.find(9)
-    assert !field.is_for_all?
-    assert !field.project_ids.include?(Issue.find(6).project_id)
-    assert_select 'input[name=?]', 'issue[custom_field_values][9]', 0
-  end
-
-  def test_get_bulk_edit_with_user_custom_field
-    field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true)
-
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 2]
-    assert_response :success
-    assert_template 'bulk_edit'
-
-    assert_select 'select.user_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
-      assert_select 'option', Project.find(1).users.count + 2 # "no change" + "none" options
-    end
-  end
-
-  def test_get_bulk_edit_with_version_custom_field
-    field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true)
-
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 2]
-    assert_response :success
-    assert_template 'bulk_edit'
-
-    assert_select 'select.version_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
-      assert_select 'option', Project.find(1).shared_versions.count + 2 # "no change" + "none" options
-    end
-  end
-
-  def test_get_bulk_edit_with_multi_custom_field
-    field = CustomField.find(1)
-    field.update_attribute :multiple, true
-
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 2]
-    assert_response :success
-    assert_template 'bulk_edit'
-
-    assert_select 'select[name=?]', 'issue[custom_field_values][1][]' do
-      assert_select 'option', field.possible_values.size + 1 # "none" options
-    end
-  end
-
-  def test_bulk_edit_should_propose_to_clear_text_custom_fields
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 3]
-    assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', '__none__'
-  end
-
-  def test_bulk_edit_should_only_propose_statuses_allowed_for_all_issues
-    WorkflowTransition.delete_all
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
-                               :old_status_id => 1, :new_status_id => 1)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
-                               :old_status_id => 1, :new_status_id => 3)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
-                               :old_status_id => 1, :new_status_id => 4)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
-                               :old_status_id => 2, :new_status_id => 1)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
-                               :old_status_id => 2, :new_status_id => 3)
-    WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
-                               :old_status_id => 2, :new_status_id => 5)
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 2]
-
-    assert_response :success
-    statuses = assigns(:available_statuses)
-    assert_not_nil statuses
-    assert_equal [1, 3], statuses.map(&:id).sort
-
-    assert_select 'select[name=?]', 'issue[status_id]' do
-      assert_select 'option', 3 # 2 statuses + "no change" option
-    end
-  end
-
-  def test_bulk_edit_should_propose_target_project_open_shared_versions
-    @request.session[:user_id] = 2
-    post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
-    assert_response :success
-    assert_template 'bulk_edit'
-    assert_equal Project.find(1).shared_versions.open.all.sort, assigns(:versions).sort
-
-    assert_select 'select[name=?]', 'issue[fixed_version_id]' do
-      assert_select 'option', :text => '2.0'
-    end
-  end
-
-  def test_bulk_edit_should_propose_target_project_categories
-    @request.session[:user_id] = 2
-    post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
-    assert_response :success
-    assert_template 'bulk_edit'
-    assert_equal Project.find(1).issue_categories.sort, assigns(:categories).sort
-
-    assert_select 'select[name=?]', 'issue[category_id]' do
-      assert_select 'option', :text => 'Recipes'
-    end
-  end
-
-  def test_bulk_update
-    @request.session[:user_id] = 2
-    # update issues priority
-    post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
-                                     :issue => {:priority_id => 7,
-                                                :assigned_to_id => '',
-                                                :custom_field_values => {'2' => ''}}
-
-    assert_response 302
-    # check that the issues were updated
-    assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
-
-    issue = Issue.find(1)
-    journal = issue.journals.reorder('created_on DESC').first
-    assert_equal '125', issue.custom_value_for(2).value
-    assert_equal 'Bulk editing', journal.notes
-    assert_equal 1, journal.details.size
-  end
-
-  def test_bulk_update_with_group_assignee
-    group = Group.find(11)
-    project = Project.find(1)
-    project.members << Member.new(:principal => group, :roles => [Role.givable.first])
-
-    @request.session[:user_id] = 2
-    # update issues assignee
-    post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
-                                     :issue => {:priority_id => '',
-                                                :assigned_to_id => group.id,
-                                                :custom_field_values => {'2' => ''}}
-
-    assert_response 302
-    assert_equal [group, group], Issue.find_all_by_id([1, 2]).collect {|i| i.assigned_to}
-  end
-
-  def test_bulk_update_on_different_projects
-    @request.session[:user_id] = 2
-    # update issues priority
-    post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
-                                     :issue => {:priority_id => 7,
-                                                :assigned_to_id => '',
-                                                :custom_field_values => {'2' => ''}}
-
-    assert_response 302
-    # check that the issues were updated
-    assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
-
-    issue = Issue.find(1)
-    journal = issue.journals.reorder('created_on DESC').first
-    assert_equal '125', issue.custom_value_for(2).value
-    assert_equal 'Bulk editing', journal.notes
-    assert_equal 1, journal.details.size
-  end
-
-  def test_bulk_update_on_different_projects_without_rights
-    @request.session[:user_id] = 3
-    user = User.find(3)
-    action = { :controller => "issues", :action => "bulk_update" }
-    assert user.allowed_to?(action, Issue.find(1).project)
-    assert ! user.allowed_to?(action, Issue.find(6).project)
-    post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
-                                     :issue => {:priority_id => 7,
-                                                :assigned_to_id => '',
-                                                :custom_field_values => {'2' => ''}}
-    assert_response 403
-    assert_not_equal "Bulk should fail", Journal.last.notes
-  end
-
-  def test_bullk_update_should_send_a_notification
-    @request.session[:user_id] = 2
-    ActionMailer::Base.deliveries.clear
-    post(:bulk_update,
-         {
-           :ids => [1, 2],
-           :notes => 'Bulk editing',
-           :issue => {
-             :priority_id => 7,
-             :assigned_to_id => '',
-             :custom_field_values => {'2' => ''}
-           }
-         })
-
-    assert_response 302
-    assert_equal 2, ActionMailer::Base.deliveries.size
-  end
-
-  def test_bulk_update_project
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
-    # Issues moved to project 2
-    assert_equal 2, Issue.find(1).project_id
-    assert_equal 2, Issue.find(2).project_id
-    # No tracker change
-    assert_equal 1, Issue.find(1).tracker_id
-    assert_equal 2, Issue.find(2).tracker_id
-  end
-
-  def test_bulk_update_project_on_single_issue_should_follow_when_needed
-    @request.session[:user_id] = 2
-    post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1'
-    assert_redirected_to '/issues/1'
-  end
-
-  def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
-    @request.session[:user_id] = 2
-    post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1'
-    assert_redirected_to '/projects/onlinestore/issues'
-  end
-
-  def test_bulk_update_tracker
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'}
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
-    assert_equal 2, Issue.find(1).tracker_id
-    assert_equal 2, Issue.find(2).tracker_id
-  end
-
-  def test_bulk_update_status
-    @request.session[:user_id] = 2
-    # update issues priority
-    post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
-                                     :issue => {:priority_id => '',
-                                                :assigned_to_id => '',
-                                                :status_id => '5'}
-
-    assert_response 302
-    issue = Issue.find(1)
-    assert issue.closed?
-  end
-
-  def test_bulk_update_priority
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
-
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
-    assert_equal 6, Issue.find(1).priority_id
-    assert_equal 6, Issue.find(2).priority_id
-  end
-
-  def test_bulk_update_with_notes
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues'
-
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
-    assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
-    assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
-  end
-
-  def test_bulk_update_parent_id
-    IssueRelation.delete_all
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 3],
-      :notes => 'Bulk editing parent',
-      :issue => {:priority_id => '', :assigned_to_id => '',
-                 :status_id => '', :parent_issue_id => '2'}
-    assert_response 302
-    parent = Issue.find(2)
-    assert_equal parent.id, Issue.find(1).parent_id
-    assert_equal parent.id, Issue.find(3).parent_id
-    assert_equal [1, 3], parent.children.collect(&:id).sort
-  end
-
-  def test_bulk_update_custom_field
-    @request.session[:user_id] = 2
-    # update issues priority
-    post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
-                                     :issue => {:priority_id => '',
-                                                :assigned_to_id => '',
-                                                :custom_field_values => {'2' => '777'}}
-
-    assert_response 302
-
-    issue = Issue.find(1)
-    journal = issue.journals.reorder('created_on DESC').first
-    assert_equal '777', issue.custom_value_for(2).value
-    assert_equal 1, journal.details.size
-    assert_equal '125', journal.details.first.old_value
-    assert_equal '777', journal.details.first.value
-  end
-
-  def test_bulk_update_custom_field_to_blank
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing custom field',
-                                     :issue => {:priority_id => '',
-                                                :assigned_to_id => '',
-                                                :custom_field_values => {'1' => '__none__'}}
-    assert_response 302
-    assert_equal '', Issue.find(1).custom_field_value(1)
-    assert_equal '', Issue.find(3).custom_field_value(1)
-  end
-
-  def test_bulk_update_multi_custom_field
-    field = CustomField.find(1)
-    field.update_attribute :multiple, true
-
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2, 3], :notes => 'Bulk editing multi custom field',
-                                     :issue => {:priority_id => '',
-                                                :assigned_to_id => '',
-                                                :custom_field_values => {'1' => ['MySQL', 'Oracle']}}
-
-    assert_response 302
-
-    assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
-    assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
-    # the custom field is not associated with the issue tracker
-    assert_nil Issue.find(2).custom_field_value(1)
-  end
-
-  def test_bulk_update_multi_custom_field_to_blank
-    field = CustomField.find(1)
-    field.update_attribute :multiple, true
-
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing multi custom field',
-                                     :issue => {:priority_id => '',
-                                                :assigned_to_id => '',
-                                                :custom_field_values => {'1' => ['__none__']}}
-    assert_response 302
-    assert_equal [''], Issue.find(1).custom_field_value(1)
-    assert_equal [''], Issue.find(3).custom_field_value(1)
-  end
-
-  def test_bulk_update_unassign
-    assert_not_nil Issue.find(2).assigned_to
-    @request.session[:user_id] = 2
-    # unassign issues
-    post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
-    assert_response 302
-    # check that the issues were updated
-    assert_nil Issue.find(2).assigned_to
-  end
-
-  def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
-    @request.session[:user_id] = 2
-
-    post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
-
-    assert_response :redirect
-    issues = Issue.find([1,2])
-    issues.each do |issue|
-      assert_equal 4, issue.fixed_version_id
-      assert_not_equal issue.project_id, issue.fixed_version.project_id
-    end
-  end
-
-  def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1,2], :back_url => '/issues'
-
-    assert_response :redirect
-    assert_redirected_to '/issues'
-  end
-
-  def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
-
-    assert_response :redirect
-    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
-  end
-
-  def test_bulk_update_with_all_failures_should_show_errors
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2], :issue => {:start_date => 'foo'}
-
-    assert_response :success
-    assert_template 'bulk_edit'
-    assert_select '#errorExplanation span', :text => 'Failed to save 2 issue(s) on 2 selected: #1, #2.'
-    assert_select '#errorExplanation ul li', :text => 'Start date is not a valid date: #1, #2'
-
-    assert_equal [1, 2], assigns[:issues].map(&:id)
-  end
-
-  def test_bulk_update_with_some_failures_should_show_errors
-    issue1 = Issue.generate!(:start_date => '2013-05-12')
-    issue2 = Issue.generate!(:start_date => '2013-05-15')
-    issue3 = Issue.generate!
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [issue1.id, issue2.id, issue3.id],
-                       :issue => {:due_date => '2013-05-01'}
-    assert_response :success
-    assert_template 'bulk_edit'
-    assert_select '#errorExplanation span',
-                  :text => "Failed to save 2 issue(s) on 3 selected: ##{issue1.id}, ##{issue2.id}."
-    assert_select '#errorExplanation ul li',
-                   :text => "Due date must be greater than start date: ##{issue1.id}, ##{issue2.id}"
-    assert_equal [issue1.id, issue2.id], assigns[:issues].map(&:id)
-  end
-
-  def test_bulk_update_with_failure_should_preserved_form_values
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2', :start_date => 'foo'}
-
-    assert_response :success
-    assert_template 'bulk_edit'
-    assert_select 'select[name=?]', 'issue[tracker_id]' do
-      assert_select 'option[value=2][selected=selected]'
-    end
-    assert_select 'input[name=?][value=?]', 'issue[start_date]', 'foo'
-  end
-
-  def test_get_bulk_copy
-    @request.session[:user_id] = 2
-    get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
-    assert_response :success
-    assert_template 'bulk_edit'
-
-    issues = assigns(:issues)
-    assert_not_nil issues
-    assert_equal [1, 2, 3], issues.map(&:id).sort
-
-    assert_select 'input[name=copy_attachments]'
-  end
-
-  def test_bulk_copy_to_another_project
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count', 2 do
-      assert_no_difference 'Project.find(1).issues.count' do
-        post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}, :copy => '1'
-      end
-    end
-    assert_redirected_to '/projects/ecookbook/issues'
-
-    copies = Issue.all(:order => 'id DESC', :limit => issues.size)
-    copies.each do |copy|
-      assert_equal 2, copy.project_id
-    end
-  end
-
-  def test_bulk_copy_should_allow_not_changing_the_issue_attributes
-    @request.session[:user_id] = 2
-    issues = [
-      Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
-                    :priority_id => 2, :subject => 'issue 1', :author_id => 1,
-                    :assigned_to_id => nil),
-      Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2,
-                    :priority_id => 1, :subject => 'issue 2', :author_id => 2,
-                    :assigned_to_id => 3)
-    ]
-    assert_difference 'Issue.count', issues.size do
-      post :bulk_update, :ids => issues.map(&:id), :copy => '1', 
-           :issue => {
-             :project_id => '', :tracker_id => '', :assigned_to_id => '',
-             :status_id => '', :start_date => '', :due_date => ''
-           }
-    end
-
-    copies = Issue.all(:order => 'id DESC', :limit => issues.size)
-    issues.each do |orig|
-      copy = copies.detect {|c| c.subject == orig.subject}
-      assert_not_nil copy
-      assert_equal orig.project_id, copy.project_id
-      assert_equal orig.tracker_id, copy.tracker_id
-      assert_equal orig.status_id, copy.status_id
-      assert_equal orig.assigned_to_id, copy.assigned_to_id
-      assert_equal orig.priority_id, copy.priority_id
-    end
-  end
-
-  def test_bulk_copy_should_allow_changing_the_issue_attributes
-    # Fixes random test failure with Mysql
-    # where Issue.where(:project_id => 2).limit(2).order('id desc')
-    # doesn't return the expected results
-    Issue.delete_all("project_id=2")
-
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count', 2 do
-      assert_no_difference 'Project.find(1).issues.count' do
-        post :bulk_update, :ids => [1, 2], :copy => '1', 
-             :issue => {
-               :project_id => '2', :tracker_id => '', :assigned_to_id => '4',
-               :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
-             }
-      end
-    end
-
-    copied_issues = Issue.where(:project_id => 2).limit(2).order('id desc').to_a
-    assert_equal 2, copied_issues.size
-    copied_issues.each do |issue|
-      assert_equal 2, issue.project_id, "Project is incorrect"
-      assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
-      assert_equal 1, issue.status_id, "Status is incorrect"
-      assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
-      assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
-    end
-  end
-
-  def test_bulk_copy_should_allow_adding_a_note
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count', 1 do
-      post :bulk_update, :ids => [1], :copy => '1',
-           :notes => 'Copying one issue',
-           :issue => {
-             :project_id => '', :tracker_id => '', :assigned_to_id => '4',
-             :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
-           }
-    end
-    issue = Issue.first(:order => 'id DESC')
-    assert_equal 1, issue.journals.size
-    journal = issue.journals.first
-    assert_equal 1, journal.details.size
-    assert_equal 'Copying one issue', journal.notes
-  end
-
-  def test_bulk_copy_should_allow_not_copying_the_attachments
-    attachment_count = Issue.find(3).attachments.size
-    assert attachment_count > 0
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', 1 do
-      assert_no_difference 'Attachment.count' do
-        post :bulk_update, :ids => [3], :copy => '1',
-             :issue => {
-               :project_id => ''
-             }
-      end
-    end
-  end
-
-  def test_bulk_copy_should_allow_copying_the_attachments
-    attachment_count = Issue.find(3).attachments.size
-    assert attachment_count > 0
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', 1 do
-      assert_difference 'Attachment.count', attachment_count do
-        post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '1',
-             :issue => {
-               :project_id => ''
-             }
-      end
-    end
-  end
-
-  def test_bulk_copy_should_add_relations_with_copied_issues
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', 2 do
-      assert_difference 'IssueRelation.count', 2 do
-        post :bulk_update, :ids => [1, 3], :copy => '1', 
-             :issue => {
-               :project_id => '1'
-             }
-      end
-    end
-  end
-
-  def test_bulk_copy_should_allow_not_copying_the_subtasks
-    issue = Issue.generate_with_descendants!
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', 1 do
-      post :bulk_update, :ids => [issue.id], :copy => '1',
-           :issue => {
-             :project_id => ''
-           }
-    end
-  end
-
-  def test_bulk_copy_should_allow_copying_the_subtasks
-    issue = Issue.generate_with_descendants!
-    count = issue.descendants.count
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', count+1 do
-      post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '1',
-           :issue => {
-             :project_id => ''
-           }
-    end
-    copy = Issue.where(:parent_id => nil).order("id DESC").first
-    assert_equal count, copy.descendants.count
-  end
-
-  def test_bulk_copy_should_not_copy_selected_subtasks_twice
-    issue = Issue.generate_with_descendants!
-    count = issue.descendants.count
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', count+1 do
-      post :bulk_update, :ids => issue.self_and_descendants.map(&:id), :copy => '1', :copy_subtasks => '1',
-           :issue => {
-             :project_id => ''
-           }
-    end
-    copy = Issue.where(:parent_id => nil).order("id DESC").first
-    assert_equal count, copy.descendants.count
-  end
-
-  def test_bulk_copy_to_another_project_should_follow_when_needed
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1], :copy => '1', :issue => {:project_id => 2}, :follow => '1'
-    issue = Issue.first(:order => 'id DESC')
-    assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
-  end
-
-  def test_bulk_copy_with_all_failures_should_display_errors
-    @request.session[:user_id] = 2
-    post :bulk_update, :ids => [1, 2], :copy => '1', :issue => {:start_date => 'foo'}
-
-    assert_response :success
-  end
-
-  def test_destroy_issue_with_no_time_entries
-    assert_nil TimeEntry.find_by_issue_id(2)
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', -1 do
-      delete :destroy, :id => 2
-    end
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    assert_nil Issue.find_by_id(2)
-  end
-
-  def test_destroy_issues_with_time_entries
-    @request.session[:user_id] = 2
-
-    assert_no_difference 'Issue.count' do
-      delete :destroy, :ids => [1, 3]
-    end
-    assert_response :success
-    assert_template 'destroy'
-    assert_not_nil assigns(:hours)
-    assert Issue.find_by_id(1) && Issue.find_by_id(3)
-
-    assert_select 'form' do
-      assert_select 'input[name=_method][value=delete]'
-    end
-  end
-
-  def test_destroy_issues_and_destroy_time_entries
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', -2 do
-      assert_difference 'TimeEntry.count', -3 do
-        delete :destroy, :ids => [1, 3], :todo => 'destroy'
-      end
-    end
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
-    assert_nil TimeEntry.find_by_id([1, 2])
-  end
-
-  def test_destroy_issues_and_assign_time_entries_to_project
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', -2 do
-      assert_no_difference 'TimeEntry.count' do
-        delete :destroy, :ids => [1, 3], :todo => 'nullify'
-      end
-    end
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
-    assert_nil TimeEntry.find(1).issue_id
-    assert_nil TimeEntry.find(2).issue_id
-  end
-
-  def test_destroy_issues_and_reassign_time_entries_to_another_issue
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', -2 do
-      assert_no_difference 'TimeEntry.count' do
-        delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
-      end
-    end
-    assert_redirected_to :action => 'index', :project_id => 'ecookbook'
-    assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
-    assert_equal 2, TimeEntry.find(1).issue_id
-    assert_equal 2, TimeEntry.find(2).issue_id
-  end
-
-  def test_destroy_issues_from_different_projects
-    @request.session[:user_id] = 2
-
-    assert_difference 'Issue.count', -3 do
-      delete :destroy, :ids => [1, 2, 6], :todo => 'destroy'
-    end
-    assert_redirected_to :controller => 'issues', :action => 'index'
-    assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
-  end
-
-  def test_destroy_parent_and_child_issues
-    parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
-    child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
-    assert child.is_descendant_of?(parent.reload)
-
-    @request.session[:user_id] = 2
-    assert_difference 'Issue.count', -2 do
-      delete :destroy, :ids => [parent.id, child.id], :todo => 'destroy'
-    end
-    assert_response 302
-  end
-
-  def test_destroy_invalid_should_respond_with_404
-    @request.session[:user_id] = 2
-    assert_no_difference 'Issue.count' do
-      delete :destroy, :id => 999
-    end
-    assert_response 404
-  end
-
-  def test_default_search_scope
-    get :index
-
-    assert_select 'div#quick-search form' do
-      assert_select 'input[name=issues][value=1][type=hidden]'
-    end
-  end
-end
--- a/.svn/pristine/ff/ff1c47ab3a4a85cdc878d408e530d4ba3db0f578.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::AttachmentsTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules,
-           :attachments
-
-  def setup
-    Setting.rest_api_enabled = '1'
-    set_fixtures_attachments_directory
-  end
-
-  def teardown
-    set_tmp_attachments_directory
-  end
-
-  test "GET /attachments/:id.xml should return the attachment" do
-    get '/attachments/7.xml', {}, credentials('jsmith')
-    assert_response :success
-    assert_equal 'application/xml', @response.content_type
-    assert_tag :tag => 'attachment',
-      :child => {
-        :tag => 'id',
-        :content => '7',
-        :sibling => {
-          :tag => 'filename',
-          :content => 'archive.zip',
-          :sibling => {
-            :tag => 'content_url',
-            :content => 'http://www.example.com/attachments/download/7/archive.zip'
-          }
-        }
-      }
-  end
-
-  test "GET /attachments/:id.xml should deny access without credentials" do
-    get '/attachments/7.xml'
-    assert_response 401
-    set_tmp_attachments_directory
-  end
-
-  test "GET /attachments/download/:id/:filename should return the attachment content" do
-    get '/attachments/download/7/archive.zip', {}, credentials('jsmith')
-    assert_response :success
-    assert_equal 'application/octet-stream', @response.content_type
-    set_tmp_attachments_directory
-  end
-
-  test "GET /attachments/download/:id/:filename should deny access without credentials" do
-    get '/attachments/download/7/archive.zip'
-    assert_response 302
-    set_tmp_attachments_directory
-  end
-
-  test "POST /uploads.xml should return the token" do
-    set_tmp_attachments_directory
-    assert_difference 'Attachment.count' do
-      post '/uploads.xml', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
-      assert_response :created
-      assert_equal 'application/xml', response.content_type
-    end
-
-    xml = Hash.from_xml(response.body)
-    assert_kind_of Hash, xml['upload']
-    token = xml['upload']['token']
-    assert_not_nil token
-
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_equal token, attachment.token
-    assert_nil attachment.container
-    assert_equal 2, attachment.author_id
-    assert_equal 'File content'.size, attachment.filesize
-    assert attachment.content_type.blank?
-    assert attachment.filename.present?
-    assert_match /\d+_[0-9a-z]+/, attachment.diskfile
-    assert File.exist?(attachment.diskfile)
-    assert_equal 'File content', File.read(attachment.diskfile)
-  end
-
-  test "POST /uploads.json should return the token" do
-    set_tmp_attachments_directory
-    assert_difference 'Attachment.count' do
-      post '/uploads.json', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
-      assert_response :created
-      assert_equal 'application/json', response.content_type
-    end
-
-    json = ActiveSupport::JSON.decode(response.body)
-    assert_kind_of Hash, json['upload']
-    token = json['upload']['token']
-    assert_not_nil token
-
-    attachment = Attachment.first(:order => 'id DESC')
-    assert_equal token, attachment.token
-  end
-
-  test "POST /uploads.xml should accept :filename param as the attachment filename" do
-    set_tmp_attachments_directory
-    assert_difference 'Attachment.count' do
-      post '/uploads.xml?filename=test.txt', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
-      assert_response :created
-    end
-
-    attachment = Attachment.order('id DESC').first
-    assert_equal 'test.txt', attachment.filename
-    assert_match /_test\.txt$/, attachment.diskfile
-  end
-
-  test "POST /uploads.xml should not accept other content types" do
-    set_tmp_attachments_directory
-    assert_no_difference 'Attachment.count' do
-      post '/uploads.xml', 'PNG DATA', {"CONTENT_TYPE" => 'image/png'}.merge(credentials('jsmith'))
-      assert_response 406
-    end
-  end
-
-  test "POST /uploads.xml should return errors if file is too big" do
-    set_tmp_attachments_directory
-    with_settings :attachment_max_size => 1 do
-      assert_no_difference 'Attachment.count' do
-        post '/uploads.xml', ('x' * 2048), {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
-        assert_response 422
-        assert_tag 'error', :content => /exceeds the maximum allowed file size/
-      end
-    end
-  end
-end
--- a/.svn/pristine/ff/ffd51ba3b4736e466b3394ff29f5bd178dfb6f31.svn-base	Mon Mar 17 08:57:53 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WatcherTest < ActiveSupport::TestCase
-  fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules,
-           :issues, :issue_statuses, :enumerations, :trackers, :projects_trackers,
-           :boards, :messages,
-           :wikis, :wiki_pages,
-           :watchers
-
-  def setup
-    @user = User.find(1)
-    @issue = Issue.find(1)
-  end
-
-  def test_validate
-    user = User.find(5)
-    assert !user.active?
-    watcher = Watcher.new(:user_id => user.id)
-    assert !watcher.save
-  end
-
-  def test_watch
-    assert @issue.add_watcher(@user)
-    @issue.reload
-    assert @issue.watchers.detect { |w| w.user == @user }
-  end
-
-  def test_cant_watch_twice
-    assert @issue.add_watcher(@user)
-    assert !@issue.add_watcher(@user)
-  end
-
-  def test_watched_by
-    assert @issue.add_watcher(@user)
-    @issue.reload
-    assert @issue.watched_by?(@user)
-    assert Issue.watched_by(@user).include?(@issue)
-  end
-
-  def test_watcher_users
-    watcher_users = Issue.find(2).watcher_users
-    assert_kind_of Array, watcher_users
-    assert_kind_of User, watcher_users.first
-  end
-
-  def test_watcher_users_should_not_validate_user
-    User.update_all("firstname = ''", "id=1")
-    @user.reload
-    assert !@user.valid?
-
-    issue = Issue.new(:project => Project.find(1), :tracker_id => 1, :subject => "test", :author => User.find(2))
-    issue.watcher_users << @user
-    issue.save!
-    assert issue.watched_by?(@user)
-  end
-
-  def test_watcher_user_ids
-    assert_equal [1, 3], Issue.find(2).watcher_user_ids.sort
-  end
-
-  def test_watcher_user_ids=
-    issue = Issue.new
-    issue.watcher_user_ids = ['1', '3']
-    assert issue.watched_by?(User.find(1))
-  end
-
-  def test_watcher_user_ids_should_make_ids_uniq
-    issue = Issue.new(:project => Project.find(1), :tracker_id => 1, :subject => "test", :author => User.find(2))
-    issue.watcher_user_ids = ['1', '3', '1']
-    issue.save!
-    assert_equal 2, issue.watchers.count
-  end
-
-  def test_addable_watcher_users
-    addable_watcher_users = @issue.addable_watcher_users
-    assert_kind_of Array, addable_watcher_users
-    assert_kind_of User, addable_watcher_users.first
-  end
-
-  def test_addable_watcher_users_should_not_include_user_that_cannot_view_the_object
-    issue = Issue.new(:project => Project.find(1), :is_private => true)
-    assert_nil issue.addable_watcher_users.detect {|user| !issue.visible?(user)}
-  end
-
-  def test_any_watched_should_return_false_if_no_object_is_watched
-    objects = (0..2).map {Issue.generate!}
-
-    assert_equal false, Watcher.any_watched?(objects, @user)
-  end
-
-  def test_any_watched_should_return_true_if_one_object_is_watched
-    objects = (0..2).map {Issue.generate!}
-    objects.last.add_watcher(@user)
-
-    assert_equal true, Watcher.any_watched?(objects, @user)
-  end
-
-  def test_any_watched_should_return_false_with_no_object
-    assert_equal false, Watcher.any_watched?([], @user)
-  end
-
-  def test_recipients
-    @issue.watchers.delete_all
-    @issue.reload
-
-    assert @issue.watcher_recipients.empty?
-    assert @issue.add_watcher(@user)
-
-    @user.mail_notification = 'all'
-    @user.save!
-    @issue.reload
-    assert @issue.watcher_recipients.include?(@user.mail)
-
-    @user.mail_notification = 'none'
-    @user.save!
-    @issue.reload
-    assert !@issue.watcher_recipients.include?(@user.mail)
-  end
-
-  def test_unwatch
-    assert @issue.add_watcher(@user)
-    @issue.reload
-    assert_equal 1, @issue.remove_watcher(@user)
-  end
-
-  def test_prune
-    Watcher.delete_all("user_id = 9")
-    user = User.find(9)
-
-    # public
-    Watcher.create!(:watchable => Issue.find(1), :user => user)
-    Watcher.create!(:watchable => Issue.find(2), :user => user)
-    Watcher.create!(:watchable => Message.find(1), :user => user)
-    Watcher.create!(:watchable => Wiki.find(1), :user => user)
-    Watcher.create!(:watchable => WikiPage.find(2), :user => user)
-
-    # private project (id: 2)
-    Member.create!(:project => Project.find(2), :principal => user, :role_ids => [1])
-    Watcher.create!(:watchable => Issue.find(4), :user => user)
-    Watcher.create!(:watchable => Message.find(7), :user => user)
-    Watcher.create!(:watchable => Wiki.find(2), :user => user)
-    Watcher.create!(:watchable => WikiPage.find(3), :user => user)
-
-    assert_no_difference 'Watcher.count' do
-      Watcher.prune(:user => User.find(9))
-    end
-
-    Member.delete_all
-
-    assert_difference 'Watcher.count', -4 do
-      Watcher.prune(:user => User.find(9))
-    end
-
-    assert Issue.find(1).watched_by?(user)
-    assert !Issue.find(4).watched_by?(user)
-  end
-
-  def test_prune_all
-    user = User.find(9)
-    Watcher.new(:watchable => Issue.find(4), :user => User.find(9)).save(:validate => false)
-
-    assert Watcher.prune > 0
-    assert !Issue.find(4).watched_by?(user)
-  end
-end
Binary file .svn/wc.db has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.travis.yml	Tue Sep 09 09:32:11 2014 +0100
@@ -0,0 +1,38 @@
+# Redmine runs tests on own continuous integration server.
+# http://www.redmine.org/projects/redmine/wiki/Continuous_integration
+# You can also run tests on your environment.
+language: ruby
+rvm:
+  - 1.8.7
+  - 1.9.2
+  - 1.9.3
+  - 2.0
+  - jruby
+matrix:
+  allow_failures:
+    # SCM tests fail randomly due to IO.popen().
+    # https://github.com/jruby/jruby/issues/779
+    - rvm: jruby
+env:
+  - "TEST_SUITE=units       DATABASE_ADAPTER=postgresql"
+  - "TEST_SUITE=functionals DATABASE_ADAPTER=postgresql"
+  - "TEST_SUITE=integration DATABASE_ADAPTER=postgresql"
+  - "TEST_SUITE=units       DATABASE_ADAPTER=mysql"
+  - "TEST_SUITE=functionals DATABASE_ADAPTER=mysql"
+  - "TEST_SUITE=integration DATABASE_ADAPTER=mysql"
+  - "TEST_SUITE=units       DATABASE_ADAPTER=sqlite3"
+  - "TEST_SUITE=functionals DATABASE_ADAPTER=sqlite3"
+  - "TEST_SUITE=integration DATABASE_ADAPTER=sqlite3"
+before_install:
+  - "sudo apt-get update -qq"
+  - "sudo apt-get --no-install-recommends install bzr cvs git mercurial subversion"
+script:
+  - "SCMS=bazaar,cvs,subversion,git,mercurial,filesystem"
+  - "export SCMS"
+  - "git --version"
+  - "bundle install"
+  - "RUN_ON_NOT_OFFICIAL='' RUBY_VER=1.9 BRANCH=trunk bundle exec rake config/database.yml"
+  - "bundle install"
+  - "JRUBY_OPTS=-J-Xmx1024m bundle exec rake ci"
+notifications:
+  email: false
--- a/Gemfile	Mon Mar 17 08:57:53 2014 +0000
+++ b/Gemfile	Tue Sep 09 09:32:11 2014 +0100
@@ -1,6 +1,7 @@
 source 'https://rubygems.org'
 
-gem "rails", "3.2.17"
+gem "rails", "3.2.19"
+gem "rake", "~> 10.1.1"
 gem "jquery-rails", "~> 2.0.2"
 gem "coderay", "~> 1.1.0"
 gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
@@ -77,7 +78,7 @@
 
 group :test do
   gem "shoulda", "~> 3.3.2"
-  gem "mocha", ">= 0.14", :require => 'mocha/api'
+  gem "mocha", "~> 1.0.0", :require => 'mocha/api'
   if RUBY_VERSION >= '1.9.3'
     gem "capybara", "~> 2.1.0"
     gem "selenium-webdriver"
--- a/app/controllers/admin_controller.rb	Mon Mar 17 08:57:53 2014 +0000
+++ b/app/controllers/admin_controller.rb	Tue Sep 09 09:32:11 2014 +0100
@@ -65,7 +65,7 @@
       @test = Mailer.test_email(User.current).deliver
       flash[:notice] = l(:notice_email_sent, User.current.mail)
     rescue Exception => e
-      flash[:error] = l(:notice_email_error, Redmine::CodesetUtil.replace_invalid_utf8(e.message))
+      flash[:error] = l(:notice_email_error, Redmine::CodesetUtil.replace_invalid_utf8(e.message.dup))
     end
     ActionMailer::Base.raise_delivery_errors = raise_delivery_errors
     redirect_to settings_path(:tab => 'notifications')
--- a/app/controllers/application_controller.rb	Mon Mar 17 08:57:53 2014 +0000
+++ b/app/controllers/application_controller.rb	Tue Sep 09 09:32:11 2014 +0100
@@ -44,6 +44,7 @@
     unless api_request?
       super
       cookies.delete(autologin_cookie_name)
+      self.logged_user = nil
       render_error :status => 422, :message => "Invalid form authenticity token."
     end
   end
@@ -375,11 +376,7 @@
 
   def redirect_back_or_default(default)
     back_url = params[:back_url].to_s
-    if back_url.present?
-      begin
-        uri = URI.parse(back_url)
-        # do not redirect user to another host or to the login or register page
-        if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
+    if back_url.present? && valid_back_url?(back_url)
           # soundsoftware: if back_url is the home page,
           # change it to My Page (#125)
           if (uri.path == home_path)
@@ -395,18 +392,41 @@
             uri.scheme = "https"
           end
           back_url = uri.to_s
-          redirect_to(back_url)
-          return
-        end
-      rescue URI::InvalidURIError
-        logger.warn("Could not redirect to invalid URL #{back_url}")
-        # redirect to default
-      end
+      redirect_to(back_url)
+      return
     end
     redirect_to default
     false
   end
 
+  # Returns true if back_url is a valid url for redirection, otherwise false
+  def valid_back_url?(back_url)
+    if CGI.unescape(back_url).include?('..')
+      return false
+    end
+
+    begin
+      uri = URI.parse(back_url)
+    rescue URI::InvalidURIError
+      return false
+    end
+
+    if uri.host.present? && uri.host != request.host
+      return false
+    end
+
+    if uri.path.match(%r{/(login|account/register)})
+      return false
+    end
+
+    if relative_url_root.present? && !uri.path.starts_with?(relative_url_root)
+      return false
+    end
+
+    return true
+  end
+  private :valid_back_url?
+
   # Redirects to the request referer if present, redirects to args or call block otherwise.
   def redirect_to_referer_or(*args, &block)
     redirect_to :back
@@ -569,7 +589,7 @@
 
   # Returns a string that can be used as filename value in Content-Disposition header
   def filename_for_content_disposition(name)
-    request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
+    request.env['HTTP_USER_AGENT'] =~ %r{(MSIE|Trident)} ? ERB::Util.url_encode(name) : name
   end
 
   def api_request?
--- a/app/models/custom_field.rb	Mon Mar 17 08:57:53 2014 +0000
+++ b/app/models/custom_field.rb	Tue Sep 09 09:32:11 2014 +0100
@@ -352,8 +352,8 @@
     errs = []
     unless value.to_s == ''
       errs << ::I18n.t('activerecord.errors.messages.invalid') unless regexp.blank? or value =~ Regexp.new(regexp)
-      errs << ::I18n.t('activerecord.errors.messages.too_short', :count => min_length) if min_length > 0 and value.length < min_length
-      errs << ::I18n.t('activerecord.errors.messages.too_long', :count => max_length) if max_length > 0 and value.length > max_length
+      errs << ::I18n.t('activerecord.errors.messages.too_short', :count => min_length) if min_length && min_length > 0 && value.length < min_length
+      errs << ::I18n.t('activerecord.errors.messages.too_long', :count => max_length) if max_length && max_length > 0 && value.length > max_length
 
       # Format specific validations
       case field_format
--- a/app/views/attachments/_form.html.erb	Mon Mar 17 08:57:53 2014 +0000
+++ b/app/views/attachments/_form.html.erb	Tue Sep 09 09:32:11 2014 +0100
@@ -15,7 +15,6 @@
       :id => nil,
       :class => 'file_selector',
       :multiple => true,
-      :onchange => 'addInputFiles(this);',
       :data => {
         :max_file_size => Setting.attachment_max_size.to_i.kilobytes,
         :max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
@@ -25,6 +24,9 @@
       } %>
 (<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
 </span>
+<%= javascript_tag do %>
+  $('input.file_selector').on('change', function(){addInputFiles(this);});
+<% end %>
 
 <% content_for :header_tags do %>
   <%= javascript_include_tag 'attachments' %>
--- a/config/configuration.yml.example	Mon Mar 17 08:57:53 2014 +0000
+++ b/config/configuration.yml.example	Tue Sep 09 09:32:11 2014 +0100
@@ -72,10 +72,9 @@
 #
 # === More configuration options
 #
-# See the "Configuration options" at the following website for a list of the
-# full options allowed:
+# See following page:
 #
-# http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer
+# http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
 
 
 # default configuration options for all environments
--- a/config/environments/production.rb	Mon Mar 17 08:57:53 2014 +0000
+++ b/config/environments/production.rb	Tue Sep 09 09:32:11 2014 +0100
@@ -5,7 +5,8 @@
   config.cache_classes = true
 
   #####
-  # Customize the default logger (http://ruby-doc.org/core/classes/Logger.html)
+  # Customize the default logger
+  # http://www.ruby-doc.org/stdlib-1.8.7/libdoc/logger/rdoc/Logger.html
   #
   # Use a different logger for distributed setups
   # config.logger        = SyslogLogger.new
--- a/doc/CHANGELOG	Mon Mar 17 08:57:53 2014 +0000
+++ b/doc/CHANGELOG	Tue Sep 09 09:32:11 2014 +0100
@@ -4,6 +4,22 @@
 Copyright (C) 2006-2014  Jean-Philippe Lang
 http://www.redmine.org/
 
+== 2014-07-06 v2.4.6
+
+* Defect #13932: File upload does not work with Safari
+* Defect #16467: back_url redirection does not work for '/'
+* Defect #16511: Potentiel data leak in "Invalid form authenticity token" error screen
+* Defect #16530: back_url redirection work for non sub uri
+* Defect #16711: Non-ascii attachment file name get corrupted in IE11
+* Defect #17151: File upload broken on Chrome 36
+* Defect #17235: use test_email report can't modify frozen String
+* Defect #17391: Upgrade to Rails 3.2.19
+* Patch #17206: Fix Invalid CSS on Error-Pages
+
+== 2014-03-29 v2.4.5
+
+* Defect #16466: Fixed back url verification
+
 == 2014-03-02 v2.4.4
 
 * Defect #16081: Export CSV - Custom field true/false not using translation
@@ -23,6 +39,11 @@
 * Defect #16038: Issue#css_classes corrupts user.groups association cache
 * Patch #15960: pt-BR translation for 2.4-stable
 
+Additional note:
+
+#15781 was forgotten to merge to v2.4.3.
+It is in v2.5.0.
+
 == 2013-12-23 v2.4.2
 
 * Defect #15398: HTML 5 invalid <center> tag
--- a/lib/redmine/version.rb	Mon Mar 17 08:57:53 2014 +0000
+++ b/lib/redmine/version.rb	Tue Sep 09 09:32:11 2014 +0100
@@ -4,7 +4,7 @@
   module VERSION #:nodoc:
     MAJOR = 2
     MINOR = 4
-    TINY  = 4
+    TINY  = 6
 
     # Branch values:
     # * official release: nil
--- a/lib/tasks/ci.rake	Mon Mar 17 08:57:53 2014 +0000
+++ b/lib/tasks/ci.rake	Tue Sep 09 09:32:11 2014 +0100
@@ -1,4 +1,4 @@
-desc "Run the Continous Integration tests for Redmine"
+desc "Run the Continuous Integration tests for Redmine"
 task :ci do
   # RAILS_ENV and ENV[] can diverge so force them both to test
   ENV['RAILS_ENV'] = 'test'
@@ -16,13 +16,23 @@
     Rake::Task["db:create:all"].invoke
     Rake::Task["db:migrate"].invoke
     Rake::Task["db:schema:dump"].invoke
-    Rake::Task["test:scm:setup:all"].invoke
+    if scms = ENV['SCMS']
+      scms.split(',').each do |scm|
+        Rake::Task["test:scm:setup:#{scm}"].invoke
+      end
+    else
+      Rake::Task["test:scm:setup:all"].invoke
+    end
     Rake::Task["test:scm:update"].invoke
   end
 
   desc "Build Redmine"
   task :build do
-    Rake::Task["test"].invoke
+    if test_suite = ENV['TEST_SUITE']
+      Rake::Task["test:#{test_suite}"].invoke
+    else
+      Rake::Task["test"].invoke
+    end
     # Rake::Task["test:ui"].invoke if RUBY_VERSION >= '1.9.3'
   end
 
@@ -43,14 +53,24 @@
   case database
   when 'mysql'
     dev_conf =  {'adapter' => (RUBY_VERSION >= '1.9' ? 'mysql2' : 'mysql'),
-                'database' => dev_db_name, 'host' => 'localhost',
-                'username' => 'jenkins', 'password' => 'jenkins',
-                'encoding' => 'utf8'}
+                 'database' => dev_db_name, 'host' => 'localhost',
+                 'encoding' => 'utf8'}
+    if ENV['RUN_ON_NOT_OFFICIAL']
+      dev_conf['username'] = 'root'
+    else
+      dev_conf['username'] = 'jenkins'
+      dev_conf['password'] = 'jenkins'
+    end
     test_conf = dev_conf.merge('database' => test_db_name)
   when 'postgresql'
     dev_conf =  {'adapter' => 'postgresql', 'database' => dev_db_name,
-                 'host' => 'localhost',
-                 'username' => 'jenkins', 'password' => 'jenkins'}
+                 'host' => 'localhost'}
+    if ENV['RUN_ON_NOT_OFFICIAL']
+      dev_conf['username'] = 'postgres'
+    else
+      dev_conf['username'] = 'jenkins'
+      dev_conf['password'] = 'jenkins'
+    end
     test_conf = dev_conf.merge('database' => test_db_name)
   when /sqlite3/
     dev_conf =  {'adapter' => (Object.const_defined?(:JRUBY_VERSION) ?
--- a/public/404.html	Mon Mar 17 08:57:53 2014 +0000
+++ b/public/404.html	Tue Sep 09 09:32:11 2014 +0100
@@ -4,7 +4,7 @@
 <title>Redmine 404 error</title>
 <style>
 body{
-font-family: Trebuchet MS,Georgia,"Times New Roman",serif;
+font-family: "Trebuchet MS",Georgia,"Times New Roman",serif;
 color:#303030;
 margin:10px;
 }
--- a/public/500.html	Mon Mar 17 08:57:53 2014 +0000
+++ b/public/500.html	Tue Sep 09 09:32:11 2014 +0100
@@ -4,7 +4,7 @@
 <title>Redmine 500 error</title>
 <style>
 body{
-font-family: Trebuchet MS,Georgia,"Times New Roman",serif;
+font-family: "Trebuchet MS",Georgia,"Times New Roman",serif;
 color:#303030;
 margin:10px;
 }
--- a/public/help/zh-tw/wiki_syntax_detailed.html	Mon Mar 17 08:57:53 2014 +0000
+++ b/public/help/zh-tw/wiki_syntax_detailed.html	Tue Sep 09 09:32:11 2014 +0100
@@ -143,7 +143,7 @@
         <p>逸出字元:</p>
 
         <ul>
-            <li>您可以在文字的前面加上驚嘆號 (!) 來避免該文字被剖析成 Remine 連結</li>
+            <li>您可以在文字的前面加上驚嘆號 (!) 來避免該文字被剖析成 Redmine 連結</li>
         </ul>
 
 
--- a/public/javascripts/attachments.js	Mon Mar 17 08:57:53 2014 +0000
+++ b/public/javascripts/attachments.js	Tue Sep 09 09:32:11 2014 +0100
@@ -99,8 +99,10 @@
   return $.ajax(uploadUrl, {
     type: 'POST',
     contentType: 'application/octet-stream',
-    beforeSend: function(jqXhr) {
+    beforeSend: function(jqXhr, settings) {
       jqXhr.setRequestHeader('Accept', 'application/js');
+      // attach proper File object 
+      settings.data = blob;
     },
     xhr: function() {
       var xhr = $.ajaxSettings.xhr();
@@ -131,7 +133,7 @@
     }
   }
 
-  clearedFileInput.insertAfter('#attachments_fields');
+  clearedFileInput.insertAfter('#attachments_fields').on('change', function(){addInputFiles(this);});
 }
 
 function uploadAndAttachFiles(files, inputEl) {
--- a/test/functional/account_controller_test.rb	Mon Mar 17 08:57:53 2014 +0000
+++ b/test/functional/account_controller_test.rb	Tue Sep 09 09:32:11 2014 +0100
@@ -43,13 +43,61 @@
 
   def test_login_should_redirect_to_back_url_param
     # request.uri is "test.host" in test environment
-    post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http://test.host/issues/show/1'
-    assert_redirected_to '/issues/show/1'
+    back_urls = [
+      'http://test.host/issues/show/1',
+      '/'
+    ]
+    back_urls.each do |back_url|
+      post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
+      assert_redirected_to back_url
+    end
+  end
+
+  def test_login_with_suburi_should_redirect_to_back_url_param
+    @relative_url_root = ApplicationController.relative_url_root
+    ApplicationController.relative_url_root = '/redmine'
+
+    back_urls = [
+      'http://test.host/redmine/issues/show/1',
+      '/redmine'
+    ]
+    back_urls.each do |back_url|
+      post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
+      assert_redirected_to back_url
+    end
+  ensure
+    ApplicationController.relative_url_root = @relative_url_root
   end
 
   def test_login_should_not_redirect_to_another_host
-    post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http://test.foo/fake'
-    assert_redirected_to '/my/page'
+    back_urls = [
+      'http://test.foo/fake',
+      '//test.foo/fake'
+    ]
+    back_urls.each do |back_url|
+      post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
+      assert_redirected_to '/my/page'
+    end
+  end
+
+  def test_login_with_suburi_should_not_redirect_to_another_suburi
+    @relative_url_root = ApplicationController.relative_url_root
+    ApplicationController.relative_url_root = '/redmine'
+
+    back_urls = [
+      'http://test.host/',
+      'http://test.host/fake',
+      'http://test.host/fake/issues',
+      'http://test.host/redmine/../fake',
+      'http://test.host/redmine/../fake/issues',
+      'http://test.host/redmine/%2e%2e/fake'
+    ]
+    back_urls.each do |back_url|
+      post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
+      assert_redirected_to '/my/page'
+    end
+  ensure
+    ApplicationController.relative_url_root = @relative_url_root
   end
 
   def test_login_with_wrong_password