Compare commits

...
1327 Commits
Author SHA1 Message Date
Jean-Philippe Lang 7e6d1b6c35 Version set to 1.2.3.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8178 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-10 14:49:48 +00:00
Jean-Philippe Lang 5c4b618bce CHANGELOG updated.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8177 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-10 14:49:10 +00:00
Jean-Philippe Lang 2f87b3bae3 Merged r7920, r7921, r7922 and r7924 from trunk (#9405).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8158 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-10 12:04:47 +00:00
Jean-Philippe Lang 1848fcd91e Merged r8103 from trunk (#9737).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8157 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-10 11:56:13 +00:00
Jean-Philippe Lang 40a14cafbc Merged r7809 from trunk (#9567).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8120 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:58:58 +00:00
Jean-Philippe Lang f252108f30 Merged r7834 from trunk (#9566).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8119 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:57:55 +00:00
Jean-Philippe Lang 6d57380712 Merged r7780 from trunk (#9552).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8118 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:56:49 +00:00
Jean-Philippe Lang 00d1b230e0 Merged r7814 from trunk (#9577).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8117 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:54:05 +00:00
Jean-Philippe Lang d19a0b70e0 Merged r7971 from trunk (#9682).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8116 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:52:31 +00:00
Jean-Philippe Lang 535b5ccf2b Merged r7919 from trunk (#9448).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8115 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:49:52 +00:00
Toshi MARUYAMA a441667b8d Merged r8106 from trunk
remove trailing white-spaces from calendar-hr.js

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8108 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 01:21:54 +00:00
Toshi MARUYAMA d4246334e0 Merged r8105 from trunk
convert calendar-hr.js (Croatian) from Windows-1250 to UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8107 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 01:21:06 +00:00
Toshi MARUYAMA c8c48a7816 Merged r8002 from trunk
Bulgarian translation updated by Ivan Cenov.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8083 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-04 22:36:12 +00:00
Jean-Philippe Lang fa894328bb Merged r7983 and r7984 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8000 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:17:41 +00:00
Jean-Philippe Lang 63e2e52dd3 Merged r7782 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7999 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:14:24 +00:00
Jean-Philippe Lang ff75a959e0 Merged r7779 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7998 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:12:58 +00:00
Jean-Philippe Lang 5d1388db02 Merged r7985 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7997 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:11:54 +00:00
Jean-Philippe Lang 3e4d1fb04f Backported r7982 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7996 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:10:45 +00:00
Jean-Philippe Lang 2858979b69 Merged r7956 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7995 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:08:06 +00:00
Etienne Massip be09ba039b Merged r7837 from trunk (#9597).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7838 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-18 22:30:32 +00:00
Toshi MARUYAMA a5adecb40c Merge r7797 from trunk
Simplified Chinese "text_git_repository_note" translation updated by Steven Wong.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7801 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 06:38:41 +00:00
Toshi MARUYAMA f328373ffd Merge r7796 from trunk
Simplified Chinese translation for 1.2.2 updated by Steven Wong.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7800 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 06:38:08 +00:00
Toshi MARUYAMA 367ad46911 Merge r7795 from trunk
Simplified Chinese translation changed by Steven Wong.

* field_due_date
* permission_rename_wiki_pages
* button_rename

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7799 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 06:37:33 +00:00
Toshi MARUYAMA 909cb9ab78 Merge r6699 from trunk
remove trailing white-spaces from config/locales/zh.yml

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7793 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 03:46:53 +00:00
Toshi MARUYAMA 8c2869f521 Merge r6698 from trunk
Ruby 1.9: fix parsing error of zh.yml with psych yaml library

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7792 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 03:46:05 +00:00
Jean-Philippe Lang 20e54f46b0 Merged r7776 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7777 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 12:53:35 +00:00
Jean-Philippe Lang 88e918f64d Merged r7774 from trunk (#8615).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7775 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 12:44:13 +00:00
Jean-Philippe Lang b6f0d9da8a Merged r7772 from trunk (#8615).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7773 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 12:33:15 +00:00
Jean-Philippe Lang d6bf26ace7 Merged r6308 from trunk (#8884).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7770 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:44:10 +00:00
Jean-Philippe Lang 21910aa428 Merged r6311 from trunk (#8880).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7769 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:40:56 +00:00
Jean-Philippe Lang f22ff1f1c2 Merged r6298 from trunk (#8865).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7768 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:37:55 +00:00
Jean-Philippe Lang 83a2283b7d Merged r6300 and r6302 from trunk (#8836).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7767 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:36:52 +00:00
Jean-Philippe Lang 03b2162e6c Merged r6324 and r6325 from trunk (#8651).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7766 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:35:03 +00:00
Jean-Philippe Lang c605477da5 Merged r6314 from trunk (#8633).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7765 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:31:49 +00:00
Toshi MARUYAMA 35ec8e3570 Merged r7731 from trunk
Spanish translation updated by Ismael G Marin C.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7732 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-05 06:57:52 +00:00
Toshi MARUYAMA 6e68bf8ab4 merge r7707 from trunk
add unit test of escaping image urls

Contributed by Holger Just.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7709 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-02 07:41:12 +00:00
Toshi MARUYAMA d181a2221a merge r6759 from trunk
remove trailing white-spaces from test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7708 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-02 07:40:49 +00:00
Toshi MARUYAMA e4034bc74b backed out previous 1.2-stable dummy commit
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7703 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-30 03:29:14 +00:00
Toshi MARUYAMA 310d4c52ce dummy commit to run test on CI server
Tests fail on CI Server, but I don't know the reason.
http://www.redmine.org/builds/build_1.2-stable-1.8.7-sqlite3_82.html

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7702 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-30 03:28:46 +00:00
Toshi MARUYAMA 1d1b3fc77d Merged r7699 from trunk
Dutch translation updated by Pieter Nicolai

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7700 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-30 00:05:29 +00:00
Toshi MARUYAMA 5e58434567 Merged r7660 from trunk
scm: git: fix typo of comments about fetching revisions

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7661 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-27 01:37:09 +00:00
Toshi MARUYAMA 8da22803be Merged r7658 from trunk
scm: git: recovery and improve comments of fetching from 1.1
about harmful influence that git does not have the revision number.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7659 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-27 00:41:37 +00:00
Toshi MARUYAMA 83ab216d70 Merged r7650 from trunk
scm: mercurial: drop supporting below Mercurial 1.1

On November 1st 2011, Mercurial 2.0 will be released.

On Mercurial 1.1.2, unit lib test fails with following error.

<pre>
Traceback (most recent call last):
  File "/WEB-DOWN/hg-repo/hg-crew/hg", line 20, in <module>
    mercurial.dispatch.run()
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 20, in run
    sys.exit(dispatch(sys.argv[1:]))
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 29, in dispatch
    return _runcatch(u, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 45, in _runcatch
    return _dispatch(ui, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 367, in _dispatch
    ret = _runcommand(ui, options, cmd, d)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 416, in _runcommand
    return checkargs()
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 376, in checkargs
    return cmdfunc()
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 361, in <lambda>
    d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/util.py", line 715, in check
    return func(*args, **kwargs)
  File "/REDMINE-1/hg-workdir/redmine-bb-all/lib/redmine/scm/adapters/mercurial/redminehelper.py", line 149, in rhlog
    if hg.util.version() >= '1.6':
AttributeError: 'module' object has no attribute 'version'

  1) Error:
test_nodes_in_branch(MercurialAdapterTest):
Redmine::Scm::Adapters::MercurialAdapter::HgCommandAborted: hg exited with non-zero status: 1
    lib/redmine/scm/adapters/mercurial_adapter.rb:306:in `hg'
    lib/redmine/scm/adapters/mercurial_adapter.rb:234:in `nodes_in_branch'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:311:in `test_nodes_in_branch'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:304:in `each'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:304:in `test_nodes_in_branch'
</pre>

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7651 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-25 07:20:14 +00:00
Toshi MARUYAMA 4104741383 Merged r7643 from trunk
scm: mercurial: skip failing unit model tests on below Mercurial 1.5

Tests of non ASCII nor alphabetic nor numeric *named branch* fails on below Mercurial 1.5.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7647 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-24 11:29:38 +00:00
Toshi MARUYAMA 6dac4a499f Merged r7642 from trunk
scm: mercurial: skip failing unit lib tests on below Mercurial 1.5

Tests of non ASCII nor alphabetic nor numeric *named branch* fails on below Mercurial 1.5.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7646 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-24 11:28:51 +00:00
Toshi MARUYAMA e0a8442b09 Merged r7641 from trunk
scm: mercurial: switch rev parameter of extension rhlog() if above Mercurial 1.6 or not

On Mercurial 1.5, following error raises.

<pre>
hg --config extensions.redminehelper=lib/redmine/scm/adapters/mercurial/redminehelper.py \
  --rhbranch default --from default --to 0

abort: unknown revision '"default"'!
</pre>

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7645 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-24 11:28:19 +00:00
Toshi MARUYAMA 6dd11c9558 Merged r7640 from trunk
scm: mercurial: fix extension cmdtable on Mercurial 1.5

Before Mercurial revision "40c06bbf58be":http://www.selenic.com/repo/hg-stable/rev/40c06bbf58be ,
following error raises.

<pre>
Traceback (most recent call last):
  File "/WEB-DOWN/hg-repo/hg-crew/hg", line 27, in <module>
    mercurial.dispatch.run()
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 16, in run
    sys.exit(dispatch(sys.argv[1:]))
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 30, in dispatch
    return _runcatch(u, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 47, in _runcatch
    return _dispatch(ui, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 398, in _dispatch
    cmd, func, args, options, cmdoptions = _parse(lui, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 277, in _parse
    args = fancyopts.fancyopts(args, c, cmdoptions, True)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/fancyopts.py", line 62, in fancyopts
    for short, name, default, comment in options:
ValueError: too many values to unpack

  1) Error:
test_nodes_in_branch(MercurialAdapterTest):
Redmine::Scm::Adapters::MercurialAdapter::HgCommandAborted: hg exited with non-zero status: 1
    lib/redmine/scm/adapters/mercurial_adapter.rb:306:in `hg'
    lib/redmine/scm/adapters/mercurial_adapter.rb:234:in `nodes_in_branch'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:311:in `test_nodes_in_branch'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:304:in `each'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:304:in `test_nodes_in_branch'
</pre>

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7644 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-24 11:27:38 +00:00
Toshi MARUYAMA 1608ca3d98 Merged r7579 from trunk.
Restrict anonymous read access with Redmine.pm

Redmine.pm now also checks for public projects whether the anonymous
user has the browse_repository right for a read operation.

Contributed by Holger Just.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7580 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-04 21:52:08 +00:00
Etienne Massip 0ef89ee4ea Merged r7570 from trunk (#9245).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7578 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-04 19:29:00 +00:00
Toshi MARUYAMA 4813672728 Merged r7571 from trunk.
Fix typo of fix_issue() at Changeset model.

Contributed by Sylvain Utard.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7572 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-04 10:55:32 +00:00
Etienne Massip ade5409310 Merged r7568 from trunk (#9308).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7569 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-03 20:19:44 +00:00
Etienne Massip 605f1745ff Merged #7563 from trunk (#7215).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7564 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-02 17:28:33 +00:00
Etienne Massip 8158a26ee8 Merged #7560 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7561 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-02 15:35:39 +00:00
Etienne Massip 4682acf040 Merged r7558 from trunk (#3276).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7559 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-02 14:52:43 +00:00
Etienne Massip 3955f81b3f Merged r7538 from trunk (#8411).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7539 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-26 17:47:50 +00:00
Etienne Massip 16f56a4677 Merged r7458 from trunk (#7613).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7482 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-23 17:23:22 +00:00
Toshi MARUYAMA f77b83451b Merged r7468 from trunk.
Norwegian translation of trunk r5957 and 1.2-stable r7455 updated.

Contributed by Lars Erik Gullerud.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7471 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-23 10:45:28 +00:00
Toshi MARUYAMA 2f2a93c6ef Merged r7451 and r7454 from trunk.
Slovenian translation updated.

Contributed by Nejc Vidmar.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7455 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-22 14:06:18 +00:00
Toshi MARUYAMA 5c282222a0 Backed out r7442.
Merged r7439 from trunk.

Slovenian translation of trunk r5957 and 1.2-stable r7434 updated.

Contributed by Nejc Vidmar.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7449 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-22 12:28:30 +00:00
Toshi MARUYAMA 61b4f41539 Merged r7439 from trunk.
Slovenian translation of trunk r5957 and 1.2-stable r7434 updated.

Contributed by Nejc Vidmar.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7442 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-22 01:52:04 +00:00
Toshi MARUYAMA 73e27a48e0 Merged r7432 from trunk.
fix typos in lib/redmine/hook.rb.

Contributed by Igor Zubkov.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7434 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-21 09:57:26 +00:00
Toshi MARUYAMA 51d7c568b0 Merged r7407 from trunk.
remove trailing white-spaces from lib/redmine/hook.rb

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7433 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-21 09:56:52 +00:00
Toshi MARUYAMA 51d772de70 Merged r7068 from trunk.
fix typo in imap examples at lib/tasks/email.rake.

Contributed by Nathan L Smith.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7069 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-07 01:07:43 +00:00
Toshi MARUYAMA 86845b1989 Merged r7060 from trunk.
add "ruby test/unit/issue_test.rb" for an each test at doc/RUNNING_TESTS.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7061 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-05 11:45:16 +00:00
Toshi MARUYAMA 723d60a1ce Merge r7033 from trunk.
remove duplicate "test_index_should_not_list_issues_when_module_disabled" from functional issues controller test.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7038 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-02 01:30:33 +00:00
Toshi MARUYAMA b128fcaf0d back out r7036.
I mistook merged revision of the revision comment.
r7035 is wrong. r7033 is correct.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7037 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-02 01:29:54 +00:00
Toshi MARUYAMA 73dd0c49dd Merge r7035 from trunk.
remove duplicate "test_index_should_not_list_issues_when_module_disabled" from functional issues controller test.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7036 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-02 01:15:12 +00:00
Toshi MARUYAMA cc7274f38c Merge r6915 from trunk.
fix grammatical error of field_warn_on_leaving_unsaved in pt-BR.yml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6916 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-31 14:59:35 +00:00
Toshi MARUYAMA d0f3b8fa4d Merge r6600 from trunk.
Hungarian translation for 1.2.1 updated by Csaba Molnár.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6601 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-24 12:56:36 +00:00
Toshi MARUYAMA 2302955bc5 Merge r6021 from trunk (#8825).
scm: fix JRuby tests fail in unit changeset following test.

* test_invalid_utf8_sequences_in_paths_should_be_replaced

Following Subversion functional tests fail on Japanese Windows + JRuby 1.6.2 (ruby-1.8.7-p330).

* test_directory_diff
* test_revision_diff

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6453 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-17 11:14:03 +00:00
Toshi MARUYAMA 90f83db148 Merged r6005 from trunk.
scm: git: skip non UTF-8 path encoding test of unit model test in JRuby.

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.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6452 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-17 08:16:23 +00:00
Toshi MARUYAMA b6dbf26c86 Merged r6004 from trunk.
scm: git: skip non UTF-8 path encoding test of unit adapter test in JRuby.

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.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6451 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-17 08:16:02 +00:00
Toshi MARUYAMA 8c7e0e279c Merged r6003 from trunk.
scm: git: skip non UTF-8 path encoding test of functional test in JRuby.

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.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6450 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-17 08:15:37 +00:00
Toshi MARUYAMA 6f15634e12 Merged r6447 from trunk.
scm: add comment that configuration of SCM executable command does not work if contains spaces path to configuration.yml.example.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6449 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-16 00:18:14 +00:00
Toshi MARUYAMA 7e837aa34d Merged r6418 from trunk.
remove trailing white-spaces from config/configuration.yml.example.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6448 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-16 00:17:56 +00:00
Toshi MARUYAMA 6c89118bac Merged r6441 from trunk.
PDF: remove unused vendor/plugins/rfpdf/lib/barcode/*.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6443 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 09:57:07 +00:00
Toshi MARUYAMA 260c07eb73 Merged r6435 from trunk.
PDF: remove unused sjis.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6442 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 08:29:47 +00:00
Toshi MARUYAMA 7914381cdd Merged r6434 from trunk.
PDF: remove unused zapfdingbats.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6440 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:25:48 +00:00
Toshi MARUYAMA 65ce05326a Merged r6433 from trunk.
PDF: remove unused symbol.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6439 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:25:06 +00:00
Toshi MARUYAMA 112c7a1b15 Merged r6432 from trunk.
PDF: remove unused courier.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6438 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:24:27 +00:00
Toshi MARUYAMA 23a31dfe27 Merged r6431 from trunk.
PDF: remove unused times*.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6437 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:23:43 +00:00
Toshi MARUYAMA 0dc50cb0b1 Merged r6430 from trunk.
PDF: remove unused vera*.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6436 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:23:00 +00:00
Toshi MARUYAMA 88163849b4 Merged r6427 from trunk.
PDF: remove unused vera fonts.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6429 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 05:27:03 +00:00
Toshi MARUYAMA 058f36cc6f Merged r6426 from trunk.
PDF: remove unused FreeMono fonts.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6428 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 05:26:17 +00:00
Toshi MARUYAMA 11cf38a1a8 Merged r6402 from trunk.
PDF: remove unused DejaVu fonts except DejaVuSans-BoldOblique.

FreeSans has freesansbi.rb. But there is no dejavusansbi.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6408 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-06 00:02:17 +00:00
Toshi MARUYAMA 37d7a9d62d Merged r6401 from trunk.
PDF: remove unused DejaVuSans-ExtraLight font.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6407 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-06 00:01:47 +00:00
Toshi MARUYAMA 1b299369bf Merged r6403 from trunk.
Italian translation for 1.2 updated.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6405 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-05 11:24:32 +00:00
Toshi MARUYAMA cbe42633c9 Merged r6282 from trunk.
scm: bazaar: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6294 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:48:38 +00:00
Toshi MARUYAMA 25657168b1 Merged r6281 from trunk.
scm: git: use self.class.sq_bin for command name at adpter scm_cmd().

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6293 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:48:06 +00:00
Toshi MARUYAMA 4852b38efc Merged r6280 from trunk.
scm: git: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6292 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:47:34 +00:00
Toshi MARUYAMA b882993d6a Merged r6279 from trunk.
scm: mercurial: use self.class.sq_bin for command name at adpter scm_cmd().

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6291 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:47:08 +00:00
Toshi MARUYAMA b6c46aa19d Merged r6278 from trunk.
scm: mercurial: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6290 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:46:35 +00:00
Toshi MARUYAMA 0903db52d9 Merged r6277 from trunk.
scm: cvs: use self.class.sq_bin for command name at adpter scm_cmd().

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6289 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:46:01 +00:00
Toshi MARUYAMA 93d256c4a8 Merged r6276 from trunk.
scm: cvs: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6288 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:45:26 +00:00
Toshi MARUYAMA 64a68b86c6 Merged r6275 from trunk.
scm: darcs: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6287 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:44:44 +00:00
Toshi MARUYAMA 1d79bbce44 Merged r6274 from trunk.
scm: subversion: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6286 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:44:07 +00:00
Toshi MARUYAMA 87211bcb75 Merged r6272 from trunk.
scm: add new method "shell_quote_command" at abstract adapter.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6285 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:43:22 +00:00
Toshi MARUYAMA 68e97858cb Merge(backport) r6230 from trunk (#8825).
scm: catch all exceptions at adapter shellout() to fork scm command.

If scm command does not exist,
Linux JRuby 1.6.2 (ruby-1.8.7-p330) raises java.io.IOException in production environment.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6273 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 11:53:39 +00:00
Jean-Philippe Lang f5a6b0cf93 Updates for 1.2.1 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6261 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 11:45:14 +00:00
Toshi MARUYAMA 3cf0bd713d Merged r6247 from trunk.
scm: mercurial: add functional test of destroying invalid repository.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6255 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:08:47 +00:00
Toshi MARUYAMA 36bce52f63 Merged r6246 from trunk.
scm: mercurial: do nothing in fetching if info is nil.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6254 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:08:23 +00:00
Toshi MARUYAMA 94f5c73746 Merged r6245 from trunk.
scm: mercurial: catch exception and return nil during getting info.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6253 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:08:03 +00:00
Toshi MARUYAMA 8b6fd63a59 Merged r6243 from trunk.
scm: mercurial: add functional test of destroying valid repository.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6252 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:07:44 +00:00
Toshi MARUYAMA ba6b822e97 Merged r6242 from trunk.
scm: mercurial: add instance variable @project at functional test.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6251 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:07:19 +00:00
Toshi MARUYAMA b44044a76a Merge(backport) r6130 from trunk (#8777).
scm: return nil at model default_branch and override at git model.

Redmine Git and Mercurial adapter support *branches*.
Mercurial default branch is *dafault*.
But, it is popular to show all revisions on the top page for Mercurial GUI.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6244 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 00:24:22 +00:00
Jean-Philippe Lang eb3a4587c9 Merged r6208 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6209 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 18:49:13 +00:00
Jean-Philippe Lang a8550ba8a6 Merged r6206 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6207 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 12:01:56 +00:00
Jean-Philippe Lang 0527e8cedf Merged r6203 and r6204 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6205 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 11:42:12 +00:00
Jean-Philippe Lang 2a799e8367 Merged r6201 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6202 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 11:26:35 +00:00
Jean-Philippe Lang 3e9ad22fad Merged r6199 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6200 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 10:51:57 +00:00
Jean-Philippe Lang a5bcdf6d2c Backported r6197 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6198 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 09:11:13 +00:00
Jean-Philippe Lang 3dcd5d746a Merged r6187 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6188 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-06 19:06:03 +00:00
Jean-Philippe Lang 971aa889f9 Merged r6163, r6171, r6172, r6174 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6175 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-03 15:58:02 +00:00
Jean-Philippe Lang cdc1dfb1e7 Merged r6170 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6173 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-03 15:37:01 +00:00
Jean-Philippe Lang 30255b8054 Merged r6073 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6162 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-03 10:18:18 +00:00
Jean-Philippe Lang 97b697a678 Merged r6126 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6161 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:43:08 +00:00
Jean-Philippe Lang 8e87cd6f77 Merged r6147 and r6149 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6160 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:29:54 +00:00
Jean-Philippe Lang 65bee7efa3 Merged r6148 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6159 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:28:33 +00:00
Jean-Philippe Lang 2325831d81 Merged r5991 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6158 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:28:00 +00:00
Jean-Philippe Lang c7f8ea6a37 Merged r5969 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6157 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:25:51 +00:00
Toshi MARUYAMA edc4f6d54b PDF: add dummy 'fill' parameter at rfpdf CJK Write method (#8737).
'fill' parameter is already added in trunk by r6131, r6132, r6133.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6156 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 15:44:02 +00:00
Toshi MARUYAMA bf0046b5af PDF: fix ArgumentError MultiCell() in CJK (#8737).
add dummy ln parameter at rfpdf CJK MultiCell method.
ln parameter has already added in trunk by r6131, r6132, r6133.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6155 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 14:59:30 +00:00
Toshi MARUYAMA 3de4afe53a Merged r6146 from trunk.
PDF: add revision number/id of associated revisions on issue PDF.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6153 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 13:15:54 +00:00
Toshi MARUYAMA d15912eb6a Merge(backport) r6136 from trunk (#8737).
PDF: use RDMMultiCell for drawing lines of issue description.

Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6145 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 04:48:07 +00:00
Toshi MARUYAMA 656e651c33 Merge(backport) r6135 from trunk (#8737).
PDF: add 'ln' parameter for drawing lines at RDMMultiCell().

Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6144 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 04:47:27 +00:00
Toshi MARUYAMA 9543e0a103 Merged r6138 from trunk.
PDF: code clean up lib/redmine/export/pdf.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6143 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 04:46:47 +00:00
Toshi MARUYAMA 441f2f216f Merged r6139 from trunk.
Swedish translation updated by Nicklas Holm.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6140 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-01 09:02:37 +00:00
Toshi MARUYAMA 15228c9958 Merged r6127 from trunk.
Escape AuthSources in the list.

Contributed by MAEDA, Go

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6128 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-27 23:19:41 +00:00
Jean-Baptiste Barth 5f33a09320 Merged r6124 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6125 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-26 12:51:09 +00:00
Jean-Baptiste Barth 7d77c3544a Merged r6098 from trunk.
Added Project#enable_module! and Project#disable_module!

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6106 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-21 03:35:36 +00:00
Jean-Baptiste Barth 102c9afadf Revert r6104 "Merged r6098 from trunk."
I messed things up with a cherry-pick on master, I'll re-apply it after.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6105 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-21 03:16:49 +00:00
Jean-Baptiste Barth 16ba6bcb77 Merged r6098 from trunk.
Added Project#enable_module! and Project#disable_module!

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6104 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-20 19:39:59 +00:00
Toshi MARUYAMA df37e5cfab Merged r6101 from trunk.
Russian translation update by SERGEY ERSHOV.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6102 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-20 08:54:23 +00:00
Jean-Baptiste Barth f58b86bbb8 Merged r6099 from trunk.
Added a test to ensure 'Project' column can be removed on issues list

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6100 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-20 01:32:18 +00:00
Toshi MARUYAMA 95f68ba6d9 Merged r6096 from trunk.
pt-BR translation update by Enderson Maia.

Better translation to keep a pattern in translations.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6097 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-18 10:17:16 +00:00
Toshi MARUYAMA 171c4b2747 Merged r6094 from trunk.
German translation updated by Jens Martsch.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6095 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-17 07:13:51 +00:00
Toshi MARUYAMA 860a6ce78d Merged r6068 from trunk.
pt-BR translation update by Rodrigo Rosenfeld Rosas.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6069 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-11 21:15:05 +00:00
Toshi MARUYAMA 26d42c26fa Merged r6064 from trunk.
translate field_path_to_repository in pt-BR.yml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6067 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-11 01:34:32 +00:00
Toshi MARUYAMA c69c434609 Merged r6063 from trunk.
pt-BR translation update by Rodrigo Rosenfeld Rosas.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6066 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-11 01:33:51 +00:00
Toshi MARUYAMA 9381d30ae8 Merged r6062 from trunk.
pt-BR translation update by Enderson Maia.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6065 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-11 01:33:07 +00:00
Toshi MARUYAMA 136bf86307 Merged r6042 from trunk.
scm: mercurial: fix unit adapter annotate test fails on Windows Mercurial 1.8.4+29-e597ef52a7c2.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6046 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-10 08:33:23 +00:00
Toshi MARUYAMA 07f42c53d0 Merged r6041 from trunk.
scm: mercurial: add functional test of annotate file which does not exist in *tip* is not found.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6045 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-10 08:32:42 +00:00
Toshi MARUYAMA 22e143f0b3 Merged r6035 from trunk.
PDF: use DejaVuSans fonts in Vietnamese.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6037 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-10 02:15:47 +00:00
Toshi MARUYAMA 1701de9123 Merged r6034 from trunk.
PDF: back out r6018.

change Vietnamese vi.yml general_pdf_encoding from CP1258 to UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6036 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-10 02:15:30 +00:00
Toshi MARUYAMA 0ce6793181 Merged r6031 from trunk.
PDF: fix font name in vendor/plugins/rfpdf/lib/fonts/dejavusansi.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6033 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 23:51:42 +00:00
Toshi MARUYAMA bacc44feab Merged r6030 from trunk.
PDF: Import DejaVu fonts.

http://rfpdf.googlecode.com/files/DejaVu.zip
Sep. 2007
fils size 3,685,721
md5sum: 54274d105b74f817d649035fc1541d8a

rename files.
* DejaVuSans.rb  to dejavusans.rb
* DejaVuSansb.rb to dejavusansb.rb
* DejaVuSansi.rb to dejavusansi.rb

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6032 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 23:44:34 +00:00
Toshi MARUYAMA 4f9a1cd614 Merged r6028 from trunk.
Spanish translation updated by Jorge López.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6029 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 08:06:24 +00:00
Toshi MARUYAMA 44ed963a46 Merged r6024 from trunk.
PDF: replace all non ASCII characters to '?' if Iconv error raise in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6027 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 05:29:23 +00:00
Toshi MARUYAMA 113316cf1e Merged r6023 from trunk.
PDF: use SJIS instead of CP932 at unit pdf test test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_ja in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6026 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 03:51:23 +00:00
Toshi MARUYAMA 17ed97d580 Merged r6022 from trunk.
PDF: use SJIS instead of CP932 at unit pdf test test_rdm_pdf_iconv_cannot_convert_ja_cp932 in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6025 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 03:50:35 +00:00
Toshi MARUYAMA 19c52bc671 Merged r6018 from trunk.
PDF: change Vietnamese vi.yml general_pdf_encoding from UTF-8 to CP1258.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6019 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 00:04:11 +00:00
Toshi MARUYAMA d15de8ee12 Merged r6013 from trunk.
PDF: use SJIS instead of CP932 at unit pdf test_fix_text_encoding_nil in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6017 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 23:53:42 +00:00
Toshi MARUYAMA 006c82267e Merged r6012 from trunk.
PDF: change Shift_JIS to SHIFT_JIS in lib/redmine/export/pdf.rb for Japanese ja.yml general_pdf_encoding.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6016 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 23:53:24 +00:00
Toshi MARUYAMA 887e7c6781 Merged r6011 from trunk.
PDF: add Japanese comment of ja.yml general_pdf_encoding *CP932* and *SJIS* in JRuby and CRuby (#8565, #61).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6015 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 23:53:03 +00:00
Toshi MARUYAMA 6280d9e9b2 Merged r6010 from trunk.
PDF: add *SJIS* and *Shift_JIS* in lib/redmine/export/pdf.rb for Japanese ja.yml general_pdf_encoding.

JRuby 1.6.2 (ruby-1.8.7-p330) does not support CP932.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6014 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 23:52:43 +00:00
Toshi MARUYAMA 3996d5f42e Merged r6007 from trunk.
scm: add log message of config/configuration.yml if scm command raise Errno::ENOENT exception.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6009 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 13:24:38 +00:00
Toshi MARUYAMA 579abc1802 Merged r6006 from trunk.
scm: code clean up abstract adapter.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6008 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 13:23:56 +00:00
Toshi MARUYAMA dc2efa503a Merged r5999 from trunk.
scm: catch all exceptions to get scm command version in repository model.

If scm command does not exist,
Linux jruby 1.6.2 (ruby-1.8.7-p330) raises java.io.IOException in production environment.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6000 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-03 11:41:34 +00:00
Toshi MARUYAMA 0e6cdeb860 Merged r5992 and r5997 from trunk.
Turkish translation updated by Burak Yiğit Kaya.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5998 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-02 08:26:02 +00:00
Toshi MARUYAMA 3b9ef033bf Backout r5994 Turkish translations.
Tests on CI server fails.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5996 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-02 06:29:15 +00:00
Toshi MARUYAMA 2ae54a0fc1 Merged r5993 from trunk.
change Turkish general_csv_encoding from ISO-8859-1 to ISO-8859-9 by Burak Yiğit Kaya.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5995 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-01 22:55:23 +00:00
Toshi MARUYAMA a87e6e1265 Merged r5992 from trunk.
Turkish translation updated by Burak Yiğit Kaya.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5994 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-01 22:54:58 +00:00
Toshi MARUYAMA 61b1146f9d Merged r5986 from trunk.
German translation updated by Jens Martsch.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5987 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-01 08:09:23 +00:00
Toshi MARUYAMA c509c744fd Merged r5970 from trunk.
Traditional Chinese translation updated by ChunChang Lo.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5971 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-31 03:48:27 +00:00
Jean-Philippe Lang 1be21f2413 Merged r5965 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5967 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-30 16:40:52 +00:00
Jean-Philippe Lang eaf430b630 Merged r5964 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5966 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-30 16:40:17 +00:00
Toshi MARUYAMA d2789248f7 Merged r5962 from trunk.
Bulgarian translation updated by Ivan Cenov.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5963 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 14:54:06 +00:00
Jean-Philippe Lang f08f09a9d3 Merged r5950 to r5960 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5961 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 12:06:05 +00:00
Toshi MARUYAMA 2c2760d041 Merged r5887 from trunk.
scm: replace a tab to two spaces in app/views/settings/_repositories.rhtml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5959 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 11:32:16 +00:00
Toshi MARUYAMA 218e2f32ee Merged r5886 from trunk.
scm: remove trailing white-spaces from app/views/settings/_repositories.rhtml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5958 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 11:31:48 +00:00
Jean-Philippe Lang f2b01aeb4d Merged r5948 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5949 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 08:15:18 +00:00
Jean-Philippe Lang fabf54a368 Merged r5944 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5947 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 07:47:25 +00:00
Jean-Philippe Lang 6b07f86883 Merged r5881 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5946 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 07:24:15 +00:00
Jean-Philippe Lang 36d2ea9a6c Merged r5880 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5945 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 07:18:05 +00:00
Toshi MARUYAMA 2dca48be53 Merged r5940 from trunk.
remove trailing white-spaces from rake redmine:email:test task source.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5943 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-28 03:34:47 +00:00
Toshi MARUYAMA 7678aa9445 Merged r5939 from trunk.
handle a nil user in rake redmine:email:test task.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5942 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-28 03:34:23 +00:00
Toshi MARUYAMA 9c355ee6c3 Merged r5938 from trunk.
use rake task parameter style message if redmine:email:test parameter is blank.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5941 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-28 03:33:55 +00:00
Jean-Philippe Lang 723030e40a Set version to stable.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5879 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-22 09:20:14 +00:00
Jean-Philippe Lang e6ed112d9d 1.2-stable branch added.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5878 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-22 09:17:45 +00:00
Jean-Philippe Lang 1b4a5e5aff Set version to 1.2.0.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5877 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-22 09:17:05 +00:00
Jean-Philippe Lang 7e1f04bdfb Do not propose users that can't view an issue as watchers (#7412).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5876 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-22 09:14:36 +00:00
Toshi MARUYAMA 5543ec5f5a scm: code clean up repositories controller.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5875 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 06:16:19 +00:00
Toshi MARUYAMA 782f7ca3bf scm: remove trailing white-spaces from repositories controller.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5874 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 06:15:34 +00:00
Toshi MARUYAMA 331489e8b8 set svn:eol-style=native app/views/projects/settings/_activities.rhtml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5873 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 04:33:11 +00:00
Toshi MARUYAMA 760168366e set svn:eol-style=native app/views/common/error.html.erb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5872 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 04:26:15 +00:00
Toshi MARUYAMA 61fb6d6e10 scm: git: add unit adapter test of default path_encoding is UTF-8 (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5871 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 02:40:19 +00:00
Toshi MARUYAMA 61c5740a86 scm: git: override "path_encoding" method in adapter (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5870 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 02:39:42 +00:00
Toshi MARUYAMA c9a3d925ca scm: mercurial: add unit adapter test of default path_encoding is UTF-8 (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5869 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 02:38:56 +00:00
Toshi MARUYAMA a1e3cf8218 scm: mercurial: override "path_encoding" method in adapter (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5868 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 02:38:04 +00:00
Toshi MARUYAMA c8309589b6 scm: cvs: add unit adapter test of default path_encoding is UTF-8 (#3462).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5867 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 02:19:38 +00:00
Toshi MARUYAMA 0840ad69ea scm: cvs: override "path_encoding" method in adapter (#3462).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5866 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 02:18:53 +00:00
Toshi MARUYAMA 2c817160ab scm: filesystem: add unit adapter test of default path_encoding is UTF-8 (#2274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5865 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 02:18:07 +00:00
Toshi MARUYAMA cbd1715109 scm: filesystem: override "path_encoding" method in adapter (#2274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5864 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 02:17:34 +00:00
Toshi MARUYAMA 3d4a3315f6 scm: add "path_encoding" method in abstract adapter (#2274, #3462, #2664, #5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5863 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 02:16:51 +00:00
Toshi MARUYAMA 7296315c95 scm: filesystem: code clean up unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5862 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 01:10:47 +00:00
Toshi MARUYAMA eb65817ff9 scm: filesystem: code clean up functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5861 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 01:00:24 +00:00
Toshi MARUYAMA f36d8cacba scm: code clean up app/views/repositories/revisions.rhtml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5860 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 00:59:40 +00:00
Toshi MARUYAMA e4d726bde3 scm: code clean up app/views/repositories/revision.rhtml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5859 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-21 00:58:47 +00:00
Toshi MARUYAMA f1f4362b50 scm: git: brush up model fetch_changesets() comment.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5858 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-19 22:58:38 +00:00
Toshi MARUYAMA 27a491766f Traditional Chinese translation updated by ChunChang Lo (#8400).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5857 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-19 03:57:01 +00:00
Toshi MARUYAMA fe7e8fa590 scm: git: use hash#dup for extra_info in model fetch_changesets().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5856 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-19 02:38:14 +00:00
Toshi MARUYAMA 24d58543be scm: git: add unit model test that revisions ordering is inconsistent in existing database (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5855 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-19 02:17:19 +00:00
Toshi MARUYAMA 9376f6e2c3 scm: git: add unit model test that revisions ordering is consistent in new database (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5854 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-19 02:16:56 +00:00
Toshi MARUYAMA 098655dbd0 scm: git: set revisions ordering inconsistent in existing database (#5357).
Between version 0.9 r2840 (#1406) and version 1.2 r5073 (#7821, #5357),
git revisions are stored as *C-B-A-F-E-D* in database.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5853 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-19 02:16:27 +00:00
Toshi MARUYAMA 8dc8c625f6 remove trailing white-spaces from functional settings controller test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5852 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 11:37:31 +00:00
Toshi MARUYAMA 6fea3e997b remove trailing white-spaces from unit setting test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5851 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 11:36:35 +00:00
Toshi MARUYAMA 7111bdd426 remove trailing white-spaces from reports helper source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5850 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 11:13:45 +00:00
Toshi MARUYAMA 40d9d4f08c remove trailing white-spaces from projects helper source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5849 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 11:13:02 +00:00
Toshi MARUYAMA 9831c27fd0 remove trailing white-spaces from unit document test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5848 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:56:16 +00:00
Toshi MARUYAMA 7a8552cbad remove trailing white-spaces from unit enabled module test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5847 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:55:38 +00:00
Toshi MARUYAMA 59066eaa44 remove trailing white-spaces and an empty line from unit document category test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5846 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:54:54 +00:00
Toshi MARUYAMA a913bc6a9d remove trailing white-spaces from unit default data test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5845 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:54:25 +00:00
Toshi MARUYAMA b2670f4650 remove trailing white-spaces from unit attachment test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5844 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:53:50 +00:00
Toshi MARUYAMA 441985fb24 remove trailing white-spaces from functional documents controller test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5843 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:53:16 +00:00
Toshi MARUYAMA 04b1c974fb remove trailing white-spaces from document observer model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5842 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:52:48 +00:00
Toshi MARUYAMA b86fe9a604 remove trailing white-spaces from enabled module source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5841 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:52:23 +00:00
Toshi MARUYAMA 1150917358 remove trailing white-spaces and an empty line from document category custom field model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5840 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:51:51 +00:00
Toshi MARUYAMA 966390148f remove trailing white-spaces from document category model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5839 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:51:15 +00:00
Toshi MARUYAMA 5e36c24f66 remove trailing white-spaces from mail handler controller source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5838 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:13:08 +00:00
Toshi MARUYAMA 7e308ae375 remove trailing white-spaces from files controller source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5837 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:12:48 +00:00
Toshi MARUYAMA 554c6f0d4a remove trailing white-spaces from attachments controller source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5836 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:12:27 +00:00
Toshi MARUYAMA 5d4e4f241c remove trailing white-spaces and an empty line from activities controller source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5835 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:12:04 +00:00
Toshi MARUYAMA 6eaf34c214 scm: bazaar: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5834 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 07:11:41 +00:00
Toshi MARUYAMA 944829861d remove trailing white-spaces excluding here-documents from unit application helper test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5833 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 02:46:50 +00:00
Toshi MARUYAMA c42fdcd26a remove trailing white-spaces from application helper source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5832 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 02:46:24 +00:00
Toshi MARUYAMA fb41e3dab4 remove trailing white-spaces from issues helper source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5831 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 02:45:59 +00:00
Toshi MARUYAMA 6f0de178f9 remove trailing white-spaces from repositories helper source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5830 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 02:45:35 +00:00
Toshi MARUYAMA 3660e28c05 remove trailing white-spaces from settings helper source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5829 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 02:45:11 +00:00
Toshi MARUYAMA c5554dd65e remove trailing white-spaces from setting model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5828 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 02:19:08 +00:00
Toshi MARUYAMA 71088ed847 remove trailing white-spaces from settings controller source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5827 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 02:18:47 +00:00
Toshi MARUYAMA 1f0ddc3199 scm: mercurial: code clean up unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5826 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-18 02:18:25 +00:00
Toshi MARUYAMA 574511fced remove trailing white-spaces and empty lines from extra/svn/reposman.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5825 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 13:32:08 +00:00
Toshi MARUYAMA 5b8dfe0372 remove trailing white-spaces from wiki controller source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5824 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 04:34:44 +00:00
Toshi MARUYAMA 4eb3af53d0 remove trailing white-spaces from issues controller source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5823 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 04:34:03 +00:00
Toshi MARUYAMA 22e80f04ae remove trailing white-spaces from query model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5822 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 04:33:19 +00:00
Toshi MARUYAMA e357057559 remove trailing white-spaces from issue moves controller source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5821 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 03:59:02 +00:00
Toshi MARUYAMA 6f8e3c031f remove trailing white-spaces from time entry model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5820 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 03:58:41 +00:00
Toshi MARUYAMA 32cb715db9 remove trailing white-spaces from news model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5819 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 03:58:19 +00:00
Toshi MARUYAMA da5140b1ac remove trailing white-spaces from message observer model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5818 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 03:57:57 +00:00
Toshi MARUYAMA c810b9db9c remove trailing white-spaces from message model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5817 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 03:57:34 +00:00
Toshi MARUYAMA 01c5311662 remove trailing white-spaces from mailer model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5816 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 03:57:10 +00:00
Toshi MARUYAMA f2e5b62448 remove trailing white-spaces from mail handler model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5815 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 03:56:45 +00:00
Toshi MARUYAMA fdea829952 remove trailing white-spaces from unit search test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5814 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 02:39:40 +00:00
Toshi MARUYAMA 4e8fab3206 remove trailing white-spaces from unit wiki content test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5813 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 02:38:55 +00:00
Toshi MARUYAMA 817f185e57 remove trailing white-spaces from unit wiki test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5812 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 02:38:09 +00:00
Toshi MARUYAMA 274bd27c54 remove trailing white-spaces from unit wiki page test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5811 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 02:37:04 +00:00
Toshi MARUYAMA 42a367b258 remove trailing white-spaces excluding SQL from issue model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5810 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 02:14:06 +00:00
Toshi MARUYAMA 2d7ce91e80 remove trailing white-spaces from unit mail handler test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5809 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 02:13:19 +00:00
Toshi MARUYAMA 07fe60b639 remove trailing white-spaces from unit journal test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5808 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 01:16:31 +00:00
Toshi MARUYAMA 435e9b326c remove trailing white-spaces and an empty line from unit journal observer test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5807 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 01:16:04 +00:00
Toshi MARUYAMA de13c0007b remove trailing white-spaces and empty lines from unit issue test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5806 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 01:15:35 +00:00
Toshi MARUYAMA 1122fd0e6a remove trailing white-spaces from unit issue nested set test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5805 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-17 01:15:01 +00:00
Toshi MARUYAMA a955a5140b remove trailing white-spaces from unit issues helper test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5804 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 22:56:46 +00:00
Toshi MARUYAMA 5e1576b8b4 remove trailing white-spaces from functional search controller test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5803 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 22:56:25 +00:00
Toshi MARUYAMA dfa509b69e remove trailing white-spaces from functional wiki controller test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5802 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 22:56:04 +00:00
Toshi MARUYAMA 3ec87dd73f remove trailing white-spaces from functional projects controller test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5801 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 22:55:41 +00:00
Toshi MARUYAMA d3a953450e remove trailing white-spaces from functional journals controller test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5800 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 22:55:14 +00:00
Toshi MARUYAMA 13e64ba624 Bulgarian translation updated by Ivan Cenov (#8380).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5799 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 22:54:47 +00:00
Toshi MARUYAMA 0aaa2b1b87 remove trailing white-spaces from unit activity test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5798 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 03:48:44 +00:00
Toshi MARUYAMA 6a5c9ed3c7 remove trailing white-spaces from functional IssuesController test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5797 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 03:48:18 +00:00
Toshi MARUYAMA 596670d615 remove trailing white-spaces from functional activities controller test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5796 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 00:09:58 +00:00
Toshi MARUYAMA 97abb12aeb remove trailing white-spaces from WikiContent model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5795 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-16 00:00:26 +00:00
Toshi MARUYAMA 674a61dc8e remove trailing white-spaces from Document model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5794 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-15 23:52:48 +00:00
Toshi MARUYAMA b829acfb4a remove trailing white-spaces from Attachment model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5793 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-15 23:45:13 +00:00
Toshi MARUYAMA 0f245c0e56 remove trailing white-spaces from changeset model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5792 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-15 23:01:21 +00:00
Toshi MARUYAMA b3ffd36c56 Japanese translation improvement (confirmation messages) by Go MAEDA (#8375).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5791 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-14 09:32:36 +00:00
Toshi MARUYAMA 7f8a73e60d Japanese translation improvement by Go MAEDA (#8372).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5790 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-14 04:51:59 +00:00
Toshi MARUYAMA 4c963cc9dc scm: git: add test of fetching invalid revision in unit model test (#7146).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5789 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 10:39:07 +00:00
Toshi MARUYAMA 7ca5a4939e scm: git: fix fetching 7 days problem (#7146, #6013).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5788 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 10:38:45 +00:00
Toshi MARUYAMA b0f5d3cd88 scm: git: use block to call revisions() in unit adapter test_revisions_invalid_rev() (#7146).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5787 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 08:28:51 +00:00
Toshi MARUYAMA 39930c3f4d scm: git: use block to call revisions() in unit adapter test_revisions_branch_latin_1_path_encoding_with_rev() (#7146).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5786 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 08:28:30 +00:00
Toshi MARUYAMA 763931d584 scm: git: use block to call revisions() in unit adapter test_revisions_branch_latin_1_path_encoding_all() (#7146).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5785 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 08:28:03 +00:00
Toshi MARUYAMA d3d9830936 scm: git: use block to call revisions() in unit adapter test_revisions_master_merged_rev() (#7146).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5784 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 08:27:35 +00:00
Toshi MARUYAMA 5d8bb7904c scm: git: use block to call revisions() in unit adapter test_revisions_master_all() (#7146).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5783 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 08:27:04 +00:00
Toshi MARUYAMA 2cab592b20 scm: subversion: remove trailing white-spaces from unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5782 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 06:18:18 +00:00
Toshi MARUYAMA e5606c8d32 scm: mercurial: remove trailing white-spaces from unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5781 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 06:17:34 +00:00
Toshi MARUYAMA be7cfb949d scm: filesystem: remove trailing white-spaces from unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5780 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 06:16:39 +00:00
Toshi MARUYAMA 06bd7e35c6 scm: darcs: remove trailing white-spaces from unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5779 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 06:15:57 +00:00
Toshi MARUYAMA bfe1993758 scm: cvs: remove trailing white-spaces from unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5778 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 06:15:21 +00:00
Toshi MARUYAMA 38d5925d70 scm: git: back out r5673 (#7146).
recovery "block_given?" in adapter.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5777 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 06:03:26 +00:00
Toshi MARUYAMA 4ea8f1637c scm: git: use symbol instead of string whether reporting last commit in project setting i18n text (#8365).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5776 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 04:34:29 +00:00
Toshi MARUYAMA d65c3d438d scm: git: show only filename and filesize if setting of reporting last commit is disable (#8365, #7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5775 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 03:55:21 +00:00
Toshi MARUYAMA 625b7d9051 scm: update locales of whether reporting last commit for files and directories in project setting (#8365, #7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5774 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 03:54:44 +00:00
Toshi MARUYAMA 13a5032dbe scm: git: add Japanese translation of whether reporting last commit for files and directories in project setting (#8365, #7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5773 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 03:54:07 +00:00
Toshi MARUYAMA 042a7661e3 scm: git: use i18n text whether reporting last commit for files and directories in project setting (#8365, #7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5772 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 03:53:30 +00:00
Toshi MARUYAMA 4cbe231c8c scm: git: add check box of whether reporting last commit for files and directories in project setting (#8365, #7047).
Browsing repository tree performance problem is git only.
So, adding new "report_last_commit" column is very expensive.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5771 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 03:52:56 +00:00
Toshi MARUYAMA 57c5b4ea74 scm: use repository merge_extra_info() to save extra_ parameter (#8365, #7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5770 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 03:52:18 +00:00
Toshi MARUYAMA ab430a13b5 scm: switch to save repository setting params in "extra_" or not (#8365, #7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5769 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 03:51:43 +00:00
Toshi MARUYAMA d21b35d32a scm: git: get "extra_report_last_commit" value from extra_info (#8365, #7047).
Browsing repository tree performance problem is git only.
So, adding new "report_last_commit" column is very expensive.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5768 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-13 03:51:14 +00:00
Toshi MARUYAMA 5ca257181f scm: add a test of a repository model method "merge_extra_info()" in unit test (#7146, #7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5767 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 23:58:58 +00:00
Toshi MARUYAMA 4ee79a60ef scm: add a repository model method "merge_extra_info()" to merge "extra_info" serializing hash yaml (#7146, #7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5766 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 23:58:38 +00:00
Toshi MARUYAMA 9888f13eb0 Bulgarian translation updated by Ivan Cenov (#8358).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5765 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 23:58:17 +00:00
Toshi MARUYAMA ee3cf64d52 scm: git: add test of revisions() with invalid revision in unit adapter test (#7146).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5764 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 23:45:04 +00:00
Toshi MARUYAMA b8850ca9d6 scm: git: output log if revisions() catches an error (#7146).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5763 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 23:44:43 +00:00
Toshi MARUYAMA 30aecd5e25 scm: add "extra_info" column to repositories table and set serialize (#7146, #7047).
This column is for specific SCM.
Git 7 days problem (#7146) can not resolve unless storing branches info in database.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5762 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 17:29:18 +00:00
Toshi MARUYAMA 3e2a67be4f scm: git: add another revision in merged revisions test in unit adapter test (#7146).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5761 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 13:01:10 +00:00
Toshi MARUYAMA 12565cc1ee scm: git: add test of revisions() in merged revisions in unit adapter test (#7146).
Git branch is a reference of specific revision.
Git branch is equivalent with Mercurial *heads*.
http://mercurial.selenic.com/wiki/GitConcepts?action=recall&rev=53#Branch_model

32ae898b7 in git test repository is a merged revision with two heads.
713f49446 and 4a07fe31b *were* in different branches before merged.
713f49446 and 4a07fe31b are descendants of 61b685fbe5.
4a07fe31b is a child of 61b685fbe5.
To get revisions from 713f4944648826f5 to master,
"git log" needs to return 4a07fe31b.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5760 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 13:00:43 +00:00
Toshi MARUYAMA 03ce61bb99 scm: git: add test of "latin_1_path_encoding" branch revisions with from revision in adapter test (#7146).
"latin_1_path_encoding" branch is straight line.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5759 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 12:11:44 +00:00
Toshi MARUYAMA ac3845daaf scm: git: add test of "branch_latin_1_path_encoding" branch all revisions in adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5758 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 12:09:42 +00:00
Toshi MARUYAMA bc06f85cb3 scm: git: rename "test_revisions_master()" to "test_revisions_master_all()" in unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5757 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 12:09:17 +00:00
Toshi MARUYAMA 1a947a1617 scm: mercurial: remove trailing white-spaces from model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5756 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 07:52:14 +00:00
Toshi MARUYAMA 9c09b74dff scm: darcs: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5755 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 07:41:29 +00:00
Toshi MARUYAMA b5130b17a0 scm: filesystem: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5754 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 07:41:08 +00:00
Toshi MARUYAMA fa5f4ff77a scm: subversion: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5753 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 07:16:20 +00:00
Toshi MARUYAMA 850059d0cf scm: bazaar: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5752 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 07:16:00 +00:00
Toshi MARUYAMA 6520d484bf scm: subversion: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5751 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 07:15:39 +00:00
Toshi MARUYAMA cddc5f70a3 scm: git: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5750 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 07:06:57 +00:00
Toshi MARUYAMA 092cfc0229 remove trailing white-spaces from app/controllers/application_controller.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5749 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 04:25:47 +00:00
Toshi MARUYAMA 9121a060a5 Use link_to_user instead of a manual link in my account sidebar (#8345).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5748 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 00:26:58 +00:00
Toshi MARUYAMA 1d78dd8324 HTML escape some user values in account sidebar (#8345).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5747 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 00:26:16 +00:00
Toshi MARUYAMA 16c0b67941 make username a link to their profile page (#8345).
Contributed by Adam Soltys.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5746 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-12 00:25:35 +00:00
Toshi MARUYAMA 398f6dd2fc Russian translation updated by Dmitry Babenko (#8210).
* text_issues_destroy_descendants_confirmation
* field_root_directory
* text_git_repository_note

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5745 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 23:18:42 +00:00
Toshi MARUYAMA b85517ae2a Russian "default_issue_status_rejected" and "default_tracker_feature" changed (#7469, #7464).
Contributed by Dmitry Babenko.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5743 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 22:59:55 +00:00
Toshi MARUYAMA 392a7c3bc2 Hungarian translation for trunk updated by Gábor Takács (#8341).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5741 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 21:52:37 +00:00
Toshi MARUYAMA 308c24104b Hungarian translation for 1.1.3 updated by Gábor Takács (#8340).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5740 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 21:52:16 +00:00
Toshi MARUYAMA e5e8f889f5 set svn:eol-style=native sr-YU.yml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5739 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 10:30:24 +00:00
Toshi MARUYAMA 3907900ec6 set svn:eol-style=native mn.yml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5738 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 10:29:37 +00:00
Toshi MARUYAMA 26684541c1 set svn:eol-style=native mk.yml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5737 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 10:28:28 +00:00
Toshi MARUYAMA 8ce41f900f Fix newline 'LF' to 'CRLF' in sr-YU.yml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5736 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 10:27:25 +00:00
Toshi MARUYAMA 0a07cec7bd set svn:eol-style=native lv.yml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5735 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 10:27:19 +00:00
Toshi MARUYAMA d9e549fa4d Fix newline 'LF' to 'CRLF' in mn.yml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5734 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 10:26:39 +00:00
Toshi MARUYAMA 2c993df47d Fix newline 'LF' to 'CRLF' in mk.yml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5733 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 10:25:52 +00:00
Toshi MARUYAMA 8dba849a89 Fix newline 'LF' to 'CRLF' in lv.yml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5732 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-11 10:25:07 +00:00
Toshi MARUYAMA d778281881 scm: subversion: set svn:eol-style=native adapter source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5731 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-10 17:52:56 +00:00
Toshi MARUYAMA ed6618a4eb Basque translation updated by Ales Zabala Alava (#8330).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5730 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-10 17:48:49 +00:00
Toshi MARUYAMA e96bf8adfe set svn:eol-style=native Basque eu.yml (#8330).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5729 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-10 17:41:54 +00:00
Toshi MARUYAMA 76051ab4b2 Fix newline 'LF' to 'CRLF' in Basque eu.yml (#8330).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5728 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-10 17:36:51 +00:00
Toshi MARUYAMA 653884f27b scm: change separator between command and version ',' to '|' in setting (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5727 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-10 11:42:48 +00:00
Toshi MARUYAMA 5fe5e3dba3 scm: change i18n key name 'text_scm_version' to 'text_scm_command_version' in setting (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5726 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-10 11:42:26 +00:00
Toshi MARUYAMA 77b102c3df Traditional Chinese translation updated by ChunChang Lo (#8327).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5725 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-10 11:41:59 +00:00
Toshi MARUYAMA 2714f6bcac remove trailing white-spaces from lib/tasks/locales.rake.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5724 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-10 11:41:30 +00:00
Toshi MARUYAMA 0418774f50 PDF: more strict Redmine TCPDF class initialize() (#8312).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5723 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-10 01:03:28 +00:00
Toshi MARUYAMA f3a069281e scm: git: fix incorrect comment in unit model test and code clean up unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5722 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 15:26:50 +00:00
Toshi MARUYAMA b97087bad5 PDF: remove unused Redmine FPDF class (#8312).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5721 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 11:12:48 +00:00
Toshi MARUYAMA 29f6dd2a9e PDF: import CJK patches and all languages use TCPDF (#8312).
Contributed Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5720 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 11:12:27 +00:00
Toshi MARUYAMA 3b50809423 PDF: code clean up lib/redmine/export/pdf.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5719 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 10:52:08 +00:00
Toshi MARUYAMA 5742f78bd1 PDF: switch encoding and font whether CJK and Thainland non UTF-8 or not in TCPDF Redmine class (#8312).
Contributed Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5718 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 10:41:02 +00:00
Toshi MARUYAMA ba2fb5340e PDF: import tcpdf.rb patch (#8312).
Contributed Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5717 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 07:35:02 +00:00
Toshi MARUYAMA 48a6fb45a7 PDF: replace invalid UTF-8 sequences in TCPDF (#61, #8312).
There is no guarantees that database strings are valid UTF-8 in Ruby 1.8 MySQL and SQLite3.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5716 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 06:46:21 +00:00
Toshi MARUYAMA e25dd95389 PDF: replace invalid sequence in converting if encoding destination is UTF-8 (#61, #8312).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5715 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 06:45:40 +00:00
Toshi MARUYAMA a5d528c6c2 PDF: call Redmine::Export::PDF::RDMPdfEncoding::rdm_pdf_iconv() directly in unit test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5714 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 06:44:59 +00:00
Toshi MARUYAMA 32a52a6540 PDF: move fix_text_encoding() logic to new method for common use in FPDF and TCPDF (#61, #8312).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5713 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 06:44:23 +00:00
Toshi MARUYAMA 0681d086e2 PDF: check Japanese general_pdf_encoding is CP932 in unit test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5712 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 06:43:23 +00:00
Toshi MARUYAMA 23a27bd6e4 scm: fix indents of test/unit/changeset_test.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5711 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-09 04:54:37 +00:00
Toshi MARUYAMA e28ac7f880 remove trailing white-spaces from MailHandler model source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5710 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 21:28:54 +00:00
Toshi MARUYAMA a05a2e0c4d scm: code clean up unit repository test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5709 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 14:08:46 +00:00
Toshi MARUYAMA 615c81f3df scm: code clean up Repositories Controller.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5708 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 09:47:42 +00:00
Toshi MARUYAMA e68206852e remove trailing white-spaces and code clean up init i18n test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5707 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 07:12:34 +00:00
Toshi MARUYAMA ab768cecdd scm: cvs: remove trailing white-spaces from functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5706 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 05:11:22 +00:00
Toshi MARUYAMA c29bc896cc scm: subversion: remove trailing white-spaces from unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5705 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 05:10:45 +00:00
Toshi MARUYAMA f289d4e354 scm: mercurial: remove trailing white-spaces from unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5704 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 05:10:05 +00:00
Toshi MARUYAMA 1952439ea0 scm: filesystem: remove trailing white-spaces from unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5703 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 05:09:25 +00:00
Toshi MARUYAMA 12bad10573 scm: cvs: remove trailing white-spaces from unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5702 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 05:08:44 +00:00
Toshi MARUYAMA 9cb76de334 scm: subversion: remove trailing white-spaces from functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5701 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 05:08:05 +00:00
Toshi MARUYAMA 3a5cf54128 scm: git: remove trailing white-spaces from unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5700 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 02:49:41 +00:00
Toshi MARUYAMA 541a56d6e8 scm: git: add test of annotate non ASCII content of non ASCII path in functional test.
TODO: this test fails in Ruby 1.9 and Encoding.default_external is not UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5699 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 02:39:36 +00:00
Toshi MARUYAMA 099c8a6608 scm: git: add test of diff non ASCII path and non ASCII content in functional test.
TODO: this test fails in Ruby 1.9 and Encoding.default_external is not UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5698 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 02:38:36 +00:00
Toshi MARUYAMA 6eb8b5fb4a scm: git: add test of showing non ASCII contents of non ASCII path in functional test.
TODO: this test fails in Ruby 1.9 and Encoding.default_external is not UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5697 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 02:04:11 +00:00
Toshi MARUYAMA 02b43944e3 scm: git: use constant value for project id in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5696 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 01:48:53 +00:00
Toshi MARUYAMA 673fe7f372 PDF: set lang 'ja' in unit test test_fix_text_encoding_cannot_convert_ja_cp932().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5695 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-08 00:26:13 +00:00
Toshi MARUYAMA 99693d644c scm: git: fix functional annotate test.
Test committer is "jsmith". If committer is not "jsmith", test passes.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5694 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 23:10:27 +00:00
Toshi MARUYAMA 4fe71148f6 scm: git: remove trailing white-spaces from functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5693 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 23:09:42 +00:00
Toshi MARUYAMA cccbee024e scm: mercurial: add test of annotate non ASCII contents in functional test.
TODO: this test fails in Ruby 1.9 and Encoding.default_external is not UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5692 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 14:22:42 +00:00
Toshi MARUYAMA fa1fe47191 scm: mercurial: fix indent test_annotate_latin_1_path() in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5691 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 14:10:43 +00:00
Toshi MARUYAMA 5c2c85a68a scm: mercurial: add test of showing non ASCII contents in functional test.
TODO: this test fails in Ruby 1.9 and Encoding.default_external is not UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5690 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 13:36:07 +00:00
Toshi MARUYAMA ff6a86364e scm: mercurial: add test of diff non ASCII path name in functional test.
TODO: this test fails in Ruby 1.9 and Encoding.default_external is not UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5689 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 13:35:31 +00:00
Toshi MARUYAMA c5257f6e0d scm: add test of showing *real* non ASCII contents in functional filesystem repository test.
TODO: this test fails in Ruby 1.9 and Encoding.default_external is not UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5688 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 11:28:21 +00:00
Toshi MARUYAMA c4b58726e6 fix typo "heigth" to "height" in lib/redmine/helpers/gantt.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5687 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 09:50:39 +00:00
Toshi MARUYAMA ab6b848304 scm: mercurial: code clean up functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5686 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 07:25:53 +00:00
Toshi MARUYAMA f157ecb91a scm: mercurial: change Latin-1 path test methods name.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5685 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 07:25:09 +00:00
Toshi MARUYAMA e78bc574c2 remove trailing white-spaces from functional functional attachments controller test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5684 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 06:47:05 +00:00
Toshi MARUYAMA 2c08b71e8f scm: mercurial: remove trailing white-spaces and a empty line from functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5683 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 06:38:45 +00:00
Toshi MARUYAMA 20f5b6b45d scm: filesystem: remove trailing white-spaces from functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5682 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 06:38:04 +00:00
Toshi MARUYAMA 9c01d83951 remove trailing white-spaces from attachments helper.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5681 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 05:51:39 +00:00
Toshi MARUYAMA 5da0151bfb scm: filesystem: change i18n l() parameter in setting from string to symbol.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5680 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 03:43:58 +00:00
Toshi MARUYAMA bd26c9666d scm: bazaar: change i18n l() parameter in setting from string to symbol.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5679 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 03:43:17 +00:00
Toshi MARUYAMA 9f8ede65b5 scm: cvs: change i18n l() parameter in setting from string to symbol.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5678 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 03:42:26 +00:00
Toshi MARUYAMA 530151e1d9 scm: git: change i18n l() parameter in setting from string to symbol.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5677 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 03:41:46 +00:00
Toshi MARUYAMA dc8968b03e scm: mercurial: change i18n l() parameter in setting from string to symbol.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5676 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 03:41:05 +00:00
Toshi MARUYAMA ed296ec9c6 scm: darcs: change i18n l() parameter in setting from string to symbol.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5675 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-07 03:40:34 +00:00
Toshi MARUYAMA f69572b956 scm: git: change local value "revisions" name to "revs" in adapter revisions().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5674 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 13:49:33 +00:00
Toshi MARUYAMA 1194235faa scm: git: remove unused "block_given?" from adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5673 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 13:49:10 +00:00
Toshi MARUYAMA e9e477426a scm: remove trailing white-spaces from abstract adapter source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5672 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 13:48:36 +00:00
Toshi MARUYAMA 2db0475454 scm: subversion: remove trailing white-spaces from adapter source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5671 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 13:48:07 +00:00
Toshi MARUYAMA 6d75ac6560 scm: filesystem: remove trailing white-spaces from adapter source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5670 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 12:58:14 +00:00
Toshi MARUYAMA dafdcf3879 scm: darcs: remove trailing white-spaces from adapter source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5669 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 12:57:54 +00:00
Toshi MARUYAMA a49339c646 scm: bazaar: remove trailing white-spaces from adapter source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5668 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 12:57:32 +00:00
Toshi MARUYAMA 19098302ea scm: mercurial: remove trailing white-spaces from adapter source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5667 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 12:57:10 +00:00
Toshi MARUYAMA 59d82995fe scm: git: add unit adapter test of master branch revisions().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5666 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 11:45:58 +00:00
Toshi MARUYAMA e6fe554d43 scm: git: remove trailing white-spaces from adapter source.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5665 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 11:45:20 +00:00
Toshi MARUYAMA e6e0578d29 PDF: fix automatic line break problem with TCPDF (#8310).
Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5664 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 10:40:40 +00:00
Toshi MARUYAMA 479d9380a7 remove trailing white-spaces lib/redmine/export/pdf.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5663 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 10:40:12 +00:00
Toshi MARUYAMA 2711f4c745 remove trailing white-spaces lib/redmine/helpers/gantt.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5662 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 10:39:45 +00:00
Toshi MARUYAMA 773b248669 scm: git: change model report_last_commit() name to extra_report_last_commit() (#7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5661 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 03:43:11 +00:00
Toshi MARUYAMA 1ea1606007 scm: git: split unit adapter revisions test to with time or not (#7146, #6013).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5660 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 02:06:29 +00:00
Toshi MARUYAMA 0d942beb49 scm: git: remove trailing white-spaces and an empty line in unit lib test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5659 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 02:06:08 +00:00
Toshi MARUYAMA c33be450e7 scm: code clean up unit repository test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5658 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-06 01:11:50 +00:00
Toshi MARUYAMA 114e3f3b82 scm: git: use the model value of whether reporting last commit in repository tree (#7047).
And remove entries_git() and the flag in adapter.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5657 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 11:43:29 +00:00
Toshi MARUYAMA 03fb61a782 scm: git: add the model method whether reporting last commit in repository tree (#7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5656 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 11:43:09 +00:00
Toshi MARUYAMA 12f4b8b6d9 scm: git: override entries() in model for browsing tree performance (#7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5655 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 11:42:46 +00:00
Toshi MARUYAMA 931fd58de6 scm: git: use report_last_commit option in unit adapter test (#7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5654 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 11:42:24 +00:00
Toshi MARUYAMA fbdbdf96fe scm: code clean up repository model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5653 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 07:30:22 +00:00
Toshi MARUYAMA 9c3a9fdd87 scm: git: fix indent in model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5652 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 06:13:23 +00:00
Toshi MARUYAMA 919bf61cae PDF: wrap title fields properly (#8295).
Contributed Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5651 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 05:34:16 +00:00
Toshi MARUYAMA 973f3eb50e scm: remove trailing white-spaces in unit changeset test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5650 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 04:23:23 +00:00
Toshi MARUYAMA c17a78c771 scm: mercurial: fix unit model test fails if hg command is unavailable.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5649 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 04:23:07 +00:00
Toshi MARUYAMA 6f4461830c scm: fix invalid UTF-8 tests fail on Windows Ruby 1.8.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5648 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 04:22:49 +00:00
Toshi MARUYAMA 86d9ea32db scm: code clean up repository model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5647 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-05 01:30:24 +00:00
Toshi MARUYAMA 2336093739 scm: git: add comments of revision order in fetch_changesets().
Related issues.
#5357, #6013, #7146, #4773, #4547, #1406, #3449, #3567.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5644 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 23:38:11 +00:00
Toshi MARUYAMA a7c178f6a6 scm: git: rearrange fetch_changesets() comment.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5643 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 23:36:57 +00:00
Toshi MARUYAMA 19a9cba214 scm: git: call entries_git() in adapter entry() for browsing tree performance (#7047).
cat/diff/blame link calls adapter entry().
Abstract adapter entry() calls adapter entries().
Git adapter entries() is very slow.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5642 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 18:09:13 +00:00
Toshi MARUYAMA 193af67f99 scm: git: call entries_git() in adapter entriese() for browsing tree performance (#7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5641 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 18:08:30 +00:00
Toshi MARUYAMA 18df827244 scm: git: override adapter entry() for browsing tree performance (#7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5640 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 18:07:50 +00:00
Toshi MARUYAMA 97b4ee2fef scm: git: split adapter entries() for browsing tree performance (#7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5639 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 18:07:15 +00:00
Toshi MARUYAMA 905a809774 scm: add "options" parameter in adapter entries().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5638 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 14:11:25 +00:00
Toshi MARUYAMA 8df05b9a6d scm remove trailing white-spaces in abstract adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5637 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 13:16:10 +00:00
Toshi MARUYAMA 741967ae68 scm: subversion: set available version above 1.3 (#4273, #1604).
"--xml" options are introduced in 1.3.
http://subversion.apache.org/docs/release-notes/1.3.html

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5636 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 08:26:38 +00:00
Toshi MARUYAMA bba6199e51 scm: subversion: fix newline 'LF' to 'CRLF' and remove trailing white-space.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5635 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 08:25:04 +00:00
Toshi MARUYAMA 4924b99ff9 scm: update locales of the feature of SCM command availability automatic check in administration panel (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5634 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 07:50:05 +00:00
Toshi MARUYAMA 20c6dfd1af scm: add Japanese translation of the feature of SCM command availability automatic check in administration panel (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5633 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 07:49:39 +00:00
Toshi MARUYAMA 84b5a6e7b5 scm: add the feature of SCM command availability automatic check in administration panel (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5632 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 07:49:02 +00:00
Toshi MARUYAMA fb6c9a1396 scm: refactor projects/settings/_repository.rhtml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5631 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 06:35:49 +00:00
Toshi MARUYAMA 956e8af591 scm: cvs: fix loss non ASCII paths if path_encoding is '' (#3462).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5630 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 05:02:44 +00:00
Toshi MARUYAMA d6a483684b scm: filesystem: fix loss non ASCII paths if path_encoding is '' (#2274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5629 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 05:02:01 +00:00
Toshi MARUYAMA 7575989c78 scm: git: fix loss non ASCII paths if path_encoding is '' (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5628 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 05:01:28 +00:00
Toshi MARUYAMA ee7fe09b1e scm: mercurial: fix loss non ASCII paths if path_encoding is '' (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5627 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 05:00:57 +00:00
Toshi MARUYAMA ff77ecee86 scm: code clean up projects/settings/_repository.rhtml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5626 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 05:00:16 +00:00
Toshi MARUYAMA 69bb041c46 scm: set disable a button if scm is not selected in project scm setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5625 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 04:59:28 +00:00
Toshi MARUYAMA 19c6266a7d scm: git: refactor saving a revision in model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5624 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 03:44:10 +00:00
Toshi MARUYAMA cd34602b4f Fix a typo in Czech localization (#8285, #7390).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5621 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 00:33:11 +00:00
Toshi MARUYAMA 7fa85fabae Simplified Chinese translation updated by Sam Qiu (#8286).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5620 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-04 00:32:41 +00:00
Toshi MARUYAMA 5dbaffd094 scm: code clean up app/views/projects/settings/_repository.rhtml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5619 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-03 07:33:46 +00:00
Toshi MARUYAMA 7ada45d3a2 scm: code clean up RepositoriesHelper.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5618 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-03 07:33:19 +00:00
Toshi MARUYAMA ca5ce92cfc scm: code clean up RepositoriesController.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5617 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-03 07:32:50 +00:00
Toshi MARUYAMA 18d0618007 scm: space cleanup in unit repository test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5615 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-02 23:07:38 +00:00
Toshi MARUYAMA 0a132e48f9 Fix typos in public/help/wiki_syntax_detailed.html.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5614 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-02 23:07:16 +00:00
Toshi MARUYAMA ed7091cda1 Fix potential Execution After Redirect bugs.
Execution After Redirect (EAR) happens when redirect in a controller is
triggered but there still is code that is executed in the action.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5611 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-01 23:15:03 +00:00
Toshi MARUYAMA 8632efcce2 Add missing fixture when running tests from scratch in functional RolesControllerTest.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5610 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-01 23:14:28 +00:00
Toshi MARUYAMA bd4af1b9cb Fixed wiki TOC hierarchy for RTL locales (#8088).
Contributed by Mohammad Ebrahim Mohammadi Panah.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5609 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-30 10:13:02 +00:00
Toshi MARUYAMA daeebe144a Fixed hierarchy appearance for subtasks and admin projects view (#8088).
Contributed by Mohammad Ebrahim Mohammadi Panah.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5608 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-30 10:12:41 +00:00
Toshi MARUYAMA f64666f4b4 Fixed colorful indentation and "my projects" mark positioning in projects view for RTL locales (#8088).
Contributed by Mohammad Ebrahim Mohammadi Panah.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5607 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-30 10:12:20 +00:00
Toshi MARUYAMA 8d67224fe1 Show colorful indentation of subprojects on right in RTL locales (#8088).
Contributed by Mohammad Ebrahim Mohammadi Panah.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5606 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-30 10:11:58 +00:00
Toshi MARUYAMA 46bd78aa21 PDF: fix automatic line break in Chinese PDF (#5629).
Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5605 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-30 05:58:15 +00:00
Toshi MARUYAMA 880e8e575a Wrap long text fields properly in PDF exports (#5629).
Contributed by Hugo Ferreira.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5604 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-30 00:29:22 +00:00
Jean-Philippe Lang 93fabf23ae Fixes an assertion for postgresql (#7097).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5603 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 13:33:15 +00:00
Jean-Philippe Lang fdb0151869 Fixed: notes are lost when copying issue(s) (#6901, #8239).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5602 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 13:27:50 +00:00
Jean-Philippe Lang 88a93d7e10 Fixed: copying an issue keeps the author of the original issue (#6901).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5601 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 12:41:07 +00:00
Jean-Philippe Lang c9f31f0332 Adds context menu for related issues on version view.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5600 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 12:18:00 +00:00
Jean-Philippe Lang fb0641d43f Moved the version summary to the right of related issues.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5599 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 12:05:18 +00:00
Toshi MARUYAMA c47144a14f PDF: use explicit return value in Redmine::Export::PDF.fix_text_encoding() (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5598 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 11:53:24 +00:00
Toshi MARUYAMA 67c85251c3 Russian translation updated by Kirill Bezrukov (#8210).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5597 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 11:34:33 +00:00
Jean-Philippe Lang 57f63d513c Makes 'This week' filter work with any starting day of week (#7097).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5596 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 11:28:27 +00:00
Jean-Philippe Lang 07df1242b9 Persian Translation update by Behrang Noroozinia (#7418).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5595 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 10:42:16 +00:00
Jean-Philippe Lang 4673f0cf31 Updates for 1.1.3 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5593 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 09:24:32 +00:00
Jean-Philippe Lang fab9aca747 Fixed: selected modules are not activated when copying a project (#8244).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5581 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 07:26:45 +00:00
Toshi MARUYAMA 02c5577a26 PDF: add test of ensuring 'ASCII-8BIT' encoding in Ruby 1.9 (#61).
Japanese CP932(Shift_JIS) and Traditional Chinese Big5 have 0x5c(backslash) problem,
and these are incompatible with ASCII.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5566 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 05:35:51 +00:00
Toshi MARUYAMA f62605c636 PDF: fix 0x5c(backslash) escape processing in FPDF (#61).
Japanese CP932(Shift_JIS) and Traditional Chinese Big5 have 0x5c(backslash) problem.

Contributed Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5565 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-29 05:35:26 +00:00
Toshi MARUYAMA ed3efeb960 use same word "e.g." of git repository note with mercurial in Bulgarian translation (#8248).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5564 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-28 23:05:08 +00:00
Toshi MARUYAMA 0566e453e1 Bulgarian translation updated by Ivan Cenov (#8248).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5563 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-28 23:04:46 +00:00
Toshi MARUYAMA c5195c8972 code clean up app/views/admin/info.rhtml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5562 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-28 12:35:25 +00:00
Toshi MARUYAMA 363d9de8bb scm: subversion: code clean up functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5561 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-28 11:24:02 +00:00
Toshi MARUYAMA 828ce5d227 code clean up lib/tasks/extract_fixtures.rake.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5560 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-28 07:10:13 +00:00
Toshi MARUYAMA d5b97d49c6 code clean up MailHandlerTest unit test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5559 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-28 07:09:52 +00:00
Toshi MARUYAMA d3737db6b5 Delete doc/git.rdoc.
http://www.redmine.org/projects/redmine/wiki/Contribute?version=27 has the github mirror link.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5557 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-27 22:40:53 +00:00
Toshi MARUYAMA 1721148bae Remove obsolete github descriptions from doc/git.rdoc.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5555 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-27 14:04:27 +00:00
Toshi MARUYAMA ba807648ea Fix notice_failed_to_save_issues format in es, gl and ca locales (#8235).
Contributed by Jose M. Prieto.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5553 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-27 10:47:23 +00:00
Toshi MARUYAMA ef4219b9f5 add a suggestion for Redmine administrator on the 500 error page.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5552 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-27 00:21:35 +00:00
Toshi MARUYAMA c2503bc56c change 'redMine' to 'Redmine' on error pages.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5551 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-27 00:21:14 +00:00
Toshi MARUYAMA 6da0d5d366 code clean up AdminController.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5550 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-25 23:21:34 +00:00
Toshi MARUYAMA d1eb1fb07d change tabs to spaces in lib/redmine/version.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5549 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-25 23:21:06 +00:00
Toshi MARUYAMA 20c6a278ad Traditional Chinese translation updated by ChunChang Lo (#8219).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5548 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-25 05:55:32 +00:00
Toshi MARUYAMA f4745d4960 scm: bazaar: code clean up unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5547 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-25 02:02:44 +00:00
Toshi MARUYAMA 3597c8b909 Fix typos and add some missing Danish translations by Christian Pedersen (#8218).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5546 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-24 11:52:24 +00:00
Toshi MARUYAMA 92023176b8 scm: bazaar: code clean up adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5545 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-24 09:55:51 +00:00
Toshi MARUYAMA fb9fed39fe scm: git: code clean up adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5544 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-24 09:55:26 +00:00
Toshi MARUYAMA f29a4dd6c5 scm: mercurial: update locales for repository note in setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5543 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 09:25:31 +00:00
Toshi MARUYAMA 80d126d003 scm: mercurial: translate Japanese i18n text of repository note in setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5542 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 09:24:53 +00:00
Toshi MARUYAMA 7fe397e8fd scm: mercurial: use i18n text of repository note in setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5541 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 09:24:23 +00:00
Toshi MARUYAMA c2b0a5bee0 scm: git: update locales for repository note in setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5540 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 09:23:49 +00:00
Toshi MARUYAMA f7bed294c1 scm: git: translate Japanese i18n text of repository note in setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5539 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 09:23:15 +00:00
Toshi MARUYAMA d03de4449f scm: git: use i18n text of repository note in setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5538 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 09:22:47 +00:00
Toshi MARUYAMA 058766b92a scm: cvs: update locales for 'CVSROOT' and 'Module' setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5537 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 07:41:16 +00:00
Toshi MARUYAMA 592825d241 scm: cvs: add Japanese string at 'CVSROOT' and 'Module' setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5536 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 07:40:51 +00:00
Toshi MARUYAMA 7e77d5ddf9 scm: cvs: use i18n string at 'CVSROOT' and 'Module' setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5535 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 07:40:23 +00:00
Toshi MARUYAMA fbde32341e scm: filesystem: update locales for 'Root directory' setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5534 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 07:39:31 +00:00
Toshi MARUYAMA 8749b98b93 scm: filesystem: add Japanese string at 'Root directory' setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5533 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 07:39:01 +00:00
Toshi MARUYAMA 25d6ed38b6 scm: filesystem: use i18n string at 'Root directory' setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5532 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 07:38:32 +00:00
Toshi MARUYAMA 50cb5921b5 scm: update locales for 'Path to repository' setting in Mercurial, Git, Bazaar and Darcs.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5531 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 07:38:03 +00:00
Toshi MARUYAMA 7e3de248c3 scm: add Japanese string at 'Path to repository' setting in Mercurial, Git, Bazaar and Darcs.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5530 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 07:37:33 +00:00
Toshi MARUYAMA 36eac0dc8d scm: use i18n string at 'Path to repository' setting in Mercurial, Git, Bazaar and Darcs.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5529 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 07:37:03 +00:00
Toshi MARUYAMA 82d5de4b4e scm: mercurial: change "url" human attribute name from "Root directory" to "Path to repository".
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5528 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 04:41:26 +00:00
Toshi MARUYAMA 8696835b42 scm: darcs: change "url" human attribute name from "Root directory" to "Path to repository".
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5527 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 04:40:45 +00:00
Toshi MARUYAMA 7ad046f53d scm: bazaar: change "url" human attribute name from "Root directory" to "Path to repository".
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5526 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 04:40:04 +00:00
Toshi MARUYAMA 8c853fe66f scm: update locales for path encoding setting note (#2274, #2664, #3462, #5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5525 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 03:37:42 +00:00
Toshi MARUYAMA 794abbf324 scm: add Japanese string at path encoding setting note (#2274, #2664, #3462, #5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5524 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 03:37:16 +00:00
Toshi MARUYAMA 2a2e6d71e3 scm: use i18n string at path encoding setting note (#2274, #2664, #3462, #5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5523 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 03:36:52 +00:00
Toshi MARUYAMA 582b3a0008 scm: update locales for path encoding setting (#2274, #2664, #3462, #5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5522 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 03:36:26 +00:00
Toshi MARUYAMA f97b9ea02c scm: add Japanese translation "field_scm_path_encoding" (#2274, #2664, #3462, #5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5521 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 03:35:57 +00:00
Toshi MARUYAMA 379503b591 scm: use i18n string at path encoding setting (#2274, #2664, #3462, #5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5520 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 03:35:17 +00:00
Toshi MARUYAMA bb929f4f75 scm: use i18n string at commit log encoding setting (#1735).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5519 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 03:34:43 +00:00
Toshi MARUYAMA d67e4ff2f4 scm: change line order of locale key "field_commit_logs_encoding" in English, French and Japanese (#1735).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5518 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 01:20:57 +00:00
Toshi MARUYAMA a20a75817e scm: change locale key name "setting_commit_logs_encoding" to "field_commit_logs_encoding" (#1735).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5517 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 01:20:12 +00:00
Toshi MARUYAMA 2dc0875a72 scm: cvs: fix mistake human attribute names of root_url and url.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5516 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 00:25:32 +00:00
Toshi MARUYAMA 6d0f8f1db9 scm: code clean up RepositoriesHelper.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5515 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-23 00:25:03 +00:00
Toshi MARUYAMA 109b248e9c Fix Russian translation "label_overview" by Dmitry Babenko (#8210).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5514 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-22 14:51:16 +00:00
Toshi MARUYAMA 479f6674da Russian translation updated by Kirill Bezrukov (#8210).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5513 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-22 11:51:40 +00:00
Toshi MARUYAMA 97677748ba scm: add missing fixtures when running tests from scratch in unit changeset test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5512 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-22 07:13:56 +00:00
Toshi MARUYAMA f164adfb50 Fix Polish and Swedish translations to work with psych (#8209).
Contributed by Gregor Schmidt.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5511 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-21 23:25:01 +00:00
Toshi MARUYAMA 3c4eb22b99 Fix Hebrew translations to work with psyc (#8209).
Contributed by Gregor Schmidt.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5510 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-21 23:24:38 +00:00
Toshi MARUYAMA 031af32770 fix erroneous string starting with '%' in locale yamls (#8209).
Contributed by Gregor Schmidt.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5509 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-21 23:24:14 +00:00
Toshi MARUYAMA 80e4ad63bd change i18n files to use valid yaml syntax that may be parsed by psych (#8209).
Contributed by Gregor Schmidt.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5508 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-21 23:23:38 +00:00
Toshi MARUYAMA 79fb4a4c35 Traditional Chinese translation updated by ChunChang Lo (#8204).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5507 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-21 07:59:52 +00:00
Toshi MARUYAMA 8dcde8fc59 scm: code clean up RepositoriesHelper.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5506 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-20 07:16:23 +00:00
Toshi MARUYAMA 3b22d12c9c Bulgarian translation updated by Ivan Cenov (#8179).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5505 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-19 00:44:49 +00:00
Toshi MARUYAMA 32cec1b172 Swedish translation updated by Nicklas Holm (#8173).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5504 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-18 10:34:03 +00:00
Toshi MARUYAMA fab0344286 Simplified Chinese translation updated by Peng Wang (#7278).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5502 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-18 04:26:48 +00:00
Toshi MARUYAMA 346cee061f Czech translation updated by Lubor Nosek (#7390).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5500 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 23:39:39 +00:00
Toshi MARUYAMA c7228b260f Traditional Chinese translation updated by ChunChang Lo (#8170).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5499 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 23:19:49 +00:00
Jean-Philippe Lang f0dfff4866 Fixes potential test failure.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5498 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 20:34:43 +00:00
Toshi MARUYAMA 3aaaddb52a fix cs.yml lost config/configuration.yml (#7408, #7390, #7507).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5496 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 16:10:57 +00:00
Jean-Philippe Lang f89d04074e Warn about subtasks before deleting a parent issue (#6562).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5495 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 15:17:18 +00:00
Jean-Philippe Lang a96f7053fc Fixes pt locale (interpolation values is not something to translate).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5494 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 14:46:52 +00:00
Toshi MARUYAMA d6e6871e29 Japanese translation updated by Go MAEDA (#8169).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5493 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 12:31:19 +00:00
Toshi MARUYAMA 241d8534f4 Bulgarian translation updated to r5419 by Ivan Cenov (#8027).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5492 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 12:12:18 +00:00
Toshi MARUYAMA 2589d61bab Traditional Chinese translation updated to r5437 by ChunChang Lo (#7820).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5491 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 12:11:53 +00:00
Toshi MARUYAMA f9d1426f58 remove duplicate keys from Traditional Chinese translation.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5490 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 11:41:38 +00:00
Toshi MARUYAMA 10977749af Traditional Chinese translation updated to r5337 by ChunChang Lo (#7820).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5489 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 11:41:18 +00:00
Toshi MARUYAMA 76209a54ed Bulgarian translation updated to r5264 by Ivan Cenov (#8027).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5488 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 11:40:56 +00:00
Toshi MARUYAMA 1a19a0d4bf Swedish translation updated by Nicklas Holm (#8036).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5487 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 11:08:09 +00:00
Toshi MARUYAMA e2843a4b71 Traditional Chinese translation updated to r5294 by ChunChang Lo (#7820).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5486 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 11:07:45 +00:00
Toshi MARUYAMA ef999320bb Traditional Chinese translation updated to r5182 by ChunChang Lo (#7820).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5485 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 10:43:59 +00:00
Toshi MARUYAMA 67e414dbd3 European Portuguese translation updated by Alberto Ferreira (#7531).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5484 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 10:43:38 +00:00
Toshi MARUYAMA c194cdef2c Japanese translation updated by Kota Shiratsuka (#8133).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5483 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 10:10:17 +00:00
Toshi MARUYAMA c87d171c12 Traditional Chinese translation updated to r5072 by ChunChang Lo (#7820).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5482 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 10:09:50 +00:00
Toshi MARUYAMA 94f71773b6 scm: mercurial: add test of copied file from_revision node id at unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5481 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 09:33:34 +00:00
Toshi MARUYAMA 79b7e89cf9 scm: mercurial: change copied file from_revision from revision number to node id.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5480 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 09:33:07 +00:00
Toshi MARUYAMA a8e7936337 scm: mercurial: code clean up adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5479 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 09:32:35 +00:00
Toshi MARUYAMA c80fe134f5 scm: darcs: set supports_directory_revisions true at model (#7984).
Darcs adapter saves directory changes in database.
So, Redmine 1.1 shows latest changesets in sub directory.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5478 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-17 06:28:16 +00:00
Toshi MARUYAMA eb4ca1ac29 fix functional projects controller test fails in Ruby 1.8.6.
Array#count is introduced in Ruby 1.8.7.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5477 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-16 06:46:11 +00:00
Toshi MARUYAMA a7c510fd0a scm: add unit test of preventing PostgreSQL or Ruby 1.9 errors if paths is invalid UTF-8.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5476 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-16 06:45:26 +00:00
Toshi MARUYAMA 5512e397ee scm: prevent PostgreSQL or Ruby 1.9 errors if paths is invalid UTF-8.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5475 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-16 06:44:35 +00:00
Toshi MARUYAMA a78b12706a add Redmine::CodesetUtil and move replacing invalid utf8 logic to it.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5474 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-16 06:43:49 +00:00
Toshi MARUYAMA 2507bcd8e7 scm: code clean up unit changeset test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5473 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-16 01:01:58 +00:00
Toshi MARUYAMA d7fccb0d8e scm: add test of empty committer at unit changeset test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5472 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 14:22:51 +00:00
Toshi MARUYAMA dab753ba28 scm: add test of committer nil at unit changeset test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5471 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 14:22:04 +00:00
Toshi MARUYAMA 5f8c4e0703 scm: add test of invalid utf8 sequences in committer at unit changeset test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5470 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 14:21:11 +00:00
Jean-Philippe Lang e788ae7015 Upgrades prototype.js to 1.7.0.0 (#7954).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5469 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 14:14:43 +00:00
Jean-Philippe Lang 6c8708f7e2 Makes set_own_issues_private permission not available to anonymous.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5468 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 13:30:25 +00:00
Jean-Philippe Lang 2043096011 Adds translation strings for r5466.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5467 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 13:25:01 +00:00
Jean-Philippe Lang f16cddd57a Private issues (#7414).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5466 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 13:23:13 +00:00
Toshi MARUYAMA 37205a8991 scm: cvs: add path encoding select box at setting (#3462).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5465 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 07:18:10 +00:00
Toshi MARUYAMA da2c511cd1 scm: cvs: convert encoding paths in entries() of adapter (#3462).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5464 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 07:17:26 +00:00
Toshi MARUYAMA c84d2e6699 scm: cvs: convert encoding paths in revisions() of adapter (#3462).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5463 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 07:16:48 +00:00
Toshi MARUYAMA 991d39a9ac scm: cvs: convert encoding of command line arguments (#3462).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5462 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 07:16:04 +00:00
Toshi MARUYAMA eae0620e3a scm: cvs: set path encoding instance value (#3462).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5461 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 07:15:25 +00:00
Toshi MARUYAMA 50fe1ecc18 scm: cvs: strict string type and timezone in cvstime.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5460 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-15 04:23:42 +00:00
Jean-Philippe Lang 80e2eed702 Code cleanup.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5459 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-14 17:49:20 +00:00
Jean-Philippe Lang 5beef16378 Skip memberships query for anonymous user.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5458 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-14 16:32:03 +00:00
Jean-Philippe Lang 910d85be47 Skip a count query.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5457 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-14 16:29:51 +00:00
Toshi MARUYAMA 04a22fa757 scm: cvs: convert author encoding with log encoding setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5456 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-14 15:39:00 +00:00
Toshi MARUYAMA bebf8247a7 scm: cvs: fix parsing revisions if author is not ASCII.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5455 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-14 15:01:55 +00:00
Toshi MARUYAMA 7e5bc046d6 scm: cvs: add comment of author regexp fails in some non UTF-8 chars on Ruby 1.8.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5454 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-14 15:01:10 +00:00
Toshi MARUYAMA 19d524cdad scm: git: more strict functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5453 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-14 10:18:16 +00:00
Toshi MARUYAMA a20f140734 scm: cvs: code clean up functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5452 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-14 07:20:57 +00:00
Toshi MARUYAMA d43bc98a49 scm: cvs: update test repository.
add "tag00" tag and "branch00" branch.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5451 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-14 05:03:36 +00:00
Toshi MARUYAMA b091c98238 scm: cvs: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5450 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-13 11:54:42 +00:00
Toshi MARUYAMA 12c856124b scm: cvs: code clean up adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5449 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-13 11:54:06 +00:00
Toshi MARUYAMA cc534137ba scm: darcs: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5448 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-13 11:53:33 +00:00
Jean-Philippe Lang 1cd4f5b353 Adds a helper for issue heading (#7647).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5447 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 19:53:14 +00:00
Jean-Philippe Lang 6968d0da19 Fixed no method error due to typo.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5446 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 19:50:48 +00:00
Jean-Philippe Lang 7cdb4f2a87 No need to query changesets if user is not allowed to view them.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5445 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 19:45:47 +00:00
Jean-Philippe Lang b344456b6f Code cleanup.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5444 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 19:37:56 +00:00
Jean-Philippe Lang ffd0a9c72c Adds noindex,noarchive robots meta tag on form pages (#7582).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5443 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 19:22:44 +00:00
Jean-Philippe Lang 1242e448f3 Extract visibility condition from project statement and use visible scopes instead.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5442 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 16:53:39 +00:00
Jean-Philippe Lang 949b355ef2 Fixed: ambiguous lft column SQL error on Issue#descendants with a join on projects.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5441 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 16:31:00 +00:00
Toshi MARUYAMA f0d32f6567 scm: cvs: fix unit model cat test fails on Windows.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5440 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 12:24:43 +00:00
Toshi MARUYAMA 0ceeecc854 scm: cvs: code clean up unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5439 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 12:24:25 +00:00
Toshi MARUYAMA bc6b219fc9 scm: cvs: refactor adapter.
create new method path_with_proj() for calling cvs command.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5438 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 10:31:33 +00:00
Toshi MARUYAMA df04f56891 scm: cvs: remove adapter root_url() and url() methods which are implemented in abstract class.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5437 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 08:04:12 +00:00
Toshi MARUYAMA d09e496a57 scm: cvs: code clean up adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5436 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 06:53:08 +00:00
Toshi MARUYAMA 20b33942ba scm: darcs: add entries test in invalid revision in model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5435 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 05:47:05 +00:00
Toshi MARUYAMA cad14abea7 scm: cvs: add entries test in invalid revision in model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5434 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 05:46:21 +00:00
Toshi MARUYAMA 37c6480e44 scm: darcs: model entries returns nil if revision is not stored in database.
Prevent showing invalid revision in repository tab.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5433 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 05:45:37 +00:00
Toshi MARUYAMA fbf23a14b8 scm: darcs: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5432 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 05:44:48 +00:00
Toshi MARUYAMA c4616e0ae0 scm: cvs: model entries returns nil if revision is not stored in database.
Prevent showing invalid revision in repository tab.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5431 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 05:44:10 +00:00
Toshi MARUYAMA 3bff6eb660 scm: subversion: use revision and identifier as string in blame.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5430 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 05:06:22 +00:00
Toshi MARUYAMA a7aee902f2 scm: subversion: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5429 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 05:05:35 +00:00
Toshi MARUYAMA 5bb06ae42d scm: additional test of replacing invalid utf-8 sequences instead of stripping in displaying repository contents on Ruby 1.8.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5428 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 05:04:45 +00:00
Toshi MARUYAMA bb48d96d30 scm: replace invalid utf-8 sequences instead of stripping in displaying repository contents on Ruby 1.8.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5427 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-12 05:03:59 +00:00
Jean-Philippe Lang 62952a9885 Removed invalid css line.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5426 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 19:35:06 +00:00
Jean-Philippe Lang 340cf8204c Do not select the row when clicking on an image.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5425 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 19:30:54 +00:00
Jean-Philippe Lang 34f1bc0f08 Adds a specific icon for deleting a relation.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5424 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 19:30:33 +00:00
Jean-Philippe Lang 3cc7353093 Do a redirect when accessing a renamed wiki page.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5423 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 19:21:57 +00:00
Jean-Philippe Lang 6db0e8dcef Code cleanup.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5422 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 19:04:39 +00:00
Jean-Philippe Lang ae16fb3e5f Makes the issue subject field use full width.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5421 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 18:48:28 +00:00
Jean-Philippe Lang 6b44d1b27e Set fixed width for select tags on the issue form.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5420 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 18:46:53 +00:00
Jean-Philippe Lang 6fad67c887 Added strings for r5416.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5419 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 18:36:07 +00:00
Jean-Philippe Lang 3991d08858 Moved the parent issue field above start/due date fields.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5418 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 18:01:25 +00:00
Jean-Philippe Lang c52f928f35 Fixed: #setup triggers a failure even if git tests should not run.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5417 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 17:58:04 +00:00
Jean-Philippe Lang aa0d01b3d9 Adds an issues visibility level on roles (#7412).
It can be set so that users only see their own issues (created or assigned).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5416 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 17:53:15 +00:00
Jean-Philippe Lang 5fd891aa72 Fixes an error raised by cvs test with Postgresql (revision is varchar).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5415 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 16:54:35 +00:00
Toshi MARUYAMA 5b9655ab8e scm: cvs: add invalid revision annotate test in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5414 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 15:47:04 +00:00
Toshi MARUYAMA 0b68a74fc7 scm: cvs: add test annotate with revision in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5413 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 15:46:07 +00:00
Toshi MARUYAMA e9a33eff14 scm: cvs: use scm_cmd() in annotate of adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5412 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 15:45:20 +00:00
Toshi MARUYAMA 9df194ff16 scm: cvs: add annotate test of HEAD revision in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5411 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 15:44:38 +00:00
Toshi MARUYAMA 0a0819f81e scm: cvs: override annotate() in model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5410 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 15:43:50 +00:00
Toshi MARUYAMA 28a8d62fe4 scm: cvs: add test that cat returns nil if revision does not exist at model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5409 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 13:13:42 +00:00
Toshi MARUYAMA ae2304449b scm: cvs: cat returns nil if revision does not exist at model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5408 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 13:12:37 +00:00
Toshi MARUYAMA 9287f3cf73 scm: cvs: add cat test of removed file in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5407 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 12:19:05 +00:00
Toshi MARUYAMA 4bf5c42b2b scm: cvs: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5406 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 12:05:59 +00:00
Toshi MARUYAMA 7b72dc874d scm: cvs: use model instead of adapter in unit model cat test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5405 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 12:04:58 +00:00
Toshi MARUYAMA 32a9937d4e scm: code clean up abstract_adapter.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5404 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 10:25:38 +00:00
Toshi MARUYAMA 0606dfdb62 scm: move :identifier from to attr_accessor in AbstractAdapter::Revision class.
All scms which support blame use identifier.
This commit remove the link of cvs blame revision.
Redmine can not handle cvs revision (e.g. 1.2) as changeset identifier.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5403 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 10:24:44 +00:00
Toshi MARUYAMA a5384e4e88 scm: cvs: override Revision.format_identifier() for blame in adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5402 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 08:34:59 +00:00
Toshi MARUYAMA a6798d6cc2 scm: cvs: set identifier nil in blame.
Redmine can not handle cvs revision (e.g. 1.2) as changeset identifier.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5401 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 08:34:18 +00:00
Toshi MARUYAMA 4491f71441 scm: bazaar: use revision and identifier as string.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5400 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 08:33:32 +00:00
Toshi MARUYAMA 91dc3245dd scm: cvs: add -q option at rls.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5399 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 07:02:13 +00:00
Toshi MARUYAMA d595bed7ef scm: cvs: add invalid path entries test at unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5398 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 07:01:30 +00:00
Toshi MARUYAMA 25aa4d4fa0 scm: cvs: add -q option at rlog.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5397 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 06:51:41 +00:00
Toshi MARUYAMA 064e8476e8 scm: cvs: add -q option at cat.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5396 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 06:30:47 +00:00
Toshi MARUYAMA 717e2a0a9f scm: cvs: use scm_cmd() in cat.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5395 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 06:30:07 +00:00
Toshi MARUYAMA 51242b967d scm: cvs: add cat test in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5394 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 06:29:24 +00:00
Toshi MARUYAMA 71360a0f66 scm: cvs: use scm_cmd() for diff.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5393 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 05:53:35 +00:00
Toshi MARUYAMA f86779bd59 scm: bazaar: use identifier in blame.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5392 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 05:52:55 +00:00
Toshi MARUYAMA 4c3d8b681b scm: git: use revision and scmid in blame.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5391 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 05:52:34 +00:00
Toshi MARUYAMA 39c7f2942c scm: subversion: use revision in blame.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5390 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 05:52:07 +00:00
Toshi MARUYAMA 5778d3c51e scm: cvs: code clean up adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5389 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 04:18:55 +00:00
Toshi MARUYAMA f690341d9e scm: code clean up RepositoriesHelper.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5388 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 04:18:13 +00:00
Toshi MARUYAMA bf68788867 scm: more strict to_utf8() test in repository helper on Ruby 1.9.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5387 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-11 03:06:43 +00:00
Toshi MARUYAMA d5bb4b349a scm: cvs: code clean up adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5386 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-10 12:27:53 +00:00
Toshi MARUYAMA 3be326f0a4 PDF: switch FPDF ANSI or TCPDF UTF-8 with general_pdf_encoding value instead of language value such as 'ja' (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5385 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-10 08:34:52 +00:00
Toshi MARUYAMA 85b891ec9e PDF: code clean up lib/redmine/export/pdf.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5384 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-10 08:34:31 +00:00
Toshi MARUYAMA ce6377b406 PDF: switch FPDF font with general_pdf_encoding value instead of language value such as 'ja' (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5383 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-10 08:34:02 +00:00
Toshi MARUYAMA ed8b82b012 PDF: set general_pdf_encoding UTF-8 on non CJK and Thailand locales (#61).
Current trunk uses TCPDF without general_pdf_encoding value on non CJK and Thailand locales.
This commit purpose is preparing switching TCPDF or FPDF with general_pdf_encoding value
instead of language value such as 'ja'.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5382 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-10 08:33:33 +00:00
Toshi MARUYAMA bac26830e5 scm: code clean up lib/redmine/scm/adapters/abstract_adapter.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5381 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-10 08:11:18 +00:00
Toshi MARUYAMA c6ec41473e scm: cvs: code clean up lib/redmine/scm/adapters/cvs_adapter.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5380 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-10 08:10:57 +00:00
Toshi MARUYAMA 572af75c6e change "utf8" of general_csv_encoding to "UTF-8" in bs.yml and hr.yml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5379 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-10 04:46:11 +00:00
Toshi MARUYAMA 003460e77a PDF: change "utf8" of general_pdf_encoding to "UTF-8" in bs.yml and hr.yml (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5378 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-10 01:55:58 +00:00
Toshi MARUYAMA 740051b769 scm: cvs: code clean up lib/redmine/scm/adapters/cvs_adapter.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5377 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 23:23:10 +00:00
Toshi MARUYAMA 18431d3681 scm: cvs: code clean up app/models/repository/cvs.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5376 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 23:22:22 +00:00
Toshi MARUYAMA cae3fcce54 scm: use upcase to compare encoding name "UTF-8" in log converting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5375 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 23:21:41 +00:00
Toshi MARUYAMA f31df6c02f scm: code clean up app/models/changeset.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5374 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 23:21:04 +00:00
Toshi MARUYAMA 6536c53e09 scm: replace invalid utf-8 sequences in comments instead of stripping on Ruby 1.8.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5373 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 09:31:14 +00:00
Toshi MARUYAMA b9ce061319 scm: code clean up app/models/changeset.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5372 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 09:30:50 +00:00
Toshi MARUYAMA c12453ec4e scm: code clean up app/models/changeset.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5371 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 08:19:55 +00:00
Toshi MARUYAMA 1104c3900c scm: fix log converting error in Ruby 1.9 and add more tests.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5370 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 08:07:22 +00:00
Toshi MARUYAMA c711ead46c scm: more strict log converting test in Ruby 1.9.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5369 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 07:52:34 +00:00
Toshi MARUYAMA 1b0473c38e scm: set empty log encoding UTF-8 in Ruby 1.9 and add tests.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5368 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 06:34:33 +00:00
Toshi MARUYAMA e297c1c244 scm: not use Iconv for log converting in Ruby 1.9 and fix tests fails in Ruby 1.9.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5367 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 05:41:12 +00:00
Toshi MARUYAMA 1ef54041da scm: code clean up test/unit/changeset_test.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5366 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-09 05:40:25 +00:00
Jean-Philippe Lang fee9d605a3 Adds visibility condition to Issue.by_* count methods.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5365 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-08 12:21:06 +00:00
Toshi MARUYAMA 3bc9972d5e scm: add filesystem available test at unit repository test (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5364 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-08 05:44:06 +00:00
Toshi MARUYAMA b30ece064b scm: mercurial: add scm command tests at unit model test (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5363 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-08 05:43:24 +00:00
Toshi MARUYAMA d21f7fe1bf scm: git: add scm command tests at unit model test (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5362 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-08 05:42:43 +00:00
Toshi MARUYAMA 46d970a552 scm: mercurial: add client command tests at unit adapter test (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5361 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-08 04:53:11 +00:00
Toshi MARUYAMA ce3a03f4e8 scm: git: add client command tests at unit adapter test (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5360 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-08 04:52:26 +00:00
Toshi MARUYAMA bb2aec653d scm: mercurial: code clean up unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5359 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-08 04:40:48 +00:00
Toshi MARUYAMA fd316c99fa scm: mercurial: set client available if cvs version above 0.9.5.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5358 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-08 04:39:55 +00:00
Jean-Philippe Lang 1ee96293c3 Adds missing strings for notification settings (#8075).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5357 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-07 20:53:46 +00:00
Jean-Philippe Lang 1a454b8f39 Fixes test broken by r5354.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5356 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-07 20:49:33 +00:00
Jean-Philippe Lang c2d2761caa Adds functional test for project copy.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5355 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-07 17:25:51 +00:00
Jean-Philippe Lang d0ea5fae62 Fixed: empty list for user/version custom fields on bulk edit form (#2096).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5354 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-07 16:34:58 +00:00
Jean-Philippe Lang 406aa946e5 Fixes #possible_values for version custom field.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5353 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-07 16:11:29 +00:00
Toshi MARUYAMA 5eea9ec61a PDF: add test of replacing converting error characters in FPDF ANSI on Ruby 1.8 (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5352 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 10:50:24 +00:00
Toshi MARUYAMA 2f2cdfd96a PDF: replace converting error characters instead of returning UTF-8 in FPDF ANSI on Ruby 1.8 (#61).
In Japan, UTF-8 characters in Shift_JIS(CP932) becomes garbling(MOJI-BAKE).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5351 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 10:50:01 +00:00
Toshi MARUYAMA 561f6bb6d1 PDF: add test of replacing converting error characters in FPDF ANSI on Ruby 1.9 (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5350 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 10:16:29 +00:00
Toshi MARUYAMA b23bf1f299 scm: git: use "-c log.decorate=no" option instead of "--no-decorate" of "git log" above Git 1.7.2 (#8081, #8083).
Git on Redmine CI Server does not support "--no-decorate" option of "git log".

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5349 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 07:16:25 +00:00
Toshi MARUYAMA 2e0fdb39ef scm: git: change "decorate = short" to "decorate = no" in config log section of test repository (#8081, #8083).
Git on Redmine CI Server does not support "--no-decorate" option of "git log".

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5348 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 07:15:35 +00:00
Toshi MARUYAMA d6e2e81f0c PDF: nil safe at fix_text_encoding(txt) of lib/redmine/export/pdf.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5345 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 05:52:07 +00:00
Toshi MARUYAMA 411c7100cb PDF: add test of Ruby 1.9 compatibility of '0x5c'(backslash) handling in FPDF ANSI (#61, #117).
Japanese Shift_JIS and Traditional Chinese Big5 have '0x5c'(backslash) problem.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5344 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 05:39:26 +00:00
Toshi MARUYAMA a4bad14359 PDF: Ruby 1.9 compatibility of '0x5c'(backslash) handling in FPDF ANSI (#61, #117).
Japanese Shift_JIS and Traditional Chinese Big5 have '0x5c'(backslash) problem.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5343 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 05:38:31 +00:00
Toshi MARUYAMA 470ff0c6e5 PDF: add \\(double backslashes) handling of FPDF ANSI test in unit lib test (#61, #117).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5342 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 04:28:19 +00:00
Toshi MARUYAMA 73a248530a PDF: fix \\(double backslashes) handling of FPDF ANSI (#61, #117).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5341 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 04:27:38 +00:00
Toshi MARUYAMA 7f923cdc66 PDF: set language 'ja' in '0x5c'(backslash) handling unit lib test (#61, #117).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5339 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 02:41:48 +00:00
Toshi MARUYAMA 7ca82846fc scm: git: add "decorate = short" in config log section of test repository (#8081).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5338 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 02:41:27 +00:00
Toshi MARUYAMA d20bc57be0 PDF: create new unit lib pdf test and add '0x5c'(backslash) handling test (#61, #117).
Japanese Shift_JIS and Traditional Chinese Big5 have '0x5c'(backslash) problem.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5337 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-06 00:40:51 +00:00
Toshi MARUYAMA 91e4d7d298 code clean up lib/redmine/export/pdf.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5335 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 23:04:32 +00:00
Toshi MARUYAMA 00277a2a0a scm: git: add "--no-decorate" option in "git log".
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5334 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 23:03:49 +00:00
Jean-Philippe Lang 44214ed1aa Localize anonymous and non member roles names (#8072).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5333 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 22:37:45 +00:00
Jean-Philippe Lang 5823481d6e Wrap text custom fields in the issue list (#8064).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5332 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 22:18:49 +00:00
Toshi MARUYAMA 47dccc53b3 PDF: Ruby 1.9 compatibility for FPDF ANSI (#61).
Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5331 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 14:13:03 +00:00
Jean-Philippe Lang c41a3ace07 Removed duplicate Modules fieldset on project copy form.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5330 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 13:26:32 +00:00
Jean-Philippe Lang c9a3700cfc Removed a duplicate test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5329 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 13:04:59 +00:00
Jean-Philippe Lang 5f7f69e214 Removed calls to deprecated Project.visible_by method.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5328 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 12:57:18 +00:00
Jean-Philippe Lang 2b8d32a30e Makes search providers use visible scopes.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5327 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 12:55:19 +00:00
Jean-Philippe Lang 8cf42fabf6 Add permission option to wiki page activity provider.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5326 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 12:52:57 +00:00
Jean-Philippe Lang da6c149275 Makes activity providers use visible scopes.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5325 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 12:52:20 +00:00
Jean-Philippe Lang 405fc07e90 Makes visible scopes accept projects option and deprecate Project.visible_by.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5324 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 12:50:19 +00:00
Jean-Philippe Lang c2095f5e2f Set CSV separator to ; and decimal separator to , for italian (#8067).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5322 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 12:15:04 +00:00
Jean-Philippe Lang 13eea4266e Adds context menu for related issues (#8006).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5321 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 12:11:05 +00:00
Jean-Philippe Lang e3dae9ddbf Cleaner way to handle the replacement of watch links (#8071).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5320 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 12:09:15 +00:00
Jean-Philippe Lang 1af6527e42 Code cleanup.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5319 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 11:40:31 +00:00
Jean-Philippe Lang efccc61d79 Fixed: DoubleRenderError introduced by #7996.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5318 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-05 11:38:45 +00:00
Toshi MARUYAMA 1eab530e92 update locales for bulk delete time entries (#7996).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5317 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 11:55:16 +00:00
Toshi MARUYAMA 098fabd6ce add function of bulk delete time entries (#7996).
Contributed by Adam Soltys.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5316 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 11:54:47 +00:00
Toshi MARUYAMA c2baf187ac add functional tests for bulk edit time entries (#7996).
Contributed by Adam Soltys.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5315 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 11:54:22 +00:00
Toshi MARUYAMA 2029df01ae add bulk edit items and context menu in time entries list view (#7996).
get bulk edit form action working by mapping permissions.

Contributed by Adam Soltys.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5314 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 11:53:55 +00:00
Toshi MARUYAMA 8a31517288 add bulk edit and bulk update actions for time entries (#7996).
get bulk edit form action working by mapping permissions.

Contributed by Adam Soltys.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5313 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 11:53:29 +00:00
Toshi MARUYAMA ab31a114fd add controller for bulk edit time entries (#7996).
Contributed by Adam Soltys.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5312 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 11:53:03 +00:00
Toshi MARUYAMA f6c5426605 add view for bulk edit time entries (#7996).
Contributed by Adam Soltys.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5311 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 11:52:33 +00:00
Toshi MARUYAMA 70a641c9bc update locales for bulk edit time entries (#7996).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5310 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 11:51:54 +00:00
Toshi MARUYAMA 87945f2ff5 add context menu in time entries for bulk edit (#7996).
Contributed by Adam Soltys.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5309 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 11:51:17 +00:00
Toshi MARUYAMA 3b20bd76a8 code clean up lib/redmine/export/pdf.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5308 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 05:01:42 +00:00
Toshi MARUYAMA 6d13ed58db i18n: add test of utf-8 strings.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5307 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 02:39:43 +00:00
Toshi MARUYAMA d435195764 PDF: remove replacing non ASCII quotation marks (#61).
Languages except CJK and Thailand use TCPDF UTF-8.
TCPDF UTF-8 supports these quotation marks.

Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5306 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 01:10:31 +00:00
Toshi MARUYAMA 846ac262ec Remove empty lines from test/unit/mailer_test.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5305 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-04 01:10:10 +00:00
Jean-Philippe Lang 3c06f66d71 Shorten query[column_names] param name.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5304 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 14:31:32 +00:00
Jean-Philippe Lang 87bcb21563 Keep issue filter params on sort headers.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5303 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 14:09:22 +00:00
Jean-Philippe Lang 01fed468fa Changes pagination links to non-AJAX requests (#5138).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5302 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 14:06:53 +00:00
Jean-Philippe Lang 0f0fbeb26d Makes all pagination-like links use #link_to_content_update (#5138).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5301 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 14:01:32 +00:00
Jean-Philippe Lang 7bca8c4212 Removed the changeset-changes class to the commit logs on the issue view (#8038).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5300 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 12:33:27 +00:00
Jean-Philippe Lang 4ab4c21890 Disable unused fields when switching the period type.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5299 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 12:02:56 +00:00
Jean-Philippe Lang 70ec78d013 Removed hidden project_id and issue_id parameters.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5298 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 12:02:10 +00:00
Jean-Philippe Lang b0ade644d6 Changed timelogs filters to use non-AJAX requests (#1965).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5297 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 11:55:24 +00:00
Toshi MARUYAMA 90ed078445 PDF: code clean up lib/redmine/export/pdf.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5296 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 02:47:06 +00:00
Toshi MARUYAMA dfe83ffa91 PDF: fix width calculation of multi byte character in Simplified and Traditional Chinese (#61).
Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5295 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-03 02:12:09 +00:00
Jean-Philippe Lang afbd83d404 Skip a count(*) SQL query.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5294 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-02 11:46:20 +00:00
Jean-Philippe Lang 8cd93159d6 Do not load projects association in #rolled_up_trackers.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5293 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-02 11:31:33 +00:00
Jean-Philippe Lang 80b59f3cf4 Skip a few count(*) SQL queries on the issue list.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5292 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-02 10:18:05 +00:00
Toshi MARUYAMA 859e8ae828 PDF: set enable to use TCPDF UTF-8 on Windows except CJK and Thai (#61).
Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5291 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-02 08:01:47 +00:00
Toshi MARUYAMA 2b899b73ad PDF: fix the problem that TCPDF built-in font breaks in the Windows (#61).
This problem occurs because the EOF character string is included in the built-in font.

Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5290 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-02 08:01:29 +00:00
Toshi MARUYAMA bc5be82683 Fix typo "attachements" in test/integration/issues_test.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5289 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-02 08:01:06 +00:00
Jean-Philippe Lang eda002d0df Adds an index on users.type for faster retrieval of groups.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5288 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 19:32:07 +00:00
Jean-Philippe Lang 737247f4c9 No PUT request to get previous/next month.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5287 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 19:04:26 +00:00
Jean-Philippe Lang 2c4cc25433 Limits nested set overhead when destroying an issue without children.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5286 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 18:58:29 +00:00
Jean-Philippe Lang 6550ef9df5 Fixed: deleting a parent issue may lead to a stale object error (#7920).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5285 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 18:42:41 +00:00
Jean-Philippe Lang b972b5a647 Fixed: list of users for adding to a group may be empty if 100 first users have been added (#8029).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5284 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 16:47:30 +00:00
Jean-Philippe Lang 4e7835c68c Fixed: bulk destroying parent and child issues raises a stale object error (#7920).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5283 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 16:26:53 +00:00
Toshi MARUYAMA 516320e82b PDF: back out r5253 (#7794, #61).
r5256 fixed #7794 completely.
r5253 effects the width of the ASCII character of Japanese PDF.

Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5281 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 15:46:18 +00:00
Jean-Philippe Lang 063ae06b09 Gantt routes with format.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5280 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 15:30:32 +00:00
Jean-Philippe Lang a669dfbd7f Shortens filter param names.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5279 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 15:00:23 +00:00
Jean-Philippe Lang 25ea0f34a6 Keep filter params in 'Per page' links.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5278 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 14:50:18 +00:00
Jean-Philippe Lang 4641716771 Disable unused filter fields so they don't get submitted.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5277 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 14:48:06 +00:00
Jean-Philippe Lang a80b909cc8 Converted issue filters to non-AJAX GET requests (#1965).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5276 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 14:34:44 +00:00
Jean-Philippe Lang cf8d195929 Set native EOL.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5275 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 14:02:05 +00:00
Jean-Philippe Lang c6e34b0c11 Initialize TimeEntry with issue and project for the issue edit form.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5274 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 14:00:31 +00:00
Jean-Philippe Lang 2be6f54f23 Fixes #possible_values_options when given an object with nil project.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5273 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 13:56:25 +00:00
Jean-Philippe Lang 1cd6a2aa84 Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096).
These new field formats are available for project, issue, version and time entry custom fields.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5272 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 13:44:58 +00:00
Toshi MARUYAMA 122ba564b9 Fix test/integration/api_test/users_test.rb fails due to changing en.yml (#8035, #7855).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5270 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 00:46:29 +00:00
Toshi MARUYAMA 10f66e425e Fix annotate functional roles_controller_test.rb due fails to changing en.yml (#8035, #7855).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5269 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-04-01 00:11:02 +00:00
Toshi MARUYAMA f96d7ce8e0 scm: git: fix annotate test due to changing en.yml (#8035, #7855).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5268 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-31 16:46:24 +00:00
Toshi MARUYAMA dbe71b4f3b PDF: fix syntax errors at vendor/plugins/rfpdf/lib/tcpdf.rb on Ruby 1.9 (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5267 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 23:44:20 +00:00
Jean-Philippe Lang 3ec97f951e Possible values label not hidden on custom field form.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5266 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 19:00:17 +00:00
Jean-Philippe Lang 8b39f62a4c Modules selection lost on project form after validation failure (#8012).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5265 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 17:16:25 +00:00
Jean-Philippe Lang b12994e12e Removed hard coded french strings (#8020).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5264 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 16:56:52 +00:00
Jean-Philippe Lang 64c026e34e Fixes en-GB translation for field_member_of_group and field_assigned_to_role (#7855).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5263 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 16:49:52 +00:00
Jean-Philippe Lang dafb0b1227 Set native eol on en-GB.yml (#7855).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5262 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 16:46:06 +00:00
Jean-Philippe Lang 706485aaec Translations updates by joergleis (#7855).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5261 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 16:44:45 +00:00
Jean-Philippe Lang 4d0cc94d91 Japanese translation update by Yuki Kita.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5260 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 16:37:55 +00:00
Toshi MARUYAMA 325af8d48c PDF: switch TCPDF UTF-8 or FPDF ANSI (#61).
If server is Windows or language is CJK or Thai, Redmine uses FPDF.
Else Redmine uses TCPDF.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5259 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 11:32:35 +00:00
Toshi MARUYAMA 988841d69a PDF: prepare switching TCPDF UTF-8 in non CJK or FPDF ANSI in CJK (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5258 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 07:32:08 +00:00
Toshi MARUYAMA 8db478808d PDF: comment out Mime pdf in vendor/plugins/rfpdf/init.rb (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5257 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 05:46:58 +00:00
Toshi MARUYAMA 404ba921e2 PDF: import CJK patches (#61).
Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5256 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 05:05:11 +00:00
Toshi MARUYAMA 56a7ff0bc7 PDF: comment out memoizes (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5255 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 05:04:51 +00:00
Toshi MARUYAMA 2d97a7453b PDF: transplant r4602 (#61).
Ruby1.9 compatibility.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5254 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 03:28:10 +00:00
Toshi MARUYAMA 8b0144248c PDF: transplant r5183 (#61).
Fix an internal server error on formatting an issue as a PDF in Japanese (#7794).

Contributed by Yuki Sonoda.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5253 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 03:27:50 +00:00
Toshi MARUYAMA b257ad1457 PDF: transplant r1497 (#61).
Fixes Chinese pdf export when the issue description is too long (#1170).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5252 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 03:27:29 +00:00
Toshi MARUYAMA 000cf8fa9e PDF: transplant r3389 (#61).
Korean support for PDF export (#4639).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5251 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 03:27:09 +00:00
Toshi MARUYAMA b9b2f24540 PDF: transplant r393 (#61).
Added chinese simplified translation (Andy Wu)
Fixed rfpdf chinese.rb

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5250 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 03:26:47 +00:00
Toshi MARUYAMA aff157f0a0 PDF: transplant r287 (#61).
Fix for #9.
Export feature(to csv/pdf) doesn't work in Japanese
csv and pdf encoding are know defined for each language
(general_csv_encoding and general_pdf_encoding keys in lang files)
added SJIS font for japanese pdf exports.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5249 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 03:26:24 +00:00
Toshi MARUYAMA ad5dcaf179 PDF: add missing rfpdf requires (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5248 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 03:26:01 +00:00
Toshi MARUYAMA 22e8d9b949 PDF: update rfpdf (#61).
https://github.com/edwinmoss/rfpdf
revision a04724b4af95c15a99675b34e353c15534d20411

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5247 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-30 03:23:54 +00:00
Jean-Philippe Lang 13d6b3129b Adds support for preview when editing an issue note (#5520).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5246 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 21:45:30 +00:00
Jean-Philippe Lang af968bfb22 Save queries.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5245 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 20:56:28 +00:00
Jean-Philippe Lang ba0c9069ed Save 2 queries when displaying a root issue.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5244 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 20:32:35 +00:00
Jean-Philippe Lang 1c03b418e1 Save 1 query + 1 cache hit in #shared_versions for root projects.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5243 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 20:29:43 +00:00
Jean-Philippe Lang 2d3f69f8b1 Escapes wiki help link.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5242 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 20:16:05 +00:00
Jean-Philippe Lang f7edfe7652 Prettier wiki syntax help link.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5241 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 20:12:15 +00:00
Jean-Philippe Lang 9730ff2225 Adds wiki toolbar to notes editing form (#7899).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5240 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 20:04:48 +00:00
Jean-Philippe Lang bf58ad61e5 Load scripts and css for wiki formatter toolbar when needed.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5239 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 19:59:35 +00:00
Jean-Philippe Lang 70d765e906 Moves jstoolbar script include tags to head.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5238 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 19:56:22 +00:00
Jean-Philippe Lang 393df388fc Context menu: keep parent item highlighted when hovering a submenu item.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5237 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 19:24:02 +00:00
Jean-Philippe Lang 86eed08fbf Fixes progress calculation on gantt (#7838).
Contributed by Etienne Massip.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5236 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 17:35:20 +00:00
Toshi MARUYAMA 927a6b045e add .svn/ and .git/ to .hgignore.
"hg addremove" adds .svn/ and .git/ if .hgignore does not have these.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5235 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 04:54:13 +00:00
Toshi MARUYAMA e6a425dd72 i18n: fix typo general_pdf_encoding "UFT-8" in sl.yml (#61).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5233 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-28 01:09:53 +00:00
Jean-Philippe Lang d42ce927c7 Fixed windows detection in reposman.rb (#8003).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5232 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-27 16:58:21 +00:00
Jean-Philippe Lang 96ff8ef4bc Fixes wrong test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5231 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-27 16:49:35 +00:00
Jean-Philippe Lang 08f44b67f5 Fixed links in new file notification broken by r4051 (#6590).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5230 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-27 16:38:08 +00:00
Jean-Philippe Lang 100a53d240 French translation update.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5229 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-27 16:25:24 +00:00
Jean-Philippe Lang 78af4f429f Adds support for saturday as the first week day (#7097).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5228 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-27 15:43:26 +00:00
Jean-Philippe Lang 3ef5daaf35 Restore settings even if a test failure occurs.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5227 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-27 15:41:05 +00:00
Jean-Philippe Lang 4f9d3f80c4 Moved calendar tests to unit/lib/redmine/helpers.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5226 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-27 15:26:59 +00:00
Jean-Philippe Lang a2baf9f695 Do not send reminders to locked users (#5773).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5225 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-27 15:12:38 +00:00
Jean-Philippe Lang ca5951b4f6 Allow bulk editing of parent issue (#5831).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5224 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-27 15:00:02 +00:00
Toshi MARUYAMA 590cc111fc scm: remove "View all revisions" in sub directory (#7984).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5223 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-26 02:40:13 +00:00
Toshi MARUYAMA 7ec605fe04 scm: add rev param to "View revisions" (#7984).
There are two paths to show specific revision.
* http://www.redmine.org/projects/redmine/repository/revisions/5219/show
* http://www.redmine.org/projects/redmine/repository/show?rev=5219

First link is http://www.redmine.org/projects/redmine/repository/revisions/5219/changes .
But, Second link is http://www.redmine.org/projects/redmine/repository/changes .

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5222 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-26 02:39:31 +00:00
Jean-Philippe Lang 437c5658d7 Adds css classes to parent/child issues (#7986).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5221 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-25 18:31:32 +00:00
Jean-Philippe Lang f6ac158de9 Set style more specifically to avoid clashes.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5220 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-25 18:15:16 +00:00
Toshi MARUYAMA 69311c9d2f scm: do not display 'View revision' links in subversion if path or revision are nil (#7984).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5219 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-24 23:43:33 +00:00
Toshi MARUYAMA 023a0efa10 scm: backout r5213. do not display both 'View all revisions' and 'View revision' links (#7984, #7246).
Git and Mercurial support *branch*.

Git in repository root shows *master branch*.
Git master branch does not have all revisions.

Mercurial default branch is *default branch*.
Mercurial shows *tip* in repository root.

Mercurial does not treat directory. "hg log DIR" costs high.
Getting correct limited changesets in sub directory and branch is very heavy.
So, if there is no recent revision in sub directory and branch,
no changeset shows.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5218 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-24 23:42:50 +00:00
Jean-Philippe Lang c58c14cc73 Adds support for Mac metaKey in issues selection (#5148).
Contributed by Simon Courtois.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5217 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-24 19:21:47 +00:00
Jean-Philippe Lang 91b1f9be51 Moved plugin tasks directories to lib/tasks (Rails deprecation).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5216 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-24 18:46:12 +00:00
Jean-Philippe Lang 5d72122039 Fixes sort parameter in reminder email links (#7963).
Contributed by Beat Jörg.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5215 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-24 18:43:05 +00:00
Jean-Philippe Lang c17ff5f024 Fixed: unknown custom field format causes error when editing/bulk editing (#7985).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5214 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-24 18:24:30 +00:00
Jean-Philippe Lang 4d7e61c49e Do not display both 'View all revisions' and 'View revision' links (#7984).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5213 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-24 17:58:50 +00:00
Jean-Philippe Lang 5a5cb39de0 Better cross-browser checkbox positioning.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5212 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-23 20:11:57 +00:00
Toshi MARUYAMA 26a82965f0 scm: filesystem: increase non ascii contents ratio of test repository (#6256).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5211 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 23:49:48 +00:00
Toshi MARUYAMA f15b12556f scm: set mime type in downloading file.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5210 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 16:56:52 +00:00
Toshi MARUYAMA cb297048df scm: filesystem: add test for no extension file mime type in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5209 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 16:56:07 +00:00
Toshi MARUYAMA 7ba5b27d09 scm: filesystem: fix todo comment of MIME_TYPES of big-file.txt in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5208 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 15:56:28 +00:00
Toshi MARUYAMA d43493fc79 scm: filesystem: add test for displaying file over max size limit (#6256).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5207 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 15:33:33 +00:00
Toshi MARUYAMA fb0d24d37e scm: filesystem: add test for UTF-16 file displaying (#6256).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5206 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 15:32:47 +00:00
Toshi MARUYAMA 53b41950d1 scm: filesystem: add test for non ascii text file displaying (#6256).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5205 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 15:32:03 +00:00
Toshi MARUYAMA 79eba572af scm: fix non ascii text files displaying (#6256).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5204 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 15:31:17 +00:00
Toshi MARUYAMA 0597adfe53 scm: filesystem: update test repository for non ascii text files displaying (#6256).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5203 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 15:30:19 +00:00
Toshi MARUYAMA 9000cdbf2f scm: mercurial: add test of binary file should be force download in functional test (#6256).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5202 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 11:26:57 +00:00
Toshi MARUYAMA d5ee82cea9 scm: mercurial: use constant for project id in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5201 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 11:26:15 +00:00
Toshi MARUYAMA 9e191adcae scm: mercurial: remove duplicate test from functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5200 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 10:46:23 +00:00
Toshi MARUYAMA bf251a586b scm: darcs: remove duplicate test from functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5199 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 10:46:02 +00:00
Toshi MARUYAMA ec2fd81f7b scm: filesystem: add test of no extension file whose content is only ASCII can be showing (#6256).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5198 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 10:45:39 +00:00
Toshi MARUYAMA 002ff62e33 scm: git: remove duplicate test from functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5197 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 09:54:11 +00:00
Toshi MARUYAMA b9bfb0f117 scm: filesystem: add functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5196 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 09:53:49 +00:00
Toshi MARUYAMA d590a5583b scm: code clean up test/unit/repository_test.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5195 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 08:42:29 +00:00
Toshi MARUYAMA e580dbc6a3 scm: code clean up test/functional/repositories_controller_test.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5194 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 07:48:04 +00:00
Toshi MARUYAMA e6cbb1cd6b scm: filesystem: change project id of unit model test from 1 to 3.
Project id 1 has Subversion fixtures.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5193 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 05:48:06 +00:00
Toshi MARUYAMA 3f3b6c8fd2 scm: filesystem: code clean up unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5192 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 05:47:24 +00:00
Toshi MARUYAMA f161d1833c scm: filesystem: code clean up unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5191 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 05:46:43 +00:00
Toshi MARUYAMA f1a4867fce add GNU gettext po to Redmine::MimeType.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5190 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 04:35:48 +00:00
Toshi MARUYAMA dc63efa535 scm: cvs: check assign changesets in root directory showing of functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5189 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 04:17:58 +00:00
Toshi MARUYAMA bda4f7b6ee scm: cvs: remove duplicate test in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5188 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-22 04:17:18 +00:00
Jean-Philippe Lang 95c7140cdf Show open and closed issues from "Issues by" version links.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5187 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-21 20:08:16 +00:00
Jean-Philippe Lang 53ad42e1d8 Fixed: atom links on wiki index broken by r4266.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5186 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-21 18:10:04 +00:00
Jean-Philippe Lang 3d551f97e1 Fixed: Simultaneous wiki updates cause internal error (#7939).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5185 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-21 16:55:28 +00:00
Toshi MARUYAMA 3acae2529e Fix an internal server error on formatting an issue as a PDF in Japanese (#7794).
Contributed by Yuki Sonoda.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5183 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-21 06:14:02 +00:00
Toshi MARUYAMA 679e40dfb4 Fix typo in test/test_helper.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5182 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 23:10:11 +00:00
Jean-Philippe Lang 2ac4ea11a5 Changes polish csv separator to ; and decimal to , (#7875).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5181 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 21:24:14 +00:00
Jean-Philippe Lang 631de456f4 Silently ignore invalid status_by param.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5180 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 21:09:48 +00:00
Jean-Philippe Lang e1ae0e9777 Adds an option to view issues count by status on the version page (#7921).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5179 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 21:06:30 +00:00
Jean-Philippe Lang 82538dd07e Adds border and margin for issue list printing.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5178 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 20:45:52 +00:00
Jean-Philippe Lang f655353f64 Fixed: issue list truncated when printing with Firefox 3.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5177 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 20:35:31 +00:00
Jean-Philippe Lang 0b3f2bc650 Fixed: news comments not deleted when deleting a project (#7904).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5176 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 20:26:59 +00:00
Jean-Philippe Lang f279b48288 Fixes subversion tests not running on win32.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5175 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 18:25:38 +00:00
Jean-Philippe Lang 85462261ac Adds links on the issue list to collapse/expang all groups (#7236).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5174 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 16:01:25 +00:00
Toshi MARUYAMA e53c8cfc1b scm: filesystem: prevent exception raises if path encoding is incorrect.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5173 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 14:06:49 +00:00
Jean-Philippe Lang 6424155f59 Makes the user form look like account form.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5172 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 11:49:29 +00:00
Jean-Philippe Lang 50cb77cfbb Fixed: children projects are deleted instead of being destroyed when destroying parent project (#7904).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5171 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 11:46:01 +00:00
Jean-Philippe Lang 88dc1412d7 Fixes error in RepositoriesHelper#replace_invalid_utf8 when given nil.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5170 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 11:33:03 +00:00
Jean-Philippe Lang 2201a343e4 Fixes RepositoriesHelper#to_utf8 test failure for ruby1.8.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5169 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-20 11:14:50 +00:00
Toshi MARUYAMA 3ea7b9a768 scm: git: default_branch() returns nil explicitly if branches are empty.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5168 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-19 15:50:08 +00:00
Toshi MARUYAMA 08429506c5 scm: fix git and mecruial repository note in setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5167 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-19 12:45:25 +00:00
Toshi MARUYAMA 09996c3524 scm: add unit test of invalid utf8 sequences should be stripped in repository_helper to_utf8().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5166 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-19 05:46:47 +00:00
Toshi MARUYAMA e6e4256ee4 scm: to_utf8() in repositories_helper always returns UTF-8 in Ruby 1.9.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5165 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-19 05:46:25 +00:00
Toshi MARUYAMA a9d089dbcb scm: git: strict Ruby 1.9 string test in unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5164 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-17 03:54:22 +00:00
Toshi MARUYAMA 899d1d8acb scm: git: strict Ruby 1.9 string test in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5163 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-17 03:54:00 +00:00
Toshi MARUYAMA f065c6f461 scm: subversion: code clean up unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5162 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-17 03:53:34 +00:00
Toshi MARUYAMA 8d0d1d50cc scm: code clean up unit model changeset test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5161 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-17 03:53:08 +00:00
Toshi MARUYAMA c051572070 scm: strict Ruby 1.9 string test in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5160 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-17 03:52:45 +00:00
Toshi MARUYAMA b404ba776f scm: subversion: simplify Ruby 1.9 string test in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5159 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-17 03:52:18 +00:00
Toshi MARUYAMA 4923ff76fa scm: fix repository helper unit test fails in Ruby 1.9 and non UTF-8 locale.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5158 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-17 03:51:46 +00:00
Jean-Philippe Lang e27866be5b Prevent error when referencing an issue without project (#7890).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5157 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 20:52:48 +00:00
Jean-Philippe Lang 0502df816d Do not actually try to fetch changesets from the subversion repository.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5156 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 20:31:01 +00:00
Jean-Philippe Lang e904a5aae6 Adds a test for AuthSourcesController#destroy with users.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5155 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 19:52:16 +00:00
Jean-Philippe Lang 9df5750906 Indentation.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5154 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 19:36:53 +00:00
Jean-Philippe Lang 64be81a433 Saves an extra SQL query on each request.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5153 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 19:26:07 +00:00
Jean-Philippe Lang a8ccddc289 Removes a space before argument parentheses.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5152 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 18:30:37 +00:00
Jean-Philippe Lang a08c64e11f Adds links to reset filters on users and projects list.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5151 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 18:23:51 +00:00
Jean-Philippe Lang 899d410e0b Adds a Group filter on the admin users list (#7893).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5150 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 18:20:08 +00:00
Jean-Philippe Lang 0786b9ef99 Replaces TimeEntry.visible_by with a visible scope.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5149 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 17:29:30 +00:00
Toshi MARUYAMA 7ffdd961e9 scm: bazaar: add changesets order test in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5148 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 05:50:06 +00:00
Toshi MARUYAMA 16b02fcfad scm: use blank? for "root @ branch" in repository tree viewing.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5147 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 00:51:14 +00:00
Toshi MARUYAMA 2a161b4576 scm: mercurial: increase limit of branch directory latest changesets.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5146 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 00:50:53 +00:00
Toshi MARUYAMA 20fa628de5 scm: switch showing link all revisions and directory revisions if scm supports these feature or not.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5145 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 00:50:32 +00:00
Toshi MARUYAMA bae1763a09 scm: set supporting directory revisions or not at scm level.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5144 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 00:50:11 +00:00
Toshi MARUYAMA de5c337df2 scm: set supporting all revisions or not at scm level.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5143 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-16 00:49:50 +00:00
Jean-Philippe Lang 83df013f47 Adds a visible scope to the Journal model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5142 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-15 17:16:45 +00:00
Jean-Philippe Lang fba3d5d327 Adds Issue#visible_condition to build issue visibility statement.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5141 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-15 16:00:39 +00:00
Jean-Philippe Lang 5f889932b6 Changed the way the visibility SQL statement is built.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5140 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-15 15:39:59 +00:00
Toshi MARUYAMA b6dfa0b081 scm: recovery showing "root @ branch" in repository tree viewing.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5139 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-15 08:21:26 +00:00
Toshi MARUYAMA 1ec3f1c696 scm: code clean up repositories/show.rhtml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5138 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-15 07:14:39 +00:00
Toshi MARUYAMA dbb0d880a7 scm: git: prevent showing trace when repository path changed.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5137 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-15 07:14:19 +00:00
Toshi MARUYAMA 78f11a232f scm: code clean up repositories/show.rhtml.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5136 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-15 05:11:21 +00:00
Jean-Philippe Lang 3328a1fc37 Use names instead of ids for wiki anchors (#6905).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5135 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 22:01:43 +00:00
Jean-Philippe Lang 36dbb3906b Send the CSRF token with Ajax requests (#7843).
Contributed by Etienne Massip.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5134 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 21:31:02 +00:00
Jean-Philippe Lang 6f5ffce799 Fixed: line breaks are ignored in quoted text (#6148).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5133 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 20:35:36 +00:00
Jean-Philippe Lang 208d2d4090 Moved text formatting tests from application_helper tests to formatter tests.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5132 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 20:29:06 +00:00
Toshi MARUYAMA d317aec3ef scm: mercurial: add tag test in functional test (#1981).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5131 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 13:42:37 +00:00
Toshi MARUYAMA 3285a721b1 scm: mercurial: add named branch test in functional test (#7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5130 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 13:42:16 +00:00
Toshi MARUYAMA cf2b4d49f0 scm: mercurial: branches and tags are enable in model (#1981, #7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5129 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 13:41:52 +00:00
Toshi MARUYAMA 6702b26515 scm: mercurial: add test of latest changesets support named branch in unit model test (#7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5128 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 13:41:28 +00:00
Toshi MARUYAMA 8944150ace scm: mercurial: latest changesets support named branch (#7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5127 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 13:41:01 +00:00
Toshi MARUYAMA 59c791b2e1 scm: mercurial: add latest changesets supporting tag test in unit model test (#1981).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5126 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 11:15:23 +00:00
Toshi MARUYAMA 081a90701a scm: mercurial: add latest changesets improvement test in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5125 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 11:03:55 +00:00
Toshi MARUYAMA 29c1aadbb5 scm: mercurial: add latest changesets improvement test in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5124 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 11:03:34 +00:00
Toshi MARUYAMA c8ce22c275 scm: mercurial: latest changesets improvement and supporting tag (#1981).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5123 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 10:36:34 +00:00
Toshi MARUYAMA a5e55a9053 scm: mercurial: check changesets size is greater than 0 in browse test in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5122 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 10:23:51 +00:00
Toshi MARUYAMA cb2dc02a67 scm: git: add browsing tag test in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5121 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 08:16:23 +00:00
Toshi MARUYAMA 3c3e16e022 scm: git: check entries and changesets size are greater than 0 in browse test in functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5120 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 08:16:03 +00:00
Toshi MARUYAMA 953e8e0f72 scm: git: code clean up functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5119 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 08:15:42 +00:00
Toshi MARUYAMA f3822e18bd scm: mercurial: prepare tests of named branch and tag in functional test (#1981, #7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5118 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 08:15:22 +00:00
Toshi MARUYAMA 7e96ea617c scm: mercurial: prepare tests of named branch and tag in unit model test (#1981, #7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5117 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 08:15:00 +00:00
Toshi MARUYAMA 620e428e95 scm: mercurial: code clean up unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5116 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 08:14:38 +00:00
Toshi MARUYAMA cbe59c5990 scm: mercurial: add test of non ASCII named branch in unit adapter test (#7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5115 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 04:55:20 +00:00
Toshi MARUYAMA 5abec74de3 scm: mercurial: add test of non ASCII tag in unit adapter test (#1981).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5114 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 04:55:03 +00:00
Toshi MARUYAMA 5edc631791 scm: mercurial: prepare test of wrapping revision of cat and annotate with URL encoding (#1981, #7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5113 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 04:54:45 +00:00
Toshi MARUYAMA bf6ec48bea scm: mercurial: wrap revision of cat and annotate with URL encoding (#1981, #7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5112 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-14 02:23:54 +00:00
Jean-Philippe Lang 0445c1e9cb Updates zoom icons and removes unused ones.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5111 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 16:56:20 +00:00
Jean-Philippe Lang 7927bc2d89 Check for a valid time entry if comments have been entered when updating an issue (#7581).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5110 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 16:38:01 +00:00
Jean-Philippe Lang 8d641203d4 Add "mystery man" gravatar to options (#7640).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5109 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 16:07:55 +00:00
Toshi MARUYAMA d48a7e148e scm: mercurial: remove unused parameters from "nodes_in_branch()" method in adapter (#7246, #4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5108 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 15:03:05 +00:00
Jean-Philippe Lang e4103aab16 Removed useless javascript.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5107 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 13:32:44 +00:00
Jean-Philippe Lang a340b17d80 Adds an autoscroll div around permissions report table.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5106 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 13:31:36 +00:00
Jean-Philippe Lang 59bf5cea6e Fixed: mail handler keywords are not removed when updating issues (#7785).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5105 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 13:24:56 +00:00
Jean-Philippe Lang 9375f1c3a4 Prevent SystemStackError on Issue#all_dependent_issues with mutiple circular dependencies (#7320).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5104 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 13:00:55 +00:00
Toshi MARUYAMA 72d6b2c8df scm: mercurial: add tests for "nodes_in_branch()" method in adapter (#7246, #4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5103 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 10:52:03 +00:00
Toshi MARUYAMA b914a3648a scm: mercurial: add new "nodes_in_branch()" method in adapter (#7246, #4455).
For latest changesets supporting named branch.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5102 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 00:48:07 +00:00
Toshi MARUYAMA 2e2055c051 scm: mercurial: add new "rhlog()" function in helper extension (#7246, #4455).
For latest changesets supporting named branch.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5101 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-13 00:47:47 +00:00
Jean-Philippe Lang 7db930f1b4 Fixed: Wiki headings containing backslash followed by a digit are not displayed correctly (#7846).
Contributed by Etienne Massip.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5100 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-12 18:28:30 +00:00
Jean-Philippe Lang 1423890735 Adds an option to #render_page_hierarchy to add timestamp titles.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5099 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-12 18:27:02 +00:00
Jean-Philippe Lang b8b35ab05f Moved wiki page updated_on eager load to a scope and fixed timestamp titles on wiki page index (#7818).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5098 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-12 18:09:46 +00:00
Jean-Philippe Lang f7127e9466 Fixed: wiki page with backslash in title can not be found (#7589).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5097 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-12 13:42:29 +00:00
Jean-Philippe Lang fcf0162c8d Fixes diff test regarding r5094.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5096 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-12 12:14:14 +00:00
Jean-Philippe Lang d96fd25e64 Fixes diff test regarding r5094.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5095 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-12 12:06:58 +00:00
Jean-Philippe Lang 21c79827ff Highlight changes inside diff lines (#7139).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5094 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 20:23:29 +00:00
Toshi MARUYAMA 099ba68836 scm: cvs: fix missing author, revision and comment in tree view (#4270).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5093 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 12:06:05 +00:00
Toshi MARUYAMA 0d63e9e8fd scm: mercurial: add :order => 'id DESC' explicitly for MySQL test fails.
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?

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5091 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 07:34:14 +00:00
Toshi MARUYAMA cb8c2d59bf scm: mercurial: remove duplicates tests in unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5090 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 07:33:53 +00:00
Toshi MARUYAMA 542e0cb88d scm: mercurial: fix unit model test fails on MySQL and remove duplicates tests.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5089 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 04:38:26 +00:00
Toshi MARUYAMA 732ee35b2f scm: cvs: fix age column on repository view is off by timezone delta (#7827).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5088 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 04:19:33 +00:00
Toshi MARUYAMA 651976eebd scm: cvs: use "-D time_to_cvstime_rlog(identifier)" in adapter entries().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5087 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 04:19:12 +00:00
Toshi MARUYAMA 45cba97088 scm: cvs: code clean up adapter entries().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5086 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 01:48:36 +00:00
Toshi MARUYAMA eea06ab770 scm: cvs: use scm_cmd() in adapter revisions().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5085 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 01:48:18 +00:00
Toshi MARUYAMA bf032661f7 scm: cvs: code clean up model.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5084 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 00:43:24 +00:00
Toshi MARUYAMA b5bf2fb322 scm: cvs: use scm_cmd() in adapter entries().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5083 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 00:42:59 +00:00
Toshi MARUYAMA d3d7ea08f4 scm: cvs: add new method 'scm_cmd' to wrap shellout.
Refer Mercurial adapter r4830.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5082 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 00:42:40 +00:00
Toshi MARUYAMA f41848fda4 scm: cvs: code clean up functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5081 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-11 00:42:21 +00:00
Jean-Philippe Lang 28feb58754 Speeds up WikiHelper#wiki_page_options_for_select.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5080 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-10 19:44:32 +00:00
Jean-Philippe Lang ef189164bf Code cleanup.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5079 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-10 19:34:49 +00:00
Jean-Philippe Lang 11c660e91f Code cleanup.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5078 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-10 19:34:17 +00:00
Jean-Philippe Lang ec8d9a7911 Gantt: do not ignore project filter (#7000, #7352), do not display empty projects/versions, and display shared versions used in other projects (#5817, #6476, #6604).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5077 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-10 18:07:09 +00:00
Jean-Philippe Lang b1cc8511c7 Prevent icons clipping on gantt.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5076 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-10 17:40:51 +00:00
Toshi MARUYAMA 2ebaf1372d scm: git: fix newlines of test/unit/repository_git_test.rb.
svn cat fails.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5075 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-10 08:43:23 +00:00
Toshi MARUYAMA c072d3b62f scm: git: add tests for previous and next versions in unit model test (#7821, #5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5074 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-10 04:31:10 +00:00
Toshi MARUYAMA 6dc57e752d scm: git: insert revisions to database with reverse commit order (#7821, #5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5073 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-10 04:30:47 +00:00
Toshi MARUYAMA b235e36946 scm: git: unit model latin-1 path encoding test passes on Japanese Windows (#5251).
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-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5072 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-09 04:14:17 +00:00
Toshi MARUYAMA 74f44a5b6a scm: git: unit adapter latin-1 path encoding test passes on Japanese Windows (#5251).
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-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5071 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-09 04:13:58 +00:00
Toshi MARUYAMA f9717c0bda scm: git: fix PortgreSQL functional test fails (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5070 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-09 01:25:40 +00:00
Toshi MARUYAMA 16be7f2e30 scm: git: switch "-c core.quotepath=false" in git version above 1.7.2 or not (#5251).
The -c option was introduced in git version (1.7.2)
http://www.kernel.org/pub/software/scm/git/docs/RelNotes-1.7.2.txt

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5069 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 23:30:29 +00:00
Toshi MARUYAMA 779cab05f8 scm: git: change core.quotepath to false in test repository config (#5251).
The -c option was introduced in git version (1.7.2)
http://www.kernel.org/pub/software/scm/git/docs/RelNotes-1.7.2.txt

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5068 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 23:18:27 +00:00
Toshi MARUYAMA 45239fcb0a scm: git: add reverse log test in unit adapter test (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5067 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 15:05:41 +00:00
Toshi MARUYAMA f36f5d0fee scm: git: fix unit adapter test fails in Ruby 1.9 Linux latin-1 locale (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5066 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 13:22:53 +00:00
Toshi MARUYAMA 4f5f98220e scm: git: fix unit adapter test fails in Ruby 1.9 Linux latin-1 locale (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5065 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 12:45:32 +00:00
Toshi MARUYAMA 15ebb42579 scm: git: add path encoding select box at setting (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5064 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 12:08:56 +00:00
Toshi MARUYAMA 084bdd7559 scm: git: add latin-1 encoding directory test in unit model test (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5063 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 12:08:35 +00:00
Toshi MARUYAMA 4e0031a8f0 scm: git: add latin-1 encoding directory test in unit adapter test (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5062 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 12:08:14 +00:00
Toshi MARUYAMA de71851e98 scm: git: fix latin-1 directory entries() in adapter (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5061 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 11:13:18 +00:00
Toshi MARUYAMA 266e33b5f1 scm: git: add latin-1 encoding directory to test repository (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5060 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 11:01:51 +00:00
Toshi MARUYAMA d5b268129c scm: mercurial: add latin-1 encoding directory to test repository (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5059 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 10:35:48 +00:00
Toshi MARUYAMA e2adda86c2 scm: git: add latest changesets path encoding test in unit model test (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5058 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 07:41:25 +00:00
Toshi MARUYAMA 7d47bf8a7f scm: git: prepare path encoding test in unit model test (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5057 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 07:41:04 +00:00
Toshi MARUYAMA 7c7bbf6d18 scm: git: add latest changesets branch test in unit model test (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5056 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 07:06:46 +00:00
Toshi MARUYAMA 71ac6a29f0 scm: git: add latest changesets tag test in unit model test (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5055 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 07:06:25 +00:00
Toshi MARUYAMA cc6931f58d scm: git: add latest changesets limit test in unit model test (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5054 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 07:06:04 +00:00
Toshi MARUYAMA d0324858c1 scm: git: remove Setting.commit_logs_encoding from unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5053 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:50:29 +00:00
Toshi MARUYAMA c95e4fbea9 scm: git: add latest changesets test in unit model test (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5052 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:50:05 +00:00
Toshi MARUYAMA c381ce10e4 scm: git: prepare path encoding test in unit model test (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5051 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:49:44 +00:00
Toshi MARUYAMA 3abdd84a49 scm: git: add tests for path encoding entries() in unit adapter test (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5050 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:38:23 +00:00
Toshi MARUYAMA 3a39fc6176 scm: git: add core.quotepath = false to run git command (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5049 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:38:00 +00:00
Toshi MARUYAMA d03dd88717 scm: git: add tests for branch entries() in unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5048 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:37:39 +00:00
Toshi MARUYAMA 6d763215a9 scm: git: add tests for tag entries() in unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5047 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:37:18 +00:00
Toshi MARUYAMA 9294fb4699 scm: git: use scm_cmd() in adapter tags().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5046 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:10:53 +00:00
Toshi MARUYAMA 0e32fcf93e scm: git: add tags test in unit adapter test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5045 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:10:30 +00:00
Toshi MARUYAMA 04aca2fcb9 scm: git: add tests for path encoding cat, diff and blame in unit adapter test (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5044 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 06:10:07 +00:00
Toshi MARUYAMA dc4ab44938 scm: git: use scm_cmd() in adapter branches().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5043 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 05:18:04 +00:00
Toshi MARUYAMA 7e6a5ec7ab scm: git: support path encoding in adapter cat (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5042 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 05:17:43 +00:00
Toshi MARUYAMA c809c0c498 scm: git: support path encoding in adapter blame (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5041 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 05:17:22 +00:00
Toshi MARUYAMA c4b84ec510 scm: git: support path encoding in adapter entries() (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5040 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 04:50:48 +00:00
Toshi MARUYAMA 5086bc4383 scm: git: support path encoding in adapter diff (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5039 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 04:50:28 +00:00
Toshi MARUYAMA 32bd4ec0b4 scm: git: support path encoding in adapter revisions() (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5038 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 04:50:06 +00:00
Toshi MARUYAMA 10830d4dd3 scm: git: add two tags to test repository.
One is lightweight, another is annotated.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5037 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 03:52:33 +00:00
Toshi MARUYAMA 08ee6a3932 scm: git: convert path encoding in "git log" (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5036 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 03:29:58 +00:00
Toshi MARUYAMA 3c0fdd4938 scm: git: add instance variable for path encoding in adapter (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5035 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 03:29:36 +00:00
Toshi MARUYAMA a1364ed2b8 scm: git: code clean up adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5034 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-08 03:29:11 +00:00
Toshi MARUYAMA daac76f1b6 scm: git: update test repository for path encoding (#5251).
Mercurial and Git treats file names as byte string.
This git test repository contains Latin-1 encoding path.
Be careful on non Latin-1(CP1252) Windows.

Please see r4996 comment.

I removed a revision including "copied file" from r5026 test repository.
Mercurial supports "copy", but Git does not support.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5033 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-07 23:47:25 +00:00
Jean-Philippe Lang 5aca773ff9 CHANGELOG updated.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5030 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-07 19:26:24 +00:00
Toshi MARUYAMA 984cb589ef scm: git: remove "core.quotepath = true" to run git command (#5251).
If path encoding is UTF-8, git adapter may run on Linux.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5029 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-07 14:09:29 +00:00
Toshi MARUYAMA 30063d14c1 scm: git: use core.quotepath = true to run git command for database safety (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5028 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-07 13:46:42 +00:00
Toshi MARUYAMA 5d9962751c scm: git: backout r5026 (#5251).
In case git repository contains latin-1 path,
although Redmine uses "git log -C core.quotepath=false --encoding=UTF-8",
log encoding is latin-1.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5027 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-07 13:46:21 +00:00
Toshi MARUYAMA 3a56e1eeab scm: git: update test repository for path encoding (#5251).
Mercurial and Git treats file names as byte string.
This git test repository contains Latin-1 encoding path.
Be careful on non Latin-1(CP1252) Windows.

Please see r4996 comment.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5026 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-07 13:15:04 +00:00
Toshi MARUYAMA 90d4447bd3 scm: git: change core.quotepath = true temporarily to run git command (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5025 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-07 13:14:44 +00:00
Toshi MARUYAMA fce4dcb5a6 scm: git: add core.quotepath = false to run git command (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5024 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-07 12:42:14 +00:00
Toshi MARUYAMA 827efee243 scm: git: add core.quotepath = true in test repository config (#5251).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5023 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-07 12:41:52 +00:00
Jean-Philippe Lang 334132289c Fixed: error on JournalsController#index when custom fields are present (#7795).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5021 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-06 16:04:35 +00:00
Jean-Philippe Lang 0df520961c Updates for 1.1.2 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5019 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-06 13:18:33 +00:00
Jean-Philippe Lang 3beebe7409 Translations updates.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5016 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-06 13:01:46 +00:00
Jean-Philippe Lang 372cd6e44e Adds new string to locales.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5009 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 15:34:03 +00:00
Jean-Philippe Lang 5b01b3d594 Version list style updated.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5008 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 15:25:51 +00:00
Jean-Philippe Lang e41b76b459 Fixed: Login page should not show projects link and search box if authentication is required (#3715).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5007 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 15:14:24 +00:00
Jean-Philippe Lang 923d1f831f Removes duplicate DOM id in custom field form.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5006 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 14:55:33 +00:00
Jean-Philippe Lang 7257eabfc0 Extends custom field possible values textarea.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5005 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 14:52:47 +00:00
Jean-Philippe Lang 8fb446e87f Fixed: Email notifications are sent to watchers even if 'No events' setting is chosen (#7763).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5004 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 14:43:53 +00:00
Jean-Philippe Lang 36009de154 Adds email notifications support for news comments (#2074).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5003 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 14:32:58 +00:00
Toshi MARUYAMA 8d3773e0e1 scm: mercurial: add changesets order test in unit model test (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5002 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 14:03:19 +00:00
Toshi MARUYAMA 2aff1749ae scm: mercurial: add path encoding select box at setting (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5001 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 13:39:00 +00:00
Toshi MARUYAMA 82c670ba03 scm: mercurial: add path encoding tests in functional test (#2664, #4050).
TODO: This test fails in Ruby 1.9 and Encoding.default_external is not UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5000 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 11:07:58 +00:00
Toshi MARUYAMA 17219baa62 scm: mercurial: additional unit model tests for path encoding (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4999 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 08:08:32 +00:00
Toshi MARUYAMA d8e1af6156 scm: mercurial: add unit adapter test repository for path contains space (#2664, #4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4998 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 08:08:13 +00:00
Toshi MARUYAMA 53249469a0 scm: mercurial: update test repository for path contains space (#2664, #4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4997 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 08:07:53 +00:00
Toshi MARUYAMA b7dffa44c9 scm: mercurial: update test repository for path encoding (#2664).
Mercurial (and also Git) treats file names as byte string.
This mercurial test repository contains Latin-1 encoding path.
Be careful on non Latin-1(CP1252) Windows.

If your Windows is not Latin-1 Windows,
in order to checkout(update) Latin-1 path,
You need to use cygwin 1.7 and set LANG=en_US.ISO-8859-1.

Please refer.
http://mercurial.selenic.com/wiki/EncodingStrategy?action=recall&rev=6

Redmine mercurial adapter do not need to checkout(update) repository.
Mercurial does not have "bare" repository such as Git.
You can use "hg update null" for equivalent "bare" repository.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4996 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-04 04:25:48 +00:00
Toshi MARUYAMA 32e69dcaca scm: mercurial: convert copied file path encoding (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4995 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-03 12:44:14 +00:00
Toshi MARUYAMA 5c3caf2e6b scm: mercurial: remove localtime from adapter (#4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4994 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-03 12:11:23 +00:00
Toshi MARUYAMA 923558e45c scm: Ruby 1.9 compatibility for XML UTF-8 parsing.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4993 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-03 05:51:46 +00:00
Toshi MARUYAMA 71aac2e3fe scm: fix unit tests fails in Ruby 1.9.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4992 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-03 05:32:33 +00:00
Toshi MARUYAMA cc210c58a4 scm: mercurial: code clean up unit model test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4991 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-03 03:35:13 +00:00
Toshi MARUYAMA bc09628249 scm: code clean up repositories_helper.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4990 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-03 03:30:10 +00:00
Toshi MARUYAMA c3e8fc5f1a scm: mercurial: wrap revison, tag and branch with URL encoding for entries (#4455, #1981, #7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4989 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-02 10:17:36 +00:00
Toshi MARUYAMA a79c89eb3c scm: filesystem: add note "Default: UTF-8" in path encoding setting (#2274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4988 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-02 07:11:00 +00:00
Toshi MARUYAMA 0220e7db3b scm: subversion: add changesets order test in unit model test (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4987 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-02 07:10:39 +00:00
Toshi MARUYAMA b59becdfbc scm: git: add more tests in fetch changesets incremental unit model test (#5357).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4986 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-02 05:12:39 +00:00
Toshi MARUYAMA d245102e97 scm: code clean up repositories_helper.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4985 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-02 05:12:15 +00:00
Toshi MARUYAMA ee0d7d9bf0 scm: code clean up test/unit/changeset_test.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4984 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 15:35:27 +00:00
Toshi MARUYAMA 270dda120c scm: remove global repository log encoding setting from view (#1735).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4983 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 10:27:51 +00:00
Toshi MARUYAMA 5f5dec16f2 scm: add feature of per project repository log encoding setting (#1735).
Subversion, Mercurial and Git supports UTF-8 log.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4982 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 10:27:30 +00:00
Toshi MARUYAMA c09b6edaf4 scm: copy global log encoding setting to repository (#1735).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4981 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 10:14:47 +00:00
Toshi MARUYAMA 165ab7e6c3 scm: add log_encoding column to repositories table (#1735).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4980 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 09:47:06 +00:00
Toshi MARUYAMA f2c750c3e9 scm: darcs: refactor functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4979 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 07:38:05 +00:00
Toshi MARUYAMA 984283dde9 scm: darcs: change project id of unit app test from 1 to 3.
Project id 1 has Subversion fixtures.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4978 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 07:12:56 +00:00
Toshi MARUYAMA 089c23f228 scm: bazaar: change project id of unit app test from 1 to 3.
Project id 1 has Subversion fixtures.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4977 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 07:03:21 +00:00
Toshi MARUYAMA e7cc1f4b4b scm: code clean up at test/unit/changeset_test.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4976 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 05:49:14 +00:00
Toshi MARUYAMA 026c9e87c0 scm: add scm specific human_attribute_name for input validation.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4975 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 05:14:03 +00:00
Toshi MARUYAMA 571ecf07e3 scm: add notes "local repository" in Git and Mercurial setting.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4974 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-03-01 04:43:30 +00:00
Jean-Philippe Lang 93bc9b17a9 Stringify avatar to prevent "can't convert nil into String" errors on gantt (#7317).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4968 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-28 20:23:28 +00:00
Jean-Philippe Lang e1eafe3b25 Escapes body css classes.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4965 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-28 16:44:02 +00:00
Toshi MARUYAMA eb1271bb44 scm: git: use --encoding=UTF-8 in "git log" (#3396).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4964 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-28 14:12:47 +00:00
Toshi MARUYAMA 06c9eea67a scm: git: refactor lastrev() in adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4963 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-28 14:12:24 +00:00
Toshi MARUYAMA 06f078a813 scm: ignore log encoding setting in Subversion and Mercurial (#7597).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4962 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-28 12:09:32 +00:00
Toshi MARUYAMA 7664892b5d scm: refactor scm log encoding test (#1735, #3396, #7597).
Bazaar log depends on locale.
On Japanese Windows, standard out is CP932.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4961 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-28 10:03:09 +00:00
Toshi MARUYAMA f03e338880 scm: return if str.blank? in to_utf8(str).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4960 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-28 08:03:43 +00:00
Toshi MARUYAMA d7aa303a5c scm: git: move saving changesets from adapter to model (#3396).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4959 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-28 04:46:42 +00:00
Jean-Philippe Lang c781cbb2f7 Fixes a failing test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4958 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-27 15:51:10 +00:00
Toshi MARUYAMA 5d0869bcde scm: mercurial: change project id of unit app test from 1 to 3.
Project id 1 has Subversion fixtures.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4957 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-27 13:50:00 +00:00
Toshi MARUYAMA 186a64c557 scm: git: add utf-8 log test in app unit test (#3396).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4956 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-27 13:49:37 +00:00
Jean-Philippe Lang 5f44bf1e7a Adds new string to locales.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4955 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-27 13:43:18 +00:00
Jean-Philippe Lang 2627419131 Keep track of issue description changes (#746).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4954 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-27 13:34:41 +00:00
Jean-Philippe Lang ca807c8d92 Fixes wiki diff rendering.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4953 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-27 12:50:47 +00:00
Jean-Philippe Lang d06f4d013d Extracts a diff helper from the WikiDiff class.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4952 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-27 12:35:31 +00:00
Jean-Philippe Lang 2d115bbe70 Fixes syntax for time logging in commit messages (#7630, #7718).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4951 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-26 14:46:19 +00:00
Jean-Philippe Lang a78d565959 Adds support for SCM/LDAP passwords encryption in the database (#7411).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4950 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-26 13:09:25 +00:00
Jean-Philippe Lang e1ad561cf6 Adds a method to temporarily override configuration settings.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4949 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-25 14:30:05 +00:00
Jean-Philippe Lang 2b80f46361 Bulgarian translation update by Ivan Cenov.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4948 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 18:09:36 +00:00
Jean-Philippe Lang ead20ec2e5 Removes obsolete code from Opera pseudo right click (#7700).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4947 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 17:56:17 +00:00
Jean-Philippe Lang af8689db98 Do not responde with javascript on regular requests.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4946 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 17:52:38 +00:00
Toshi MARUYAMA 9a8c88ec0a scm: git: add flag of disable showing last commit in repository tree (#7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4945 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 13:01:13 +00:00
Toshi MARUYAMA 8bdf73882e scm: filesystem: fix mistake of respository select box on r4943 (#2274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4944 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 07:00:41 +00:00
Toshi MARUYAMA 3a20d13262 scm: filesystem: add path encoding select item (#2274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4943 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 05:59:42 +00:00
Toshi MARUYAMA 61667a2171 scm: code clean up repositories_helper.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4942 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 05:59:21 +00:00
Toshi MARUYAMA 9937ac677f scm: update adapter initialize() to use path encoding (#2664, #2274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4941 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 05:58:59 +00:00
Toshi MARUYAMA 4bf84ca468 scm: add "path_encoding" column in repositories table (#2664, #2274).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4940 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 05:58:37 +00:00
Toshi MARUYAMA a2e47f9fba scm: cvs: fix CVS diffs do not handle new files properly (#7615).
Contributed by Jim Naslund.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4939 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 04:03:43 +00:00
Toshi MARUYAMA e51aeb5a40 scm: use "ASCII-8BIT" in IO.popen() in Ruby 1.9.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4938 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-24 04:03:16 +00:00
Jean-Philippe Lang f27637b07c Adds tasks for locales maintenance.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4937 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 18:03:33 +00:00
Jean-Philippe Lang ce84bb1a01 Adds random salt to user passwords (#7410).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4936 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 17:27:31 +00:00
Jean-Philippe Lang 3ab981c04c Fixed: Bulk editing menu non-functional in Opera browser (#3132).
Contributed by Claudio Acciaresi.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4935 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 16:55:32 +00:00
Toshi MARUYAMA 0edde5da92 scm: mercurial: replace urllib.unquote to urllib.unquote_plus in helper (#4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4934 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 11:38:23 +00:00
Toshi MARUYAMA d671b11641 scm: mercurial: remove unused rhannotate command options in helper.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4933 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 07:57:33 +00:00
Toshi MARUYAMA a93d6a1621 scm: add unit RepositoryHelper test for Ruby 1.9 compatibility.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4932 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 07:04:52 +00:00
Toshi MARUYAMA f8da0127f7 scm: mercurial: annotate path encoding support in adapter (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4931 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 07:04:32 +00:00
Toshi MARUYAMA 494c2b5007 scm: mercurial: annotate path encoding support in helper (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4930 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 07:04:12 +00:00
Toshi MARUYAMA 35f075d8ad scm: fix diffs do not handle one line new files properly (#7618).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4929 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 07:03:45 +00:00
Toshi MARUYAMA 7dfd0bf679 scm: mercurial: path encoding support for "cat" in adapter (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4928 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-23 00:34:27 +00:00
Toshi MARUYAMA bb248fb037 scm: mercurial: change some newlines in mercurial_adapter.rb CRLF to LF.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4927 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 14:29:09 +00:00
Toshi MARUYAMA 87a6d79b5b scm: for log in Ruby 1.9, replace invalid UTF-8 to '?' instead of removing.
Refer r3466 #4773.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4926 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 13:39:37 +00:00
Toshi MARUYAMA 9f50e63583 scm: Ruby 1.9 compatibility for log.
Remove assuming UTF-8 is valid.
"\xC2\x80" of latin-1(iso-8859-1) is valid sequence of UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4925 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 13:39:12 +00:00
Toshi MARUYAMA 4257b1d9ad scm: fix unit changeset_test.rb test methods calls randomly.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4924 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 12:16:08 +00:00
Toshi MARUYAMA c37f638912 scm: mercurial: log and entries path encoding support in adapter (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4923 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 08:47:19 +00:00
Toshi MARUYAMA d43284ba04 scm: Ruby 1.9 compatibility for diff, cat and blame (#2664).
"\xC2\x80" of latin1(iso-8859-1) is valid sequence of UTF-8.
to_utf8() should not return string if it is UTF-8 valid_encoding.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4922 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 08:29:35 +00:00
Toshi MARUYAMA 1d6fbe5602 scm: Ruby 1.9 compatibility for browsing repository tree (#2664, #2274).
If repository path is not UTF-8, Ruby 1.9 shows trace.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4921 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 08:16:05 +00:00
Toshi MARUYAMA 11e4c5c1ea scm: Ruby 1.9 compatibility in getting scm version (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4920 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 08:05:51 +00:00
Toshi MARUYAMA 1236e037f2 scm: mercurial: override initialize() for path encoding (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4919 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 08:05:29 +00:00
Toshi MARUYAMA 069d057143 scm: git: Ruby 1.9 compatibility of adapter test (#3396).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4918 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-22 00:40:02 +00:00
Jean-Philippe Lang 496f22e422 Moves scm path configuration examples in comments.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4917 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 17:40:54 +00:00
Jean-Philippe Lang d78fa206c2 Extracts gantt subjects styles to css (#7280).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4916 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 17:10:15 +00:00
Jean-Philippe Lang 727ce783c0 Removed .settings folder (#7676).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4915 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 15:26:43 +00:00
Jean-Philippe Lang e68507265e Adds full subject as gantt subject title (#7280).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4914 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 15:17:52 +00:00
Jean-Philippe Lang 2f7084f7a2 Prevent text wrap in gantt subjects (#7280).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4913 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 15:06:11 +00:00
Toshi MARUYAMA 111ae3c2e9 scm: prevent diff shows trace if UTF-8 is invalid in Ruby 1.9.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4912 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 14:28:41 +00:00
Jean-Philippe Lang 4abdc0f225 Makes filters behaviour consistent with the issue list.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4911 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 14:02:22 +00:00
Jean-Philippe Lang 40f2d5a995 Makes title/filters consistent with the issue list.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4910 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 13:58:08 +00:00
Jean-Philippe Lang a11e3a85d6 Preserve Issues/Gantt/Calendar tab when displaying a saved query (#7605).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4909 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 13:52:19 +00:00
Jean-Philippe Lang 0efc783a7e Splits private/public issue queries in the sidebar (#1067).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4908 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 13:34:33 +00:00
Toshi MARUYAMA a189b4b377 scm: filesystem: refactor for path encoding (#2274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4907 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 12:10:39 +00:00
Toshi MARUYAMA 8963579be3 scm: add "scm_iconv" method for repository path encoding in abstract_adapter.rb (#2664, #2274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4906 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 12:10:16 +00:00
Jean-Philippe Lang ca3b503478 Updgraded Rails to 2.3.11 (#6887).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4904 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 11:02:18 +00:00
Jean-Philippe Lang c35a79ab44 Added Persian translation contributed by Behrang Noroozinia (#7418).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4903 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 10:08:59 +00:00
Jean-Philippe Lang 317c35c36b Fills locales with new strings.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4902 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 10:02:47 +00:00
Jean-Philippe Lang ea33418828 Updated basque and czech translations. Contributed by Ales Zabala Alava and Michal Gebauer.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4901 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 10:01:47 +00:00
Jean-Philippe Lang 17591a3ea5 Warning on leaving a page with unsaved content in textarea (#2910).
The warning can be turned off in the user's preference.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4900 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 09:53:29 +00:00
Toshi MARUYAMA 11c72f2823 scm: add CP932 at Setting::ENCODINGS (#2664, #2274).
CP932 is variant Japanese Shift_JIS on Windows.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4899 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 09:41:34 +00:00
Toshi MARUYAMA 842968f636 scm: mercurial: add 'rhcat' function using URL encoding in mercurial helper extension (#2664).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4898 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 04:00:12 +00:00
Toshi MARUYAMA 7a9136f93a Ruby 1.9 compatibility of unified_diff.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4897 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 03:59:50 +00:00
Toshi MARUYAMA 3e463c4e69 scm: subversion: change some functional tests project id from 1 to 3.
TODO: remaining tests read fixture. All tests need to read test repository.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4896 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-21 03:59:30 +00:00
Jean-Philippe Lang 4b096e9a56 Allow additional workflow transitions for issue author and assignee (#2732).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4895 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 15:38:07 +00:00
Jean-Philippe Lang 7ddb1c694a Fixed: date part of the time default format doesn't respect the date format (#7639).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4894 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 14:56:37 +00:00
Toshi MARUYAMA 20a54f1ef5 scm: git: move "--no-color" option from scm_cmd() to revision().
Ruby 1.9.2 test fails.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4893 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 14:49:09 +00:00
Jean-Philippe Lang fdff8d6b9c Use #custom_field_values to display issue custom fields in email, just like on regular views (#7604).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4892 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 14:27:34 +00:00
Jean-Philippe Lang e29b99c67e Do not keep illegitimate custom_values when setting custom_field_values (#7604).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4891 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 14:26:23 +00:00
Jean-Philippe Lang 490ad9eeb8 Fixed: Workflow summary shows X icon for workflow with exactly 1 status transition (#7611).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4890 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 13:13:10 +00:00
Jean-Philippe Lang 58f5d3ab09 Fixed: Syntax highlighting unavailable from board new topic or topic edit preview (#7625).
Contributed by Etienne Massip.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4889 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 13:11:10 +00:00
Jean-Philippe Lang f357912d21 Fixed: SQL error when filtering issues with an empty group or role (#7656).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4888 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 13:03:32 +00:00
Toshi MARUYAMA 329b2aa263 scm: git: fix wrong commit range in git log command on Windows (#7657).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4887 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 01:33:50 +00:00
Toshi MARUYAMA 1c5cd49cd2 scm: git: add new method 'scm_cmd' to wrap shellout.
Refer Mercurial adapter r4830.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4886 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 01:33:30 +00:00
Toshi MARUYAMA 915107a0ec scm: git: add --no-color option to run "git --version".
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4885 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-20 01:33:09 +00:00
Toshi MARUYAMA af01f5259b scm: mercurial: code cleanup.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4884 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-19 10:34:37 +00:00
Toshi MARUYAMA 824adaf30c scm: git: change select label to 'Path to repository'.
Redmine requires bare repository. '.git' is confusing.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4883 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-19 06:42:50 +00:00
Toshi MARUYAMA a092f5e0b9 scm: catch exception of getting command and version in model (#4273).
If command does not exist, Windows raises exception in shellout().
Linux does not raise exception.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4882 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-19 01:11:48 +00:00
Toshi MARUYAMA 3861214ccc scm: darcs: override client_available method (#4273).
I forgot it.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4881 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-19 01:11:30 +00:00
Toshi MARUYAMA 537c53f869 scm: darcs: space cleanup in adapter.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4880 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-19 00:56:13 +00:00
Toshi MARUYAMA c6e1d4f39d scm: mercurial: fix exception operation in adapter all methods using xml and io.read (#4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4879 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 14:49:31 +00:00
Toshi MARUYAMA 96f82be2f4 scm: mercurial: simplify fixing exception operation in adapter "summary" method (#4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4878 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 14:49:09 +00:00
Toshi MARUYAMA 190d288381 scm: mercurial: fix exception operation in adapter "summary" method (#4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4876 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 12:44:43 +00:00
Toshi MARUYAMA 0833abd9e5 scm: mercurial: unit test for named branches at adapter (#7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4875 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 07:15:58 +00:00
Toshi MARUYAMA 68fe853477 scm: mercurial: support named branches at adapter (#7246).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4874 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 07:15:37 +00:00
Toshi MARUYAMA 8c9be39350 scm: mercurial: unit test for tags at adapter (#1981).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4873 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 07:15:13 +00:00
Toshi MARUYAMA 25d642e0ea scm: mercurial: support tags at adapter (#1981).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4872 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 07:14:51 +00:00
Toshi MARUYAMA 0247a149c4 scm: mercurial: temporary disable tags and branches at model (#1981, #7246, #4455).
Until latest_changesets supports tags and branches.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4871 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 07:14:32 +00:00
Toshi MARUYAMA 0b19757303 scm: mercurial: unit app test for latest_changesets SQL "like" special character '%' and '_'.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4870 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 05:55:45 +00:00
Toshi MARUYAMA 0e0a8c01ea scm: mercurial: unit app test for latest_changeset.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4869 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 05:55:25 +00:00
Toshi MARUYAMA b3c517387a scm: mercurial: improvement latest_changesets without supporting tags and named branches (#4455).
Based on latest-changesets-improvements-2.diff of #6159.
http://www.redmine.org/attachments/4332/latest-changesets-improvements-2.diff

Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4868 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 05:55:02 +00:00
Toshi MARUYAMA d393306a0c scm: mercurial: entries unit lib test for named branch (#7246).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4867 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 05:00:07 +00:00
Toshi MARUYAMA b6f12e28d7 scm: mercurial: entries unit lib test for tag (#1981).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4866 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 04:59:45 +00:00
Toshi MARUYAMA 55fdc23981 scm: mercurial: remove "TODO" comment and fix indent of unit lib test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4865 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 04:20:40 +00:00
Toshi MARUYAMA 628130ef5c scm: mercurial: unit lib test for entries (#3421).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4864 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 04:13:40 +00:00
Toshi MARUYAMA a3a9661da6 scm: mercurial: move entries unit test from app to lib.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4863 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 04:13:17 +00:00
Toshi MARUYAMA 17f1b1d0bc scm: mercurial: fix unit lib test_info test fails on Windows.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4862 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 00:58:08 +00:00
Toshi MARUYAMA bd9a3a720c scm: space cleanup of lib/redmine/scm/adapters/abstract_adapter.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4861 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-18 00:57:43 +00:00
Toshi MARUYAMA 66c979d63c scm: fix diff revision param validation.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4860 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-17 14:17:04 +00:00
Toshi MARUYAMA 7a3d385b8e scm: mercurial: fix Ruby 1.9 "hg diff" test fails (#7518).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4859 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 16:06:24 +00:00
Toshi MARUYAMA 0a87041504 scm: in repository tree, use find_changeset_by_name instead of changesets.find_by_revision (#3724, #3421).
Mercurial revision numbers are far too brittle.
Please see #6681 description.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4858 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 15:43:36 +00:00
Toshi MARUYAMA 0185d23c54 scm: mercurial: add identifier to entry.lastrev (#3724, #3421).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4857 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 15:43:15 +00:00
Toshi MARUYAMA 1f836a1d43 scm: mercurial: rewrite MercurialAdapter#entries to show per-file change log and size (#3421, #4455).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4856 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 13:35:52 +00:00
Toshi MARUYAMA 05210f18ed scm: mercurial: set instance value flag of whether "hg diff -c" supports true at tests (#7518).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4855 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 11:18:18 +00:00
Toshi MARUYAMA 4b1e16e13b scm: mercurial: rewrite MercurialAdapter#diff by using helper extension (#4455, #7518).
fix incompatibility of diff with Mercurial < 1.1.

Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4854 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 11:17:58 +00:00
Toshi MARUYAMA 671b16f898 scm: mercurial: add instance value flag of whether "hg diff -c" supports at tests (#7518).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4853 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 11:17:37 +00:00
Toshi MARUYAMA 700577c533 scm: mercurial: code clean up unit app test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4852 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 11:17:15 +00:00
Toshi MARUYAMA 724afdf49d scm: git: implement find_changeset_by_name (#7047).
SQL "like" is slow.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4851 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 11:16:53 +00:00
Toshi MARUYAMA 862058795f scm: git: change project id of unit app test from 1 to 3.
Project id 1 has Subversion fixtures.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4850 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 11:16:29 +00:00
Toshi MARUYAMA 5274230fda scm: mercurial: refactor Repository::Mercurial#fetch_changesets (#4455).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4849 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 07:32:35 +00:00
Toshi MARUYAMA 8acdda9816 scm: mercurial: rewrite MercurialAdapter#revisions as an iterator (#4455).
Now it uses XmlMini.parse() in place of slow REXML.

Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4848 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 07:32:13 +00:00
Toshi MARUYAMA 08ed9cb5d5 scm: mercurial: change identifier to revision in fetching revisions.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4847 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 07:31:52 +00:00
Toshi MARUYAMA 4fe8259017 scm: mercurial: rewrite MercurialAdapter#info by using helper extention (#4455).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4846 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 04:41:30 +00:00
Toshi MARUYAMA ef3fbeeaa0 scm: mercurial: add "summary" method in adapter (#4455).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4845 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 04:41:10 +00:00
Toshi MARUYAMA 2c4836cbae scm: mercurial: switch root_url or url in "hg" method (#4455).
"info" sets root_url from url.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4844 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 04:40:42 +00:00
Toshi MARUYAMA 202ebe1d12 scm: mercurial: add compatible test for "revisions" method.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4843 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 03:47:27 +00:00
Toshi MARUYAMA 109afa7881 scm: mercurial: refactor "cat" by using hg helper method (#4455).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4842 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 03:47:05 +00:00
Toshi MARUYAMA 82c6d84de8 scm: mercurial: refactor "annotate" by using hg helper method (#4455).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4841 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 01:14:54 +00:00
Toshi MARUYAMA ee8ae3c09b scm: mercurial: add "hgtarget" method (#4455).
Abstract adapter shell quotes paths.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4840 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 01:14:34 +00:00
Toshi MARUYAMA f66b53577f scm: mercurial: change "--cwd" option to "-R" for running "hg" (#4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4839 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 01:14:10 +00:00
Toshi MARUYAMA a6fad1eb66 scm: mercurial: add compatible test for "info" method.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4838 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-16 01:13:49 +00:00
Toshi MARUYAMA ec9eb44d6b scm: mercurial: ignore redminehelper.pyc and redminehelper.pyo for Subversion (#4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4837 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 11:10:46 +00:00
Toshi MARUYAMA aed08706e0 scm: bazaar: move cat and annotate test from unit app test to unit lib test.
Bazaar supports revision number and do not need to read database.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4836 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 11:05:33 +00:00
Toshi MARUYAMA 0d5d93343e scm: cvs: set client available if cvs version above 1.12.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4835 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 11:05:13 +00:00
Toshi MARUYAMA 9a3ae4cee5 scm: mercurial: ignore redminehelper.pyc and redminehelper.pyo for Git and Mercurial (#4455).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4834 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 11:04:52 +00:00
Toshi MARUYAMA 2547e57168 scm: mercurial: add Mercurial helper extension (#4455).
* 'rhsummary' and 'rhmanifest' for reducing the number of hg command calls.
* 'rhdiff' for compatibility with Mercurial < 1.1.

Also renamed TEMPLATES_DIR to HELPERS_DIR because the directory now contains
templates and a helper extension.

Original version was written by Alessio Franceschelli,
downloaded from http://www.redmine.org/attachments/3395/overhaul.py

Contributed by Alessio Franceschelli and Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4833 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 11:04:30 +00:00
Toshi MARUYAMA 2afc8e8c95 scm: cvs: add methods of getting cvs version and add unit lib test (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4832 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 08:04:11 +00:00
Toshi MARUYAMA 50bbb97848 scm: bazaar: add methods of getting bazaar version and add unit lib test (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4831 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 07:04:49 +00:00
Toshi MARUYAMA a9429df880 scm: mercurial: add new method 'hg' to wrap shellout (#4455).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4830 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 07:04:29 +00:00
Toshi MARUYAMA 4f1b1d9242 scm: git: add methods of getting git version and add unit lib test (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4829 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 05:58:31 +00:00
Toshi MARUYAMA e3b3152a5d scm: mercurial: switch shell quote revision with argument.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4828 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 05:58:11 +00:00
Toshi MARUYAMA 05f260da65 scm: subversion: change newlines LF to CRLF at lib/redmine/scm/adapters/subversion_adapter.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4827 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 05:33:25 +00:00
Toshi MARUYAMA 5d026d6fd3 scm: subversion: change unit app test project id from 1 to 3.
Fixtures have project id 1 subversion changesets and changes.

Change file:/// to file://.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4826 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 02:29:47 +00:00
Toshi MARUYAMA 41f190e8ed scm: subversion: refactor getting svn version and add lib test (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4825 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 02:12:39 +00:00
Toshi MARUYAMA 60d80653ba scm: catch CommandFailed during bulk Repository.fetch_changesets (#4455).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4824 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-15 02:12:19 +00:00
Toshi MARUYAMA 9c1db1e545 scm: git: remove localtime (#6346).
No needs to use localtime.
If we use localtime, we should clone.

See r4794 and r4802.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4823 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-14 08:45:54 +00:00
Toshi MARUYAMA cc4e8fe0d6 scm: add scm command and version methods at repository models (#4273).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4822 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-14 08:45:34 +00:00
Toshi MARUYAMA 8b98c05879 scm: use shell quote for scm command at adapter level (#7517, #4273).
"C:\Program Files\TortoiseHg\hg.exe" can be used in config/configuration.yml.

In Ruby 1.9 IO.popen, if cmd is an Array of String,
it will be used as the subprocess‘s argv bypassing a shell.

See http://www.ruby-doc.org/core/classes/IO.html

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4821 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-14 06:14:34 +00:00
Jean-Baptiste Barth 8b5ebd92c9 Introduced MailHandler#dispatch_to_default method to make MailHandler more extensible. #7598
Contributed by Yuki Sonoda

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4820 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-12 10:08:11 +00:00
Toshi MARUYAMA 3493bb1d37 scm: space and tab cleanup of app/controllers/repositories_controller.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4817 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-12 09:44:46 +00:00
Toshi MARUYAMA 4957f91639 scm: fix non ASCII filename downloaded from repo is broken on Internet Explorer (#7288).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4816 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-12 09:44:23 +00:00
Toshi MARUYAMA 2a11abdcfc scm: cvs: fix most binary files become corrupted on Windows (#6090).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4815 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-12 09:43:57 +00:00
Jean-Baptiste Barth 4caca2492b Ignore .project and .loadpath files for hg/git mirrors. #7497
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4813 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-12 09:02:02 +00:00
Jean-Baptiste Barth da43c0ddc6 Added 'retro' style for gravatars. #7608
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4811 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-12 08:16:37 +00:00
Toshi MARUYAMA 632151dfff scm: bazaar: fix typo and mistakes.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4810 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-11 16:00:57 +00:00
Toshi MARUYAMA cee9df5b2f scm: git: fix typo of unit lib test.
This file includes UTF-8 "literal".
We need to consider Ruby 1.9 compatibility.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4809 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-11 15:44:52 +00:00
Toshi MARUYAMA a88077a0bd scm: cvs: fix unit lib test fails on Windows.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4808 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-11 15:32:45 +00:00
Toshi MARUYAMA fe37f45cb5 scm: bazaar: prepare version string unit lib test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4807 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-11 15:31:11 +00:00
Toshi MARUYAMA 6aaf5db1e6 scm: change gunzip to tar -z option for scm repository setup in lib/tasks/testing.rake.
Pipe does not work on Mingw Ruby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4806 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-11 15:30:45 +00:00
Toshi MARUYAMA ddaf897596 scm: git: prepare version string unit lib test and git log encoding (#3396).
This file includes UTF-8 literal.
We need to consider Ruby 1.9 compatibity.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4805 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-11 15:30:22 +00:00
Toshi MARUYAMA 40b953f05a scm: cvs: code clean up.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4804 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-11 15:29:56 +00:00
Toshi MARUYAMA 95638e8f6d scm: subversion: prepare version string unit lib test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4803 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-10 18:13:10 +00:00
Toshi MARUYAMA 109fd2cdfc scm: cvs: generate pseudo scmid for auto issue close text (#6706).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4802 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-07 10:26:15 +00:00
Toshi MARUYAMA e9ab2de1e7 scm: cvs: change temporary revision number from "_N" to "tmpN" (#996, #3761, #6706).
'_' is SQL "like" special character.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4801 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-07 10:25:52 +00:00
Jean-Baptiste Barth 9c070fe092 Fixed various typos in french locale
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4799 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-06 00:31:15 +00:00
Toshi MARUYAMA fcdeb1613a scm: add scm_cvs_command at config/configuration.yml.example (#7517).
I forgot to add it.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4798 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-05 00:57:41 +00:00
Toshi MARUYAMA 3ee203ef0c scm: change key name of configurable command name (#7517, #6159, #7047).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4797 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-04 10:24:10 +00:00
Toshi MARUYAMA c1ec8c5ea3 scm: use "e.g." for "for example" at config/configuration.yml.example (#7517).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4796 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-04 05:30:14 +00:00
Toshi MARUYAMA 0ffe328c0a scm: add a feature of configurable path of executable for scm adapters (#7517).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4795 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-04 04:28:39 +00:00
Toshi MARUYAMA 10ca61a13b scm: cvs: use localtime at cvs rlog -d option (#996, #3761).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4794 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-02 13:13:44 +00:00
Toshi MARUYAMA 33d6b90616 scm: cvs: add unit lib test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4793 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-02 13:13:20 +00:00
Toshi MARUYAMA 9f1a63075e scm: mercurial: add unit lib test for the previous changeset isn't the parent (#7253, #7518).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4792 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-02 10:01:22 +00:00
Toshi MARUYAMA 08f02c5b65 scm: cvs: add fetch_changesets at all unit app test methods.
Redmine generates pseudo revision number, so all tests need to read database.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4791 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-02 10:00:20 +00:00
Toshi MARUYAMA f7f858f056 scm: cvs: code clean up.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4790 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-02 04:01:27 +00:00
Toshi MARUYAMA 2b79e05e6c scm: cvs: change project id of functional test from 1 to 3.
Project id 1 has Subversion fixtures.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4789 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-02 04:00:59 +00:00
Toshi MARUYAMA f922fa765f scm: cvs: change project id of unit app test from 1 to 3.
Project id 1 has Subversion fixtures.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4788 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-02 04:00:36 +00:00
Toshi MARUYAMA 17595c4e31 Ignore config/configuration.yml (#7408).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4787 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-02-01 13:48:56 +00:00
Jean-Philippe Lang a5e3ac2864 Update for 1.1.1 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4784 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-30 14:37:23 +00:00
Jean-Philippe Lang 48d3ab5f44 Reverted r4780 that broke gantt tests (#7280).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4782 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-30 09:09:50 +00:00
Jean-Philippe Lang 3c8df553ae Removed issue subjects wrapping in gantt (#7280).
Contributed by Etienne Massip.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4780 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-30 06:54:00 +00:00
Jean-Philippe Lang ab2933a414 Translations updates.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4777 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-30 06:37:01 +00:00
Jean-Philippe Lang 0b53c7c224 Moves .htaccess to htaccess.fcgi.example (#7256).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4775 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-30 06:31:28 +00:00
Jean-Philippe Lang d39e12c202 Prevent error when Mantis version.date_order is nil (#7476).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4765 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-28 19:45:09 +00:00
Jean-Philippe Lang 898a8c885b Fixed: Relations are not displayed after adding/removing an issue relation (#7463).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4764 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-27 21:38:47 +00:00
Jean-Philippe Lang 73a2d926f6 Fixed: no email sent with 'Notifiy for any event on the selected projects only' (#7421).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4761 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-24 17:28:59 +00:00
Jean-Philippe Lang a2a01e6b72 Moves link_to_message to ApplicationHelper to make it available to redmine links.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4760 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 17:02:10 +00:00
Jean-Philippe Lang b20210e83c Adds visible scope to redmine links queries.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4759 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 16:47:59 +00:00
Jean-Philippe Lang 777ccf1328 Adds support for cross project Redmine links (#7409).
See public/help/wiki_syntax_detailed.html for the syntax.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4758 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 16:12:38 +00:00
Jean-Philippe Lang 507f9d753f Set the httponly flag on the autologin cookie.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4757 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 11:40:07 +00:00
Jean-Philippe Lang 55acbcb560 Makes the autologin cookie configurable (#1763).
The cookie attributes (name, path, secure) can now be set in config/configuration.yml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4756 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 11:20:46 +00:00
Jean-Philippe Lang 7dd464c577 Makes the folder for attachments storage configurable in config/configuration.yml (#1236).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4755 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 10:41:43 +00:00
Jean-Philippe Lang 3b28a0e231 Ignores eclipse settings files.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4754 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 10:27:02 +00:00
Jean-Philippe Lang 5d32ce6e91 Ignores db/*.sqlite3.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4753 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 10:25:48 +00:00
Jean-Philippe Lang 4cefae0aaa Adds an application configuration file: config/configuration.yml (#7408).
Email delivery settings that were stored in config/email.yml should be moved to this new configuration file.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4752 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 10:22:00 +00:00
Toshi MARUYAMA e173f7e72d scm: darcs: fix Darcs adapter recognizes new files as modified files above Darcs 2.4 (#7415).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4749 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 04:17:26 +00:00
Toshi MARUYAMA abd2762aed scm: darcs: add compatible test of Darcs 2.3 and 2.4 (#7415).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4748 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-23 04:17:03 +00:00
Toshi MARUYAMA 1df08afefd scm: darcs: switch '.' or @url at entries() in darcs version (#4899).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4744 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 15:38:47 +00:00
Toshi MARUYAMA 0d3703c0b3 scm: darcs: change io.gets to io.read and add darcs version unit (#4494, #5404).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4743 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 15:38:23 +00:00
Toshi MARUYAMA 8fb9728b45 scm: darcs: add unit lib test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4742 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 15:37:59 +00:00
Jean-Philippe Lang b8dee485ca Moves relations fetching from views to the controller and skip invalid relations (#7385).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4741 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 13:28:20 +00:00
Jean-Philippe Lang 07a49b94ad Removed extraneous hidden_field on wiki history (#7379).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4740 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 13:21:24 +00:00
Jean-Philippe Lang 144ca23442 Coderay upgraded to 0.9.7 (#5344).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4739 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 13:18:01 +00:00
Jean-Philippe Lang e4faf3553a Fixes french translation of "Connection" (#7348).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4738 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 12:35:05 +00:00
Jean-Philippe Lang b9385dceb9 Make POP3 mail fetcher log messages instead of puts (#7177).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4737 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 12:09:07 +00:00
Jean-Philippe Lang 494cd8cc36 Avoid "private method `gsub' called for nil:NilClass" error when exporting issues with nil description (#7386).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4736 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 11:57:02 +00:00
Jean-Philippe Lang 419b195019 Fixed: subtasks are deleted (not destroyed) when destroying parent issue (#7385).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4735 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-22 11:46:15 +00:00
Toshi MARUYAMA ccdea234ad scm: functional test of using format_revision() for annotate (#3724).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4734 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-21 13:22:28 +00:00
Toshi MARUYAMA 6e1fa1603b scm: use format_revision() for history, view and annotate (#3724).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4733 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-21 13:22:08 +00:00
Jean-Philippe Lang fd3c85dc0d Load csshover.htc for IE6 only as later versions support hover on non-link elements.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4731 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-16 16:36:58 +00:00
Jean-Philippe Lang e17fadd07a Do not show "for only project I select" notification option on application settings form (#7294).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4730 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-16 15:36:42 +00:00
Jean-Philippe Lang e9f62d1209 Enable ability for administrators to delete users (#7296).
User's personal data (eg. preferences, tokens, private queries...) are deleted, public data (eg. issues, wiki edits, attachments...) are reassigned to the anonymous user.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4729 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-16 15:23:11 +00:00
Jean-Philippe Lang 0e3017dc62 Fixed: "Notifiy for only project I select" is randomly displayed (#7294).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4727 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-16 14:40:38 +00:00
Jean-Philippe Lang e809d40f4e When destroying a user, remove all references to that user (#7296).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4726 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-16 14:27:02 +00:00
Jean-Philippe Lang ced782ecb2 Adds a User-Agent header to Redmine mailhandler requests (#7318).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4725 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-15 14:48:33 +00:00
Jean-Philippe Lang 46f2f9cff7 Fixed: Label not translated in french in Settings/Email Notification tab (#7313).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4724 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-15 14:25:11 +00:00
Jean-Philippe Lang befd725b8b Prevent SystemStackError on Issue#all_dependent_issues with circular dependency (#7320).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4723 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-15 14:12:18 +00:00
Jean-Philippe Lang 7ef527a653 Adds colon after label.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4722 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-15 14:04:11 +00:00
Jean-Philippe Lang d2b6a6bc2c Adds a test for issue circular dependency validation.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4721 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-15 14:03:39 +00:00
Jean-Philippe Lang b2425dbe7f French locale update (#7337).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4720 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-15 14:02:44 +00:00
Jean-Philippe Lang 4c46fa4ef4 Fixed: "Loading..." icon does not disappear after adding a project member when there is no other member to add (#7265).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4719 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-15 13:20:18 +00:00
Toshi MARUYAMA 2b24b6c9bb scm: mercurial: fix revision at functional diff test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4718 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-15 10:15:41 +00:00
Toshi MARUYAMA effc33fe5b scm: mercurial: fix id at functional test_empty_revision test(#7307).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4714 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-14 23:10:49 +00:00
Toshi MARUYAMA 61a517179d scm: git: fix id at functional test_empty_revision test(#7307).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4713 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-14 23:10:13 +00:00
Toshi MARUYAMA acb0d96617 scm: use #blank? instead of #nil? || #empty? at Repository#find_changeset_by_name(name) (#7307).
Referring r4711.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4712 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-14 22:51:12 +00:00
Jean-Philippe Lang e14e244f7b Use #blank? instead of #nil? || #empty?.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4711 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-14 20:24:03 +00:00
Jean-Philippe Lang 7d0b1b3830 Respond with 404 instead of 500 when revision/entry is not found in the repository (#7307).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4710 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-14 20:22:36 +00:00
Jean-Philippe Lang a81953ef84 Adds a test for TimeEntry#spent_on= with invalid string.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4709 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-14 18:45:28 +00:00
Jean-Philippe Lang 88d847a1d5 Fixes TimeEntry#spent_on= so that datetimes don't get stored in SQLite3 (#7258).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4708 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-14 18:04:16 +00:00
Toshi MARUYAMA 7a35682cd9 scm: mercurial: unit lib test for entries accept both of revision number and changeset id (#3724, #3421)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4705 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-13 12:05:11 +00:00
Toshi MARUYAMA 89627d0334 scm: mercurial: fix error on revision page for empty revision (#7307).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4704 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-13 12:04:51 +00:00
Toshi MARUYAMA 98b3a50657 scm: fix error on revision page for empty revision (#7307).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4703 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-13 12:04:30 +00:00
Jean-Philippe Lang 43f6a62680 Removed obsolete css class (#7279).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4702 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 20:37:31 +00:00
Jean-Philippe Lang c19e3fbe3a Set csv separator to ; for nl locale (#7274).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4701 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 20:35:50 +00:00
Jean-Philippe Lang 2f3b1ca6b8 Fixed: Enabling gravatas causes usernames to overlap first name field in user list (#7277).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4700 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 20:27:26 +00:00
Toshi MARUYAMA eda1cd2faa scm: mercurial: change two revision diff text of mercurial (#3724).
For example, "4:def6d2f1254a 2:400bb8672109".

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4699 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 16:04:28 +00:00
Toshi MARUYAMA ebb19c5863 scm: changing two revision diff text at SCM adapter level (#3724).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4698 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 16:04:07 +00:00
Toshi MARUYAMA fdd0a2ca9b scm: mercurial: use revision text mercurial style "2:400bb8672109" (#3724).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4697 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 16:03:45 +00:00
Toshi MARUYAMA f17e1ce368 scm: mercurial: add "commit:xxx" and "rNN" link test for mercurial (#3724).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4696 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 16:03:24 +00:00
Toshi MARUYAMA d67185ec7e scm: mercurial: use scmid as identifier (#3724).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4695 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 16:03:01 +00:00
Toshi MARUYAMA 36b99a4ed3 scm: use scmid for "commit:xxx" link if available (#3724).
scmid is more solid than revision number.

Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4694 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 16:02:36 +00:00
Toshi MARUYAMA fb51f27b8a scm: fix indents in "commit:xxx" unit test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4692 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 15:23:42 +00:00
Toshi MARUYAMA e92cd2091c scm: fix assert_equal parameter order in subversion and git unit test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4691 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 15:23:22 +00:00
Toshi MARUYAMA 6a6b68d295 scm: add compatible "commit:xxx" link test for git and darcs.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4690 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 11:06:56 +00:00
Toshi MARUYAMA 80b329d031 scm: mercurial: change diff option from --git to --config diff.git=false (#7253).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4688 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 08:41:35 +00:00
Toshi MARUYAMA 331cdbed2f scm: mercurial: fix r4686 setup mercurial test repository (#7272).
If redmine top directory has .hg, "hg clone" synchronizes all revisions to test repository.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4687 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 08:41:11 +00:00
Toshi MARUYAMA a6f05b5e56 scm: mercurial: diff '-c' option supports above Mercurial 1.2 (#3724, #7253).
r4662 fails in old Mercurial.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4686 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 05:15:56 +00:00
Toshi MARUYAMA 35b9972c81 scm: mercurial: test:scm:setup:mercurial task can be simpler (#7272).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4683 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-11 04:18:08 +00:00
Jean-Philippe Lang 7b7577c747 Fixed MailHandler broken by I18n fallback added in r4679.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4682 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-10 19:57:41 +00:00
Jean-Philippe Lang a9c4ec31ca Fixes fixture added in r4680.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4681 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-10 19:45:20 +00:00
Jean-Philippe Lang f1a5dca2ba Fixed: wiki pages with cyrillic characters not found with postgresql (#7245).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4680 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-10 18:32:04 +00:00
Jean-Philippe Lang 88727bf070 Adds fallback to 'en' locale for untranslated strings (#5518).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4679 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-10 18:25:12 +00:00
Jean-Philippe Lang bebde1596c Make sure en is the current locale when running the test (#7266).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4677 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-10 17:55:57 +00:00
Jean-Philippe Lang 2cbf60851f Store the mercurial test repository as a bundle to make it compatible with older hg versions.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4676 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-10 17:43:01 +00:00
Jean-Philippe Lang a9eea27742 Fixes random failure (database may not return changes in the order expected in the test).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4674 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 21:12:20 +00:00
Jean-Philippe Lang 50d962bba1 Trying to fix random failures with postgresql due to different ids order in urls.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4673 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 21:01:40 +00:00
Jean-Philippe Lang 18cb215d72 Updated CHANGELOG for 1.1.0 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4670 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 15:57:44 +00:00
Toshi MARUYAMA b017a846ba scm: mercurial: remove new line in diff unit test(#7253).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4669 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 14:19:39 +00:00
Toshi MARUYAMA 1ff52e5c5a scm: mercurial: add --git option in 'hg diff' (#7253).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4668 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 13:53:47 +00:00
Toshi MARUYAMA 08c093bc85 scm: mercurial: replace identifier to hgrev(identifier).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4667 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 09:54:30 +00:00
Toshi MARUYAMA ed246cef41 scm: mercurial: wrap identifier with shell_quote at hgrev(identifier).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4666 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 09:54:10 +00:00
Toshi MARUYAMA e4f72a8e3a scm: add compatible functional test fof changing diff revisions label at SCM adapter level.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4665 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 09:53:50 +00:00
Toshi MARUYAMA a223a0dffd scm: mercurial: functional test for accept both of revision number and changeset id (#3724).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4664 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 02:13:54 +00:00
Toshi MARUYAMA ef28bf6d88 scm: mercurial: annotate accepts both of revision number and changeset id (#3724).
Change annotate revision label to Mercurial style '4:def6d2f1254a'
and use identifier.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4663 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-09 01:30:18 +00:00
Toshi MARUYAMA 5207211b6d scm: mercurial: fix diff and test for accept both of revision number and changeset id (#3724).
Diff of changeset can be wrong if the previous changeset isn't the parent.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4662 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-08 13:51:43 +00:00
Toshi MARUYAMA 0743ba89d4 scm: mercurial: cat test for accept both of revision number and changeset id (#3724).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4661 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-08 12:51:36 +00:00
Jean-Philippe Lang 0617625f48 Italian translation update by Emidio Stani (#7227).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4657 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-08 10:03:34 +00:00
Jean-Philippe Lang d0a076cbfd Bulgarian translation update by Ivan Cenov (#7203).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4656 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-08 10:01:09 +00:00
Toshi MARUYAMA 7484096cdc scm: mercurial: fix assert_equal parameter order at app unit test_find_changeset_by_name().
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4655 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-08 08:45:40 +00:00
Toshi MARUYAMA e2df831b53 scm: mercurial: accept both of revision and nodeid as changeset id (#3724).
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4654 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-08 06:24:27 +00:00
Toshi MARUYAMA 3ad213c29a Fix associated revisions label on issue page.
r4613 shows git long hash value.

Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4652 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-08 00:19:51 +00:00
Jean-Philippe Lang e7a9c386ef Removed hard-coded style on wiki history view.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4651 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-06 21:24:32 +00:00
Jean-Philippe Lang 306a47023c Additional unit tests for project tree.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4650 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-06 21:17:08 +00:00
Jean-Philippe Lang 88d65c5149 Do not show trackers and issue custom fields on project form when issue tracking is disabled (#7225).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4648 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-06 21:02:19 +00:00
Jean-Philippe Lang 9222cf91ea Changes ProjectsController#modules param name and add tests.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4647 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-06 20:57:17 +00:00
Jean-Philippe Lang 072c4ad14c Verify HTTP method on ProjectsController#create.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4646 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-06 20:46:22 +00:00
Jean-Philippe Lang 9fb770ba50 Moves enabled_module_names param to project attribute so that it can be set through the Project API.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4645 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-06 20:36:31 +00:00
Jean-Philippe Lang 7620142b70 Adds assertion to prevent error in test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4644 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-06 19:50:41 +00:00
Jean-Philippe Lang e6118347d3 Adds a rake task test:scm:update to update test repositories if needed.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4643 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-06 18:52:37 +00:00
Toshi MARUYAMA 1bf33bb619 scm: mercurial: add unit test for copied file (#7064).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4636 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-05 15:03:35 +00:00
Toshi MARUYAMA f4c5fe43cb scm: mercurial: add some tests at unit and functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4635 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-05 15:03:16 +00:00
Toshi MARUYAMA 9ee02d04f3 scm: mercurial: update test repository for following issues and fix tests.
* copied file (#7064)
* branch, tag (#1981)

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4634 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-05 15:02:47 +00:00
Toshi MARUYAMA ad18cfda32 scm: mercurial: escape any filenames by urlescape (#2664, #7064).
In Mercurial, filename is not UTF-8 but byte-string.
So it should be escaped to UTF-8-safe string before parsing as XML document.

NOTE: Mercurial's {|obfuscate} filter cannot be used here, because it treats
filename as encoded by HGENCODING.

Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4633 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-05 15:02:24 +00:00
Toshi MARUYAMA 6ad68ae027 scm: mercurial: cleanup indent and trailing white-space of unit lib test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4632 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-05 15:02:03 +00:00
Toshi MARUYAMA 0f8680adfd scm: mercurial: fix comment and change // to '' some strings of functional test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4631 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-05 15:01:39 +00:00
Toshi MARUYAMA e86b8febdc scm: mercurial: refactor mercurial unit test.
* lib unit test switches if repository exists.
* move cat test from app to lib.
* no need to run "hg update" in unit test (#3421).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4629 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-04 16:34:40 +00:00
Toshi MARUYAMA 5e1c42cbe3 repository: mercurial: fix functional annotate test.
Mercurial test repository author is 'jsmith'.
If author is 'foo', functional annotate test passes.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4625 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-03 10:45:44 +00:00
Toshi MARUYAMA 7958facadc repository: git: change io.gets to io.readlines (#5404, #5096).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4624 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-03 10:45:00 +00:00
Toshi MARUYAMA 8487e0a5b8 Fix subversion and git activities test reffering r4621.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4623 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-03 10:44:23 +00:00
Jean-Philippe Lang 29fddddaf1 Fixed failing subversion test.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4621 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-02 14:36:12 +00:00
Jean-Philippe Lang e0d6f8db1d Set version to 1.1.0.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4619 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-02 12:16:40 +00:00
Jean-Philippe Lang a4c5787b53 Updated footer to 2011.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4618 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-02 12:16:06 +00:00
Jean-Philippe Lang 2d9b9362a9 Fixed: should redirect to the new project when copying a project.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4616 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-02 11:42:37 +00:00
Jean-Philippe Lang ce8113dea2 Additional roles of a user who belongs to a group are not always copied when copying the project (#7213).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4615 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-02 11:38:35 +00:00
Toshi MARUYAMA 2e1bcb2abf Changing revision label and identifier at SCM adapter level (#3724, #6092)
Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4613 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-02 09:45:05 +00:00
Toshi MARUYAMA 2ae2d3ef83 Fixed: repository: mercurial: sort changesets by revision (#3449, #3567).
In DVCS, changesets are not in date order.
Because Mercurial backend inserts changesets from eariest, 'ORDER BY id'
means 'order by revision number'.

Contributed by Yuya Nishihara.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4611 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-02 06:05:54 +00:00
Jean-Baptiste Barth d29052f682 Added missing remove_index in AddUniqueIndexOnMembers down migration. #7212
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4610 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-01 23:08:49 +00:00
Toshi MARUYAMA 35c35a193c repository: switch darcs cat test if cat supports.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4608 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-01 22:01:28 +00:00
Toshi MARUYAMA 1294fe2c96 Adding .hgignore based on the .gitignore.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4606 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-01 21:07:43 +00:00
Jean-Philippe Lang ad727d3781 Fixes utf8 conversions with ruby1.9.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4605 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-01 19:12:35 +00:00
Jean-Philippe Lang 488285e123 Strip non utf8 content when displaying diff (ruby1.9 compatibility).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4604 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-01 13:40:36 +00:00
Jean-Philippe Lang 1c7079db3f Read attachment fixtures in binary mode.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4603 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-01 12:24:18 +00:00
Jean-Philippe Lang 2c830770cb ruby1.9 compatibility
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4602 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-01 11:45:12 +00:00
Jean-Philippe Lang 9748567452 ruby1.9 compatibility
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4601 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-01-01 11:13:33 +00:00
Jean-Philippe Lang d3a926df64 Fixes wrong assertion.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4600 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-12-31 15:45:35 +00:00
Jean-Philippe Lang 44ffc5a336 Remove the limitation on characters that can be used in custom_field, issue_status, role, tracker, user names (#5152).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4599 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-12-31 15:30:50 +00:00
Jean-Philippe Lang 92d34234b0 Safer assertion.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4598 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-12-31 15:24:42 +00:00
Jean-Philippe Lang 3eebd827d7 ruby1.9 compatibility
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4597 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-12-31 11:16:03 +00:00
Jean-Philippe Lang 6659c630b2 Fixes wrong Polish translation of "blocks" and "duplicates" (#6895).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4595 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-12-30 15:49:08 +00:00
Jean-Philippe Lang 4d557dd512 Japanese Translation updated (#7133).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4594 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-12-30 15:44:02 +00:00
Jean-Philippe Lang 74de89d1dd Traditional Chinese language updated (#7123).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4593 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-12-30 15:43:02 +00:00
Jean-Philippe Lang 5e725070e0 German translation updated (#7161).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4592 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-12-30 15:38:41 +00:00
670 changed files with 59628 additions and 16692 deletions
+5
View File
@@ -1,4 +1,7 @@
/.project
/.loadpath
/config/additional_environment.rb /config/additional_environment.rb
/config/configuration.yml
/config/database.yml /config/database.yml
/config/email.yml /config/email.yml
/config/initializers/session_store.rb /config/initializers/session_store.rb
@@ -7,6 +10,8 @@
/db/*.sqlite3 /db/*.sqlite3
/db/schema.rb /db/schema.rb
/files/* /files/*
/lib/redmine/scm/adapters/mercurial/redminehelper.pyc
/lib/redmine/scm/adapters/mercurial/redminehelper.pyo
/log/*.log* /log/*.log*
/log/mongrel_debug /log/mongrel_debug
/public/dispatch.* /public/dispatch.*
+29
View File
@@ -0,0 +1,29 @@
syntax: glob
.project
.loadpath
config/additional_environment.rb
config/configuration.yml
config/database.yml
config/email.yml
config/initializers/session_store.rb
coverage
db/*.db
db/*.sqlite3
db/schema.rb
files/*
lib/redmine/scm/adapters/mercurial/redminehelper.pyc
lib/redmine/scm/adapters/mercurial/redminehelper.pyo
log/*.log*
log/mongrel_debug
public/dispatch.*
public/plugin_assets
tmp/*
tmp/cache/*
tmp/sessions/*
tmp/sockets/*
tmp/test/*
vendor/rails
*.rbc
.svn/
.git/
+14 -2
View File
@@ -203,12 +203,24 @@ class AccountController < ApplicationController
self.logged_user = user self.logged_user = user
# generate a key and set cookie if autologin # generate a key and set cookie if autologin
if params[:autologin] && Setting.autologin? if params[:autologin] && Setting.autologin?
token = Token.create(:user => user, :action => 'autologin') set_autologin_cookie(user)
cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
end end
call_hook(:controller_account_success_authentication_after, {:user => user }) call_hook(:controller_account_success_authentication_after, {:user => user })
redirect_back_or_default :controller => 'my', :action => 'page' redirect_back_or_default :controller => 'my', :action => 'page'
end end
def set_autologin_cookie(user)
token = Token.create(:user => user, :action => 'autologin')
cookie_name = Redmine::Configuration['autologin_cookie_name'] || '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[cookie_name] = cookie_options
end
# Onthefly creation failed, display the registration form to fill/fix attributes # Onthefly creation failed, display the registration form to fill/fix attributes
def onthefly_creation_failed(user, auth_source_options = { }) def onthefly_creation_failed(user, auth_source_options = { })
+24 -8
View File
@@ -1,11 +1,28 @@
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public 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 class ActivitiesController < ApplicationController
menu_item :activity menu_item :activity
before_filter :find_optional_project before_filter :find_optional_project
accept_key_auth :index accept_rss_auth :index
def index def index
@days = Setting.activity_days_default.to_i @days = Setting.activity_days_default.to_i
if params[:from] if params[:from]
begin; @date_to = params[:from].to_date + 1; rescue; end begin; @date_to = params[:from].to_date + 1; rescue; end
end end
@@ -14,18 +31,18 @@ class ActivitiesController < ApplicationController
@date_from = @date_to - @days @date_from = @date_to - @days
@with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1') @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])) @author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id]))
@activity = Redmine::Activity::Fetcher.new(User.current, :project => @project, @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project,
:with_subprojects => @with_subprojects, :with_subprojects => @with_subprojects,
:author => @author) :author => @author)
@activity.scope_select {|t| !params["show_#{t}"].nil?} @activity.scope_select {|t| !params["show_#{t}"].nil?}
@activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty? @activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty?
events = @activity.events(@date_from, @date_to) events = @activity.events(@date_from, @date_to)
if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language]) if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language])
respond_to do |format| respond_to do |format|
format.html { format.html {
@events_by_day = events.group_by(&:event_date) @events_by_day = events.group_by(&:event_date)
render :layout => false if request.xhr? render :layout => false if request.xhr?
} }
@@ -40,7 +57,7 @@ class ActivitiesController < ApplicationController
} }
end end
end end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
@@ -55,5 +72,4 @@ class ActivitiesController < ApplicationController
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
end end
+10 -12
View File
@@ -17,9 +17,7 @@
class AdminController < ApplicationController class AdminController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin before_filter :require_admin
helper :sort helper :sort
include SortHelper include SortHelper
@@ -30,22 +28,20 @@ class AdminController < ApplicationController
def projects def projects
@status = params[:status] ? params[:status].to_i : 1 @status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status]) c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
unless params[:name].blank? unless params[:name].blank?
name = "%#{params[:name].strip.downcase}%" name = "%#{params[:name].strip.downcase}%"
c << ["LOWER(identifier) LIKE ? OR LOWER(name) LIKE ?", name, name] c << ["LOWER(identifier) LIKE ? OR LOWER(name) LIKE ?", name, name]
end end
@projects = Project.find :all, :order => 'lft', @projects = Project.find :all, :order => 'lft',
:conditions => c.conditions :conditions => c.conditions
render :action => "projects", :layout => false if request.xhr? render :action => "projects", :layout => false if request.xhr?
end end
def plugins def plugins
@plugins = Redmine::Plugin.all @plugins = Redmine::Plugin.all
end end
# Loads the default configuration # Loads the default configuration
# (roles, trackers, statuses, workflow, enumerations) # (roles, trackers, statuses, workflow, enumerations)
def default_configuration def default_configuration
@@ -59,7 +55,7 @@ class AdminController < ApplicationController
end end
redirect_to :action => 'index' redirect_to :action => 'index'
end end
def test_email def test_email
raise_delivery_errors = ActionMailer::Base.raise_delivery_errors raise_delivery_errors = ActionMailer::Base.raise_delivery_errors
# Force ActionMailer to raise delivery errors so we can catch it # Force ActionMailer to raise delivery errors so we can catch it
@@ -73,14 +69,16 @@ class AdminController < ApplicationController
ActionMailer::Base.raise_delivery_errors = raise_delivery_errors ActionMailer::Base.raise_delivery_errors = raise_delivery_errors
redirect_to :controller => 'settings', :action => 'edit', :tab => 'notifications' redirect_to :controller => 'settings', :action => 'edit', :tab => 'notifications'
end end
def info def info
@db_adapter_name = ActiveRecord::Base.connection.adapter_name @db_adapter_name = ActiveRecord::Base.connection.adapter_name
@checklist = [ @checklist = [
[:text_default_administrator_account_changed, User.find(:first, :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?], [:text_default_administrator_account_changed,
User.find(:first,
:conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?],
[:text_file_repository_writable, File.writable?(Attachment.storage_path)], [:text_file_repository_writable, File.writable?(Attachment.storage_path)],
[:text_plugin_assets_writable, File.writable?(Engines.public_directory)], [:text_plugin_assets_writable, File.writable?(Engines.public_directory)],
[:text_rmagick_available, Object.const_defined?(:Magick)] [:text_rmagick_available, Object.const_defined?(:Magick)]
] ]
end end
end end
+76 -41
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -18,34 +18,37 @@
require 'uri' require 'uri'
require 'cgi' require 'cgi'
class Unauthorized < Exception; end
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
include Redmine::I18n include Redmine::I18n
layout 'base' layout 'base'
exempt_from_layout 'builder', 'rsb' exempt_from_layout 'builder', 'rsb'
# Remove broken cookie after upgrade from 0.8.x (#4292) # Remove broken cookie after upgrade from 0.8.x (#4292)
# See https://rails.lighthouseapp.com/projects/8994/tickets/3360 # See https://rails.lighthouseapp.com/projects/8994/tickets/3360
# TODO: remove it when Rails is fixed # TODO: remove it when Rails is fixed
before_filter :delete_broken_cookies before_filter :delete_broken_cookies
def delete_broken_cookies def delete_broken_cookies
if cookies['_redmine_session'] && cookies['_redmine_session'] !~ /--/ if cookies['_redmine_session'] && cookies['_redmine_session'] !~ /--/
cookies.delete '_redmine_session' cookies.delete '_redmine_session'
redirect_to home_path redirect_to home_path
return false return false
end end
end end
before_filter :user_setup, :check_if_login_required, :set_localization before_filter :user_setup, :check_if_login_required, :set_localization
filter_parameter_logging :password filter_parameter_logging :password
protect_from_forgery protect_from_forgery
rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
rescue_from ::Unauthorized, :with => :deny_access
include Redmine::Search::Controller include Redmine::Search::Controller
include Redmine::MenuManager::MenuController include Redmine::MenuManager::MenuController
helper Redmine::MenuManager::MenuHelper helper Redmine::MenuManager::MenuHelper
Redmine::Scm::Base.all.each do |scm| Redmine::Scm::Base.all.each do |scm|
require_dependency "repository/#{scm.underscore}" require_dependency "repository/#{scm.underscore}"
end end
@@ -56,7 +59,7 @@ class ApplicationController < ActionController::Base
# Find the current user # Find the current user
User.current = find_current_user User.current = find_current_user
end end
# Returns the current user or nil if no user is logged in # Returns the current user or nil if no user is logged in
# and starts a session if needed # and starts a session if needed
def find_current_user def find_current_user
@@ -68,11 +71,11 @@ class ApplicationController < ActionController::Base
user = User.try_to_autologin(cookies[:autologin]) user = User.try_to_autologin(cookies[:autologin])
session[:user_id] = user.id if user session[:user_id] = user.id if user
user user
elsif params[:format] == 'atom' && params[:key] && accept_key_auth_actions.include?(params[:action]) elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
# RSS key authentication does not start a session # RSS key authentication does not start a session
User.find_by_rss_key(params[:key]) User.find_by_rss_key(params[:key])
elsif Setting.rest_api_enabled? && api_request? elsif Setting.rest_api_enabled? && accept_api_auth?
if (key = api_key_from_request) && accept_key_auth_actions.include?(params[:action]) if (key = api_key_from_request)
# Use API key # Use API key
User.find_by_api_key(key) User.find_by_api_key(key)
else else
@@ -94,14 +97,14 @@ class ApplicationController < ActionController::Base
User.current = User.anonymous User.current = User.anonymous
end end
end end
# check if login is globally required to access the application # check if login is globally required to access the application
def check_if_login_required def check_if_login_required
# no check needed if user is already logged in # no check needed if user is already logged in
return true if User.current.logged? return true if User.current.logged?
require_login if Setting.login_required? require_login if Setting.login_required?
end end
def set_localization def set_localization
lang = nil lang = nil
if User.current.logged? if User.current.logged?
@@ -117,7 +120,7 @@ class ApplicationController < ActionController::Base
lang ||= Setting.default_language lang ||= Setting.default_language
set_language_if_valid(lang) set_language_if_valid(lang)
end end
def require_login def require_login
if !User.current.logged? if !User.current.logged?
# Extract only the basic url parameters on non-GET requests # Extract only the basic url parameters on non-GET requests
@@ -146,7 +149,7 @@ class ApplicationController < ActionController::Base
end end
true true
end end
def deny_access def deny_access
User.current.logged? ? render_403 : require_login User.current.logged? ? render_403 : require_login
end end
@@ -197,7 +200,7 @@ class ApplicationController < ActionController::Base
# Finds and sets @project based on @object.project # Finds and sets @project based on @object.project
def find_project_from_association def find_project_from_association
render_404 unless @object.present? render_404 unless @object.present?
@project = @object.project @project = @object.project
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
@@ -221,12 +224,16 @@ class ApplicationController < ActionController::Base
def find_issues def find_issues
@issues = Issue.find_all_by_id(params[:id] || params[:ids]) @issues = Issue.find_all_by_id(params[:id] || params[:ids])
raise ActiveRecord::RecordNotFound if @issues.empty? raise ActiveRecord::RecordNotFound if @issues.empty?
if @issues.detect {|issue| !issue.visible?}
deny_access
return
end
@projects = @issues.collect(&:project).compact.uniq @projects = @issues.collect(&:project).compact.uniq
@project = @projects.first if @projects.size == 1 @project = @projects.first if @projects.size == 1
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
# Check if project is unique before bulk operations # Check if project is unique before bulk operations
def check_project_uniqueness def check_project_uniqueness
unless @project unless @project
@@ -235,7 +242,7 @@ class ApplicationController < ActionController::Base
return false return false
end end
end end
# make sure that the user is a member of the project (or admin) if project is private # 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 # used as a before_filter for actions that do not require any particular permission on the project
def check_project_privacy def check_project_privacy
@@ -271,27 +278,28 @@ class ApplicationController < ActionController::Base
end end
end end
redirect_to default redirect_to default
false
end end
def render_403(options={}) def render_403(options={})
@project = nil @project = nil
render_error({:message => :notice_not_authorized, :status => 403}.merge(options)) render_error({:message => :notice_not_authorized, :status => 403}.merge(options))
return false return false
end end
def render_404(options={}) def render_404(options={})
render_error({:message => :notice_file_not_found, :status => 404}.merge(options)) render_error({:message => :notice_file_not_found, :status => 404}.merge(options))
return false return false
end end
# Renders an error response # Renders an error response
def render_error(arg) def render_error(arg)
arg = {:message => arg} unless arg.is_a?(Hash) arg = {:message => arg} unless arg.is_a?(Hash)
@message = arg[:message] @message = arg[:message]
@message = l(@message) if @message.is_a?(Symbol) @message = l(@message) if @message.is_a?(Symbol)
@status = arg[:status] || 500 @status = arg[:status] || 500
respond_to do |format| respond_to do |format|
format.html { format.html {
render :template => 'common/error', :layout => use_layout, :status => @status render :template => 'common/error', :layout => use_layout, :status => @status
@@ -309,15 +317,15 @@ class ApplicationController < ActionController::Base
def use_layout def use_layout
request.xhr? ? false : 'base' request.xhr? ? false : 'base'
end end
def invalid_authenticity_token def invalid_authenticity_token
if api_request? if api_request?
logger.error "Form authenticity token is missing or is invalid. API calls must include a proper Content-type header (text/xml or text/json)." logger.error "Form authenticity token is missing or is invalid. API calls must include a proper Content-type header (text/xml or text/json)."
end end
render_error "Invalid form authenticity token." render_error "Invalid form authenticity token."
end end
def render_feed(items, options={}) def render_feed(items, options={})
@items = items || [] @items = items || []
@items.sort! {|x,y| y.event_datetime <=> x.event_datetime } @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
@items = @items.slice(0, Setting.feeds_limit.to_i) @items = @items.slice(0, Setting.feeds_limit.to_i)
@@ -325,15 +333,42 @@ class ApplicationController < ActionController::Base
render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml' render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
end end
# TODO: remove in Redmine 1.4
def self.accept_key_auth(*actions) def self.accept_key_auth(*actions)
actions = actions.flatten.map(&:to_s) ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead."
write_inheritable_attribute('accept_key_auth_actions', actions) accept_rss_auth(*actions)
end end
# TODO: remove in Redmine 1.4
def accept_key_auth_actions def accept_key_auth_actions
self.class.read_inheritable_attribute('accept_key_auth_actions') || [] ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth_actions is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead."
self.class.accept_rss_auth
end end
def self.accept_rss_auth(*actions)
if actions.any?
write_inheritable_attribute('accept_rss_auth_actions', actions)
else
read_inheritable_attribute('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?
write_inheritable_attribute('accept_api_auth_actions', actions)
else
read_inheritable_attribute('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 # Returns the number of objects that should be displayed
# on the paginated list # on the paginated list
def per_page_option def per_page_option
@@ -369,10 +404,10 @@ class ApplicationController < ActionController::Base
offset = 0 if offset < 0 offset = 0 if offset < 0
end end
offset ||= 0 offset ||= 0
[offset, limit] [offset, limit]
end end
# qvalues http header parser # qvalues http header parser
# code taken from webrick # code taken from webrick
def parse_qvalues(value) def parse_qvalues(value)
@@ -393,16 +428,16 @@ class ApplicationController < ActionController::Base
rescue rescue
nil nil
end end
# Returns a string that can be used as filename value in Content-Disposition header # Returns a string that can be used as filename value in Content-Disposition header
def filename_for_content_disposition(name) 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} ? ERB::Util.url_encode(name) : name
end end
def api_request? def api_request?
%w(xml json).include? params[:format] %w(xml json).include? params[:format]
end end
# Returns the API key present in the request # Returns the API key present in the request
def api_key_from_request def api_key_from_request
if params[:key].present? if params[:key].present?
@@ -459,7 +494,7 @@ class ApplicationController < ActionController::Base
) )
render options render options
end end
# Overrides #default_template so that the api template # Overrides #default_template so that the api template
# is used automatically if it exists # is used automatically if it exists
def default_template(action_name = self.action_name) def default_template(action_name = self.action_name)
@@ -473,7 +508,7 @@ class ApplicationController < ActionController::Base
end end
super super
end end
# Overrides #pick_layout so that #render with no arguments # Overrides #pick_layout so that #render with no arguments
# doesn't use the layout for api requests # doesn't use the layout for api requests
def pick_layout(*args) def pick_layout(*args)
+15 -15
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2008 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -19,9 +19,9 @@ class AttachmentsController < ApplicationController
before_filter :find_project before_filter :find_project
before_filter :file_readable, :read_authorize, :except => :destroy before_filter :file_readable, :read_authorize, :except => :destroy
before_filter :delete_authorize, :only => :destroy before_filter :delete_authorize, :only => :destroy
verify :method => :post, :only => :destroy verify :method => :post, :only => :destroy
def show def show
if @attachment.is_diff? if @attachment.is_diff?
@diff = File.new(@attachment.diskfile, "rb").read @diff = File.new(@attachment.diskfile, "rb").read
@@ -33,19 +33,19 @@ class AttachmentsController < ApplicationController
download download
end end
end end
def download def download
if @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project) if @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project)
@attachment.increment_download @attachment.increment_download
end end
# images are sent inline # images are sent inline
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename), send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
:type => detect_content_type(@attachment), :type => detect_content_type(@attachment),
:disposition => (@attachment.image? ? 'inline' : 'attachment') :disposition => (@attachment.image? ? 'inline' : 'attachment')
end end
def destroy def destroy
# Make sure association callbacks are called # Make sure association callbacks are called
@attachment.container.attachments.delete(@attachment) @attachment.container.attachments.delete(@attachment)
@@ -53,7 +53,7 @@ class AttachmentsController < ApplicationController
rescue ::ActionController::RedirectBackError rescue ::ActionController::RedirectBackError
redirect_to :controller => 'projects', :action => 'show', :id => @project redirect_to :controller => 'projects', :action => 'show', :id => @project
end end
private private
def find_project def find_project
@attachment = Attachment.find(params[:id]) @attachment = Attachment.find(params[:id])
@@ -63,20 +63,20 @@ private
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
# Checks that the file exists and is readable # Checks that the file exists and is readable
def file_readable def file_readable
@attachment.readable? ? true : render_404 @attachment.readable? ? true : render_404
end end
def read_authorize def read_authorize
@attachment.visible? ? true : deny_access @attachment.visible? ? true : deny_access
end end
def delete_authorize def delete_authorize
@attachment.deletable? ? true : deny_access @attachment.deletable? ? true : deny_access
end end
def detect_content_type(attachment) def detect_content_type(attachment)
content_type = attachment.content_type content_type = attachment.content_type
if content_type.blank? if content_type.blank?
+3 -3
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
class BoardsController < ApplicationController class BoardsController < ApplicationController
default_search_scope :messages default_search_scope :messages
before_filter :find_project, :find_board_if_available, :authorize before_filter :find_project, :find_board_if_available, :authorize
accept_key_auth :index, :show accept_rss_auth :index, :show
helper :messages helper :messages
include MessagesHelper include MessagesHelper
+17 -5
View File
@@ -1,3 +1,20 @@
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public 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 class CalendarsController < ApplicationController
menu_item :calendar menu_item :calendar
before_filter :find_optional_project before_filter :find_optional_project
@@ -36,9 +53,4 @@ class CalendarsController < ApplicationController
render :action => 'show', :layout => false if request.xhr? render :action => 'show', :layout => false if request.xhr?
end end
def update
show
end
end end
+14 -1
View File
@@ -1,5 +1,6 @@
class ContextMenusController < ApplicationController class ContextMenusController < ApplicationController
helper :watchers helper :watchers
helper :issues
def issues def issues
@issues = Issue.visible.all(:conditions => {:id => params[:ids]}, :include => :project) @issues = Issue.visible.all(:conditions => {:id => params[:ids]}, :include => :project)
@@ -40,5 +41,17 @@ class ContextMenusController < ApplicationController
render :layout => false render :layout => false
end end
def time_entries
@time_entries = TimeEntry.all(
:conditions => {:id => params[:ids]}, :include => :project)
@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 end
+4 -2
View File
@@ -38,8 +38,9 @@ class CustomFieldsController < ApplicationController
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field) call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
redirect_to :action => 'index', :tab => @custom_field.class.name redirect_to :action => 'index', :tab => @custom_field.class.name
else
@trackers = Tracker.find(:all, :order => 'position')
end end
@trackers = Tracker.find(:all, :order => 'position')
end end
def edit def edit
@@ -48,8 +49,9 @@ class CustomFieldsController < ApplicationController
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field) call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
redirect_to :action => 'index', :tab => @custom_field.class.name redirect_to :action => 'index', :tab => @custom_field.class.name
else
@trackers = Tracker.find(:all, :order => 'position')
end end
@trackers = Tracker.find(:all, :order => 'position')
end end
def destroy def destroy
@@ -75,10 +75,12 @@ class EnumerationsController < ApplicationController
# No associated objects # No associated objects
@enumeration.destroy @enumeration.destroy
redirect_to :action => 'index' redirect_to :action => 'index'
return
elsif params[:reassign_to_id] elsif params[:reassign_to_id]
if reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id]) if reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id])
@enumeration.destroy(reassign_to) @enumeration.destroy(reassign_to)
redirect_to :action => 'index' redirect_to :action => 'index'
return
end end
end end
@enumerations = @enumeration.class.find(:all) - [@enumeration] @enumerations = @enumeration.class.find(:all) - [@enumeration]
+1 -1
View File
@@ -13,7 +13,7 @@ class FilesController < ApplicationController
'created_on' => "#{Attachment.table_name}.created_on", 'created_on' => "#{Attachment.table_name}.created_on",
'size' => "#{Attachment.table_name}.filesize", 'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads" 'downloads' => "#{Attachment.table_name}.downloads"
@containers = [ Project.find(@project.id, :include => :attachments, :order => sort_clause)] @containers = [ Project.find(@project.id, :include => :attachments, :order => sort_clause)]
@containers += @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse @containers += @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse
render :layout => !request.xhr? render :layout => !request.xhr?
+17 -5
View File
@@ -1,3 +1,20 @@
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public 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 class GanttsController < ApplicationController
menu_item :gantt menu_item :gantt
before_filter :find_optional_project before_filter :find_optional_project
@@ -28,9 +45,4 @@ class GanttsController < ApplicationController
format.pdf { send_data(@gantt.to_pdf, :type => 'application/pdf', :filename => "#{basename}.pdf") } format.pdf { send_data(@gantt.to_pdf, :type => 'application/pdf', :filename => "#{basename}.pdf") }
end end
end end
def update
show
end
end end
+1 -1
View File
@@ -132,7 +132,7 @@ class GroupsController < ApplicationController
def autocomplete_for_user def autocomplete_for_user
@group = Group.find(params[:id]) @group = Group.find(params[:id])
@users = User.active.like(params[:q]).find(:all, :limit => 100) - @group.users @users = User.active.not_in_group(@group).like(params[:q]).all(:limit => 100)
render :layout => false render :layout => false
end end
@@ -65,10 +65,12 @@ class IssueCategoriesController < ApplicationController
# No issue assigned to this category # No issue assigned to this category
@category.destroy @category.destroy
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories' redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
return
elsif params[:todo] elsif params[:todo]
reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id]) if params[:todo] == 'reassign' reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id]) if params[:todo] == 'reassign'
@category.destroy(reassign_to) @category.destroy(reassign_to)
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories' redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
return
end end
@categories = @project.issue_categories - [@category] @categories = @project.issue_categories - [@category]
end end
+2 -2
View File
@@ -2,7 +2,7 @@ class IssueMovesController < ApplicationController
default_search_scope :issues default_search_scope :issues
before_filter :find_issues, :check_project_uniqueness before_filter :find_issues, :check_project_uniqueness
before_filter :authorize before_filter :authorize
def new def new
prepare_for_issue_move prepare_for_issue_move
render :layout => false if request.xhr? render :layout => false if request.xhr?
@@ -48,7 +48,7 @@ class IssueMovesController < ApplicationController
@copy = params[:copy_options] && params[:copy_options][:copy] @copy = params[:copy_options] && params[:copy_options][:copy]
@allowed_projects = Issue.allowed_target_projects_on_move @allowed_projects = Issue.allowed_target_projects_on_move
@target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id] @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
@target_project ||= @project @target_project ||= @project
@trackers = @target_project.trackers @trackers = @target_project.trackers
@available_statuses = Workflow.available_statuses(@project) @available_statuses = Workflow.available_statuses(@project)
@notes = params[:notes] @notes = params[:notes]
@@ -1,4 +1,4 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
@@ -28,6 +28,7 @@ class IssueRelationsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue } format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
format.js do format.js do
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
render :update do |page| render :update do |page|
page.replace_html "relations", :partial => 'issues/relations' page.replace_html "relations", :partial => 'issues/relations'
if @relation.errors.empty? if @relation.errors.empty?
@@ -47,7 +48,10 @@ class IssueRelationsController < ApplicationController
end end
respond_to do |format| respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue } format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
format.js { render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'} } format.js {
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'}
}
end end
end end
+46 -26
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2008 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -18,7 +18,7 @@
class IssuesController < ApplicationController class IssuesController < ApplicationController
menu_item :new_issue, :only => [:new, :create] menu_item :new_issue, :only => [:new, :create]
default_search_scope :issues default_search_scope :issues
before_filter :find_issue, :only => [:show, :edit, :update] before_filter :find_issue, :only => [:show, :edit, :update]
before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy] before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy]
before_filter :check_project_uniqueness, :only => [:move, :perform_move] before_filter :check_project_uniqueness, :only => [:move, :perform_move]
@@ -27,13 +27,14 @@ class IssuesController < ApplicationController
before_filter :find_optional_project, :only => [:index] before_filter :find_optional_project, :only => [:index]
before_filter :check_for_default_issue_status, :only => [:new, :create] before_filter :check_for_default_issue_status, :only => [:new, :create]
before_filter :build_new_issue_from_params, :only => [:new, :create] before_filter :build_new_issue_from_params, :only => [:new, :create]
accept_key_auth :index, :show, :create, :update, :destroy accept_rss_auth :index, :show
accept_api_auth :index, :show, :create, :update, :destroy
rescue_from Query::StatementInvalid, :with => :query_statement_invalid rescue_from Query::StatementInvalid, :with => :query_statement_invalid
helper :journals helper :journals
helper :projects helper :projects
include ProjectsHelper include ProjectsHelper
helper :custom_fields helper :custom_fields
include CustomFieldsHelper include CustomFieldsHelper
helper :issue_relations helper :issue_relations
@@ -44,6 +45,8 @@ class IssuesController < ApplicationController
include AttachmentsHelper include AttachmentsHelper
helper :queries helper :queries
include QueriesHelper include QueriesHelper
helper :repositories
include RepositoriesHelper
helper :sort helper :sort
include SortHelper include SortHelper
include IssuesHelper include IssuesHelper
@@ -58,12 +61,12 @@ class IssuesController < ApplicationController
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
verify :method => :post, :only => :bulk_update, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :post, :only => :bulk_update, :render => {:nothing => true, :status => :method_not_allowed }
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
def index def index
retrieve_query retrieve_query
sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria) sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns) sort_update(@query.sortable_columns)
if @query.valid? if @query.valid?
case params[:format] case params[:format]
when 'csv', 'pdf' when 'csv', 'pdf'
@@ -75,16 +78,16 @@ class IssuesController < ApplicationController
else else
@limit = per_page_option @limit = per_page_option
end end
@issue_count = @query.issue_count @issue_count = @query.issue_count
@issue_pages = Paginator.new self, @issue_count, @limit, params['page'] @issue_pages = Paginator.new self, @issue_count, @limit, params['page']
@offset ||= @issue_pages.current.offset @offset ||= @issue_pages.current.offset
@issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version], @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
:order => sort_clause, :order => sort_clause,
:offset => @offset, :offset => @offset,
:limit => @limit) :limit => @limit)
@issue_count_by_group = @query.issue_count_by_group @issue_count_by_group = @query.issue_count_by_group
respond_to do |format| respond_to do |format|
format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? } format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
format.api format.api
@@ -99,17 +102,22 @@ class IssuesController < ApplicationController
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def show def show
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC") @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
@journals.each_with_index {|j,i| j.indice = i+1} @journals.each_with_index {|j,i| j.indice = i+1}
@journals.reverse! if User.current.wants_comments_in_reverse_order? @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? if User.current.allowed_to?(:view_changesets, @project)
@changesets = @issue.changesets.visible.all
@changesets.reverse! if User.current.wants_comments_in_reverse_order?
end
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
@allowed_statuses = @issue.new_statuses_allowed_to(User.current) @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@edit_allowed = User.current.allowed_to?(:edit_issues, @project) @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@priorities = IssuePriority.all @priorities = IssuePriority.all
@time_entry = TimeEntry.new @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
respond_to do |format| respond_to do |format|
format.html { render :template => 'issues/show.rhtml' } format.html { render :template => 'issues/show.rhtml' }
format.api format.api
@@ -149,7 +157,7 @@ class IssuesController < ApplicationController
end end
end end
end end
def edit def edit
update_issue_from_params update_issue_from_params
@@ -211,7 +219,7 @@ class IssuesController < ApplicationController
set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids) set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project}) redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project})
end end
def destroy def destroy
@hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
if @hours > 0 if @hours > 0
@@ -233,7 +241,13 @@ class IssuesController < ApplicationController
return unless api_request? return unless api_request?
end end
end end
@issues.each(&:destroy) @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| respond_to do |format|
format.html { redirect_back_or_default(:action => 'index', :project_id => @project) } format.html { redirect_back_or_default(:action => 'index', :project_id => @project) }
format.api { head :ok } format.api { head :ok }
@@ -242,19 +256,25 @@ class IssuesController < ApplicationController
private private
def find_issue 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], :include => [:project, :tracker, :status, :author, :priority, :category]) @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
unless @issue.visible?
deny_access
return
end
@project = @issue.project @project = @issue.project
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def find_project def find_project
project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id] project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
@project = Project.find(project_id) @project = Project.find(project_id)
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
# Used by #edit and #update to set some common instance variables # Used by #edit and #update to set some common instance variables
# from the params # from the params
# TODO: Refactor, not everything in here is needed by #edit # TODO: Refactor, not everything in here is needed by #edit
@@ -262,9 +282,9 @@ private
@allowed_statuses = @issue.new_statuses_allowed_to(User.current) @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@priorities = IssuePriority.all @priorities = IssuePriority.all
@edit_allowed = User.current.allowed_to?(:edit_issues, @project) @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@time_entry = TimeEntry.new @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
@time_entry.attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
@notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil) @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil)
@issue.init_journal(User.current, @notes) @issue.init_journal(User.current, @notes)
@issue.safe_attributes = params[:issue] @issue.safe_attributes = params[:issue]
@@ -280,8 +300,9 @@ private
else else
@issue = @project.issues.visible.find(params[:id]) @issue = @project.issues.visible.find(params[:id])
end end
@issue.project = @project @issue.project = @project
@issue.author = User.current
# Tracker must be set before custom field values # Tracker must be set before custom field values
@issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first) @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
if @issue.tracker.nil? if @issue.tracker.nil?
@@ -295,7 +316,6 @@ private
@issue.watcher_user_ids = params[:issue]['watcher_user_ids'] @issue.watcher_user_ids = params[:issue]['watcher_user_ids']
end end
end end
@issue.author = User.current
@priorities = IssuePriority.all @priorities = IssuePriority.all
@allowed_statuses = @issue.new_statuses_allowed_to(User.current, true) @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
end end
+30 -8
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2008 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -16,13 +16,15 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class JournalsController < ApplicationController class JournalsController < ApplicationController
before_filter :find_journal, :only => [:edit] before_filter :find_journal, :only => [:edit, :diff]
before_filter :find_issue, :only => [:new] before_filter :find_issue, :only => [:new]
before_filter :find_optional_project, :only => [:index] before_filter :find_optional_project, :only => [:index]
before_filter :authorize, :only => [:new, :edit] before_filter :authorize, :only => [:new, :edit, :diff]
accept_key_auth :index accept_rss_auth :index
menu_item :issues
helper :issues helper :issues
helper :custom_fields
helper :queries helper :queries
include QueriesHelper include QueriesHelper
helper :sort helper :sort
@@ -43,6 +45,17 @@ class JournalsController < ApplicationController
render_404 render_404
end 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 def new
journal = Journal.find(params[:journal_id]) if params[:journal_id] journal = Journal.find(params[:journal_id]) if params[:journal_id]
if journal if journal
@@ -67,6 +80,7 @@ class JournalsController < ApplicationController
end end
def edit def edit
(render_403; return false) unless @journal.editable_by?(User.current)
if request.post? if request.post?
@journal.update_attributes(:notes => params[:notes]) if params[:notes] @journal.update_attributes(:notes => params[:notes]) if params[:notes]
@journal.destroy if @journal.details.empty? && @journal.notes.blank? @journal.destroy if @journal.details.empty? && @journal.notes.blank?
@@ -75,13 +89,21 @@ class JournalsController < ApplicationController
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @journal.journalized_id } format.html { redirect_to :controller => 'issues', :action => 'show', :id => @journal.journalized_id }
format.js { render :action => 'update' } format.js { render :action => 'update' }
end end
else
respond_to do |format|
format.html {
# TODO: implement non-JS journal update
render :nothing => true
}
format.js
end
end end
end end
private private
def find_journal def find_journal
@journal = Journal.find(params[:id]) @journal = Journal.find(params[:id])
(render_403; return false) unless @journal.editable_by?(User.current)
@project = @journal.journalized.project @project = @journal.journalized.project
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
+8 -8
View File
@@ -1,27 +1,27 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2008 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MailHandlerController < ActionController::Base class MailHandlerController < ActionController::Base
before_filter :check_credential before_filter :check_credential
verify :method => :post, verify :method => :post,
:only => :index, :only => :index,
:render => { :nothing => true, :status => 405 } :render => { :nothing => true, :status => 405 }
# Submits an incoming email to MailHandler # Submits an incoming email to MailHandler
def index def index
options = params.dup options = params.dup
@@ -32,9 +32,9 @@ class MailHandlerController < ActionController::Base
render :nothing => true, :status => :unprocessable_entity render :nothing => true, :status => :unprocessable_entity
end end
end end
private private
def check_credential def check_credential
User.current = nil User.current = nil
unless Setting.mail_handler_api_enabled? && params[:key].to_s == Setting.mail_handler_api_key unless Setting.mail_handler_api_enabled? && params[:key].to_s == Setting.mail_handler_api_key
+6 -3
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -23,7 +23,10 @@ class NewsController < ApplicationController
before_filter :find_project, :only => [:new, :create] before_filter :find_project, :only => [:new, :create]
before_filter :authorize, :except => [:index] before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => :index before_filter :find_optional_project, :only => :index
accept_key_auth :index accept_rss_auth :index
accept_api_auth :index
helper :watchers
def index def index
case params[:format] case params[:format]
+17
View File
@@ -1,3 +1,20 @@
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public 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 class PreviewsController < ApplicationController
before_filter :find_project before_filter :find_project
+15 -16
View File
@@ -1,5 +1,5 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2009 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -24,7 +24,8 @@ class ProjectsController < ApplicationController
before_filter :authorize, :except => [ :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy] before_filter :authorize, :except => [ :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy]
before_filter :authorize_global, :only => [:new, :create] before_filter :authorize_global, :only => [:new, :create]
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ] before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ]
accept_key_auth :index, :show, :create, :update, :destroy accept_rss_auth :index
accept_api_auth :index, :show, :create, :update, :destroy
after_filter :only => [:create, :edit, :update, :archive, :unarchive, :destroy] do |controller| after_filter :only => [:create, :edit, :update, :archive, :unarchive, :destroy] do |controller|
if controller.request.post? if controller.request.post?
@@ -32,9 +33,6 @@ class ProjectsController < ApplicationController
end end
end end
# TODO: convert to PUT only
verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
helper :sort helper :sort
include SortHelper include SortHelper
helper :custom_fields helper :custom_fields
@@ -71,13 +69,13 @@ class ProjectsController < ApplicationController
@project = Project.new(params[:project]) @project = Project.new(params[:project])
end end
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create def create
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position") @issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@trackers = Tracker.all @trackers = Tracker.all
@project = Project.new @project = Project.new
@project.safe_attributes = params[:project] @project.safe_attributes = params[:project]
@project.enabled_module_names = params[:enabled_modules] if params[:enabled_modules]
if validate_parent_id && @project.save if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id') @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin # Add current user as a project member if he is not admin
@@ -120,17 +118,16 @@ class ProjectsController < ApplicationController
Mailer.with_deliveries(params[:notifications] == '1') do Mailer.with_deliveries(params[:notifications] == '1') do
@project = Project.new @project = Project.new
@project.safe_attributes = params[:project] @project.safe_attributes = params[:project]
@project.enabled_module_names = params[:enabled_modules]
if validate_parent_id && @project.copy(@source_project, :only => params[:only]) 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') @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'projects', :action => 'settings' redirect_to :controller => 'projects', :action => 'settings', :id => @project
elsif !@project.new_record? elsif !@project.new_record?
# Project was created # Project was created
# But some objects were not copied due to validation failures # But some objects were not copied due to validation failures
# (eg. issues from disabled trackers) # (eg. issues from disabled trackers)
# TODO: inform about that # TODO: inform about that
redirect_to :controller => 'projects', :action => 'settings' redirect_to :controller => 'projects', :action => 'settings', :id => @project
end end
end end
end end
@@ -146,7 +143,7 @@ class ProjectsController < ApplicationController
end end
@users_by_role = @project.users_by_role @users_by_role = @project.users_by_role
@subprojects = @project.children.visible @subprojects = @project.children.visible.all
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC") @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
@trackers = @project.rolled_up_trackers @trackers = @project.rolled_up_trackers
@@ -159,11 +156,10 @@ class ProjectsController < ApplicationController
:include => [:project, :status, :tracker], :include => [:project, :status, :tracker],
:conditions => cond) :conditions => cond)
TimeEntry.visible_by(User.current) do if User.current.allowed_to?(:view_time_entries, @project)
@total_hours = TimeEntry.sum(:hours, @total_hours = TimeEntry.visible.sum(:hours, :include => :project, :conditions => cond).to_f
:include => :project,
:conditions => cond).to_f
end end
@key = User.current.rss_key @key = User.current.rss_key
respond_to do |format| respond_to do |format|
@@ -184,6 +180,8 @@ class ProjectsController < ApplicationController
def edit def edit
end end
# TODO: convert to PUT only
verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
def update def update
@project.safe_attributes = params[:project] @project.safe_attributes = params[:project]
if validate_parent_id && @project.save if validate_parent_id && @project.save
@@ -205,9 +203,10 @@ class ProjectsController < ApplicationController
end end
end end
end end
verify :method => :post, :only => :modules, :render => {:nothing => true, :status => :method_not_allowed }
def modules def modules
@project.enabled_module_names = params[:enabled_modules] @project.enabled_module_names = params[:enabled_module_names]
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'settings', :id => @project, :tab => 'modules' redirect_to :action => 'settings', :id => @project, :tab => 'modules'
end end
+6 -3
View File
@@ -25,10 +25,11 @@ class QueriesController < ApplicationController
@query.project = params[:query_is_for_all] ? nil : @project @query.project = params[:query_is_for_all] ? nil : @project
@query.user = User.current @query.user = User.current
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin? @query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
@query.column_names = nil if params[:default_columns]
@query.add_filters(params[:fields], params[:operators], params[:values]) if params[:fields] @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
@query.group_by ||= params[:group_by] @query.group_by ||= params[:group_by]
@query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns]
if request.post? && params[:confirm] && @query.save if request.post? && params[:confirm] && @query.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
@@ -41,10 +42,12 @@ class QueriesController < ApplicationController
def edit def edit
if request.post? if request.post?
@query.filters = {} @query.filters = {}
@query.add_filters(params[:fields], params[:operators], params[:values]) if params[:fields] @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
@query.attributes = params[:query] @query.attributes = params[:query]
@query.project = nil if params[:query_is_for_all] @query.project = nil if params[:query_is_for_all]
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin? @query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
@query.group_by ||= params[:group_by]
@query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns] @query.column_names = nil if params[:default_columns]
if @query.save if @query.save
+102 -59
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2009 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -26,33 +26,45 @@ class RepositoriesController < ApplicationController
menu_item :repository menu_item :repository
menu_item :settings, :only => :edit menu_item :settings, :only => :edit
default_search_scope :changesets default_search_scope :changesets
before_filter :find_repository, :except => :edit before_filter :find_repository, :except => :edit
before_filter :find_project, :only => :edit before_filter :find_project, :only => :edit
before_filter :authorize before_filter :authorize
accept_key_auth :revisions accept_rss_auth :revisions
rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed
def edit def edit
@repository = @project.repository @repository = @project.repository
if !@repository if !@repository && !params[:repository_scm].blank?
@repository = Repository.factory(params[:repository_scm]) @repository = Repository.factory(params[:repository_scm])
@repository.project = @project if @repository @repository.project = @project if @repository
end end
if request.post? && @repository if request.post? && @repository
@repository.attributes = params[:repository] p1 = params[:repository]
p = {}
p_extra = {}
p1.each do |k, v|
if k =~ /^extra_/
p_extra[k] = v
else
p[k] = v
end
end
@repository.attributes = p
@repository.merge_extra_info(p_extra)
@repository.save @repository.save
end end
render(:update) do |page| render(:update) do |page|
page.replace_html "tab-content-repository", :partial => 'projects/settings/repository' page.replace_html "tab-content-repository",
:partial => 'projects/settings/repository'
if @repository && !@project.repository if @repository && !@project.repository
@project.reload #needed to reload association @project.reload # needed to reload association
page.replace_html "main-menu", render_main_menu(@project) page.replace_html "main-menu", render_main_menu(@project)
end end
end end
end end
def committers def committers
@committers = @repository.committers @committers = @repository.committers
@users = @project.users @users = @project.users
@@ -67,16 +79,20 @@ class RepositoriesController < ApplicationController
redirect_to :action => 'committers', :id => @project redirect_to :action => 'committers', :id => @project
end end
end end
def destroy def destroy
@repository.destroy @repository.destroy
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository' redirect_to :controller => 'projects',
:action => 'settings',
:id => @project,
:tab => 'repository'
end end
def show def show
@repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty? @repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty?
@entries = @repository.entries(@path, @rev) @entries = @repository.entries(@path, @rev)
@changeset = @repository.find_changeset_by_name(@rev)
if request.xhr? if request.xhr?
@entries ? render(:partial => 'dir_list_content') : render(:nothing => true) @entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
else else
@@ -88,30 +104,31 @@ class RepositoriesController < ApplicationController
end end
alias_method :browse, :show alias_method :browse, :show
def changes def changes
@entry = @repository.entry(@path, @rev) @entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry (show_error_not_found; return) unless @entry
@changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i) @changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i)
@properties = @repository.properties(@path, @rev) @properties = @repository.properties(@path, @rev)
@changeset = @repository.find_changeset_by_name(@rev)
end end
def revisions def revisions
@changeset_count = @repository.changesets.count @changeset_count = @repository.changesets.count
@changeset_pages = Paginator.new self, @changeset_count, @changeset_pages = Paginator.new self, @changeset_count,
per_page_option, per_page_option,
params['page'] params['page']
@changesets = @repository.changesets.find(:all, @changesets = @repository.changesets.find(:all,
:limit => @changeset_pages.items_per_page, :limit => @changeset_pages.items_per_page,
:offset => @changeset_pages.current.offset, :offset => @changeset_pages.current.offset,
:include => [:user, :repository]) :include => [:user, :repository])
respond_to do |format| respond_to do |format|
format.html { render :layout => false if request.xhr? } format.html { render :layout => false if request.xhr? }
format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") } format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
end end
end end
def entry def entry
@entry = @repository.entry(@path, @rev) @entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry (show_error_not_found; return) unless @entry
@@ -121,24 +138,46 @@ class RepositoriesController < ApplicationController
@content = @repository.cat(@path, @rev) @content = @repository.cat(@path, @rev)
(show_error_not_found; return) unless @content (show_error_not_found; return) unless @content
if 'raw' == params[:format] || @content.is_binary_data? || (@entry.size && @entry.size > Setting.file_max_size_displayed.to_i.kilobyte) if 'raw' == params[:format] ||
(@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) ||
! is_entry_text_data?(@content, @path)
# Force the download # Force the download
send_data @content, :filename => @path.split('/').last 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_data @content, send_opt
else else
# Prevent empty lines when displaying a file with Windows style eol # 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") @content.gsub!("\r\n", "\n")
end @changeset = @repository.find_changeset_by_name(@rev)
end
end end
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 def annotate
@entry = @repository.entry(@path, @rev) @entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry (show_error_not_found; return) unless @entry
@annotate = @repository.scm.annotate(@path, @rev) @annotate = @repository.scm.annotate(@path, @rev)
(render_error l(:error_scm_annotate); return) if @annotate.nil? || @annotate.empty? (render_error l(:error_scm_annotate); return) if @annotate.nil? || @annotate.empty?
@changeset = @repository.find_changeset_by_name(@rev)
end end
def revision def revision
raise ChangesetNotFound if @rev.blank?
@changeset = @repository.find_changeset_by_name(@rev) @changeset = @repository.find_changeset_by_name(@rev)
raise ChangesetNotFound unless @changeset raise ChangesetNotFound unless @changeset
@@ -149,7 +188,7 @@ class RepositoriesController < ApplicationController
rescue ChangesetNotFound rescue ChangesetNotFound
show_error_not_found show_error_not_found
end end
def diff def diff
if params[:format] == 'diff' if params[:format] == 'diff'
@diff = @repository.diff(@path, @rev, @rev_to) @diff = @repository.diff(@path, @rev, @rev_to)
@@ -162,26 +201,30 @@ class RepositoriesController < ApplicationController
else else
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline' @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type) @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
# Save diff type as user preference # Save diff type as user preference
if User.current.logged? && @diff_type != User.current.pref[:diff_type] if User.current.logged? && @diff_type != User.current.pref[:diff_type]
User.current.pref[:diff_type] = @diff_type User.current.pref[:diff_type] = @diff_type
User.current.preference.save User.current.preference.save
end end
@cache_key = "repositories/diff/#{@repository.id}/" +
@cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}") Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}")
unless read_fragment(@cache_key) unless read_fragment(@cache_key)
@diff = @repository.diff(@path, @rev, @rev_to) @diff = @repository.diff(@path, @rev, @rev_to)
show_error_not_found unless @diff show_error_not_found unless @diff
end 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
end end
def stats def stats
end end
def graph def graph
data = nil data = nil
case params[:graph] case params[:graph]
when "commits_per_month" when "commits_per_month"
data = graph_commits_per_month(@repository) data = graph_commits_per_month(@repository)
@@ -195,7 +238,7 @@ class RepositoriesController < ApplicationController
render_404 render_404
end end
end end
private private
REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
@@ -208,8 +251,8 @@ class RepositoriesController < ApplicationController
@path ||= '' @path ||= ''
@rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip
@rev_to = params[:rev_to] @rev_to = params[:rev_to]
unless @rev.to_s.match(REV_PARAM_RE) && @rev.to_s.match(REV_PARAM_RE) unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
if @repository.branches.blank? if @repository.branches.blank?
raise InvalidRevisionParam raise InvalidRevisionParam
end end
@@ -221,29 +264,33 @@ class RepositoriesController < ApplicationController
end end
def show_error_not_found def show_error_not_found
render_error l(:error_scm_not_found) render_error :message => l(:error_scm_not_found), :status => 404
end end
# Handler for Redmine::Scm::Adapters::CommandFailed exception # Handler for Redmine::Scm::Adapters::CommandFailed exception
def show_error_command_failed(exception) def show_error_command_failed(exception)
render_error l(:error_scm_command_failed, exception.message) render_error l(:error_scm_command_failed, exception.message)
end end
def graph_commits_per_month(repository) def graph_commits_per_month(repository)
@date_to = Date.today @date_to = Date.today
@date_from = @date_to << 11 @date_from = @date_to << 11
@date_from = Date.civil(@date_from.year, @date_from.month, 1) @date_from = Date.civil(@date_from.year, @date_from.month, 1)
commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to]) commits_by_day = repository.changesets.count(
:all, :group => :commit_date,
:conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
commits_by_month = [0] * 12 commits_by_month = [0] * 12
commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last } commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
changes_by_day = repository.changes.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to]) changes_by_day = repository.changes.count(
:all, :group => :commit_date,
:conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
changes_by_month = [0] * 12 changes_by_month = [0] * 12
changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last } changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
fields = [] fields = []
12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)} 12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)}
graph = SVG::Graph::Bar.new( graph = SVG::Graph::Bar.new(
:height => 300, :height => 300,
:width => 800, :width => 800,
@@ -255,7 +302,7 @@ class RepositoriesController < ApplicationController
:graph_title => l(:label_commits_per_month), :graph_title => l(:label_commits_per_month),
:show_graph_title => true :show_graph_title => true
) )
graph.add_data( graph.add_data(
:data => commits_by_month[0..11].reverse, :data => commits_by_month[0..11].reverse,
:title => l(:label_revision_plural) :title => l(:label_revision_plural)
@@ -265,7 +312,7 @@ class RepositoriesController < ApplicationController
:data => changes_by_month[0..11].reverse, :data => changes_by_month[0..11].reverse,
:title => l(:label_change_plural) :title => l(:label_change_plural)
) )
graph.burn graph.burn
end end
@@ -275,18 +322,18 @@ class RepositoriesController < ApplicationController
changes_by_author = repository.changes.count(:all, :group => :committer) changes_by_author = repository.changes.count(:all, :group => :committer)
h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o} h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
fields = commits_by_author.collect {|r| r.first} fields = commits_by_author.collect {|r| r.first}
commits_data = commits_by_author.collect {|r| r.last} commits_data = commits_by_author.collect {|r| r.last}
changes_data = commits_by_author.collect {|r| h[r.first] || 0} changes_data = commits_by_author.collect {|r| h[r.first] || 0}
fields = fields + [""]*(10 - fields.length) if fields.length<10 fields = fields + [""]*(10 - fields.length) if fields.length<10
commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.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 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
# Remove email adress in usernames # Remove email adress in usernames
fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') } fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') }
graph = SVG::Graph::BarHorizontal.new( graph = SVG::Graph::BarHorizontal.new(
:height => 400, :height => 400,
:width => 800, :width => 800,
@@ -298,22 +345,18 @@ class RepositoriesController < ApplicationController
:graph_title => l(:label_commits_per_author), :graph_title => l(:label_commits_per_author),
:show_graph_title => true :show_graph_title => true
) )
graph.add_data( graph.add_data(
:data => commits_data, :data => commits_data,
:title => l(:label_revision_plural) :title => l(:label_revision_plural)
) )
graph.add_data( graph.add_data(
:data => changes_data, :data => changes_data,
:title => l(:label_change_plural) :title => l(:label_change_plural)
) )
graph.burn graph.burn
end end
end end
class Date class Date
def months_ago(date = Date.today) def months_ago(date = Date.today)
(date.year - self.year)*12 + (date.month - self.month) (date.year - self.year)*12 + (date.month - self.month)
+5 -3
View File
@@ -38,9 +38,10 @@ class RolesController < ApplicationController
end end
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'index' redirect_to :action => 'index'
else
@permissions = @role.setable_permissions
@roles = Role.find :all, :order => 'builtin, position'
end end
@permissions = @role.setable_permissions
@roles = Role.find :all, :order => 'builtin, position'
end end
def edit def edit
@@ -48,8 +49,9 @@ class RolesController < ApplicationController
if request.post? and @role.update_attributes(params[:role]) if request.post? and @role.update_attributes(params[:role])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'index' redirect_to :action => 'index'
else
@permissions = @role.setable_permissions
end end
@permissions = @role.setable_permissions
end end
def destroy def destroy
+4 -4
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -24,8 +24,8 @@ class SearchController < ApplicationController
def index def index
@question = params[:q] || "" @question = params[:q] || ""
@question.strip! @question.strip!
@all_words = params[:all_words] || (params[:submit] ? false : true) @all_words = params[:all_words] ? params[:all_words].present? : true
@titles_only = !params[:titles_only].nil? @titles_only = params[:titles_only] ? params[:titles_only].present? : false
projects_to_search = projects_to_search =
case params[:scope] case params[:scope]
+15 -14
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -17,7 +17,7 @@
class SettingsController < ApplicationController class SettingsController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin before_filter :require_admin
def index def index
@@ -36,16 +36,16 @@ class SettingsController < ApplicationController
end end
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'edit', :tab => params[:tab] redirect_to :action => 'edit', :tab => params[:tab]
return else
end @options = {}
@options = {} @options[:user_format] = User::USER_FORMATS.keys.collect {|f| [User.current.name(f), f.to_s] }
@options[:user_format] = User::USER_FORMATS.keys.collect {|f| [User.current.name(f), f.to_s] } @deliveries = ActionMailer::Base.perform_deliveries
@deliveries = ActionMailer::Base.perform_deliveries
@guessed_host_and_path = request.host_with_port.dup @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? @guessed_host_and_path << ('/'+ Redmine::Utils.relative_url_root.gsub(%r{^\/}, '')) unless Redmine::Utils.relative_url_root.blank?
Redmine::Themes.rescan Redmine::Themes.rescan
end
end end
def plugin def plugin
@@ -54,9 +54,10 @@ class SettingsController < ApplicationController
Setting["plugin_#{@plugin.id}"] = params[:settings] Setting["plugin_#{@plugin.id}"] = params[:settings]
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'plugin', :id => @plugin.id redirect_to :action => 'plugin', :id => @plugin.id
else
@partial = @plugin.settings[:partial]
@settings = Setting["plugin_#{@plugin.id}"]
end end
@partial = @plugin.settings[:partial]
@settings = Setting["plugin_#{@plugin.id}"]
rescue Redmine::PluginNotFound rescue Redmine::PluginNotFound
render_404 render_404
end end
+3 -2
View File
@@ -20,7 +20,8 @@ class SysController < ActionController::Base
def projects def projects
p = Project.active.has_module(:repository).find(:all, :include => :repository, :order => 'identifier') p = Project.active.has_module(:repository).find(:all, :include => :repository, :order => 'identifier')
render :xml => p.to_xml(:include => :repository) # 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 end
def create_project_repository def create_project_repository
@@ -31,7 +32,7 @@ class SysController < ActionController::Base
logger.info "Repository for #{project.name} was reported to be created by #{request.remote_ip}." logger.info "Repository for #{project.name} was reported to be created by #{request.remote_ip}."
project.repository = Repository.factory(params[:vendor], params[:repository]) project.repository = Repository.factory(params[:vendor], params[:repository])
if project.repository && project.repository.save if project.repository && project.repository.save
render :xml => project.repository, :status => 201 render :xml => project.repository.to_xml(:only => [:id, :url]), :status => 201
else else
render :nothing => true, :status => 422 render :nothing => true, :status => 422
end end
+121 -69
View File
@@ -1,5 +1,5 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2010 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -18,10 +18,12 @@
class TimelogController < ApplicationController class TimelogController < ApplicationController
menu_item :issues menu_item :issues
before_filter :find_project, :only => [:new, :create] before_filter :find_project, :only => [:new, :create]
before_filter :find_time_entry, :only => [:show, :edit, :update, :destroy] before_filter :find_time_entry, :only => [:show, :edit, :update]
before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
before_filter :authorize, :except => [:index] before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => [:index] before_filter :find_optional_project, :only => [:index]
accept_key_auth :index, :show, :create, :update, :destroy accept_rss_auth :index
accept_api_auth :index, :show, :create, :update, :destroy
helper :sort helper :sort
include SortHelper include SortHelper
@@ -40,60 +42,56 @@ class TimelogController < ApplicationController
'hours' => 'hours' 'hours' => 'hours'
cond = ARCondition.new cond = ARCondition.new
if @project.nil? if @issue
cond << Project.allowed_to_condition(User.current, :view_time_entries)
elsif @issue.nil?
cond << @project.project_condition(Setting.display_subprojects_issues?)
else
cond << "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}" cond << "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}"
elsif @project
cond << @project.project_condition(Setting.display_subprojects_issues?)
end end
retrieve_date_range retrieve_date_range
cond << ['spent_on BETWEEN ? AND ?', @from, @to] cond << ['spent_on BETWEEN ? AND ?', @from, @to]
TimeEntry.visible_by(User.current) do respond_to do |format|
respond_to do |format| format.html {
format.html { # Paginate results
# Paginate results @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
@entry_count = TimeEntry.count(:include => [:project, :issue], :conditions => cond.conditions) @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
@entry_pages = Paginator.new self, @entry_count, per_page_option, params['page'] @entries = TimeEntry.visible.find(:all,
@entries = TimeEntry.find(:all, :include => [:project, :activity, :user, {:issue => :tracker}],
:include => [:project, :activity, :user, {:issue => :tracker}], :conditions => cond.conditions,
:conditions => cond.conditions, :order => sort_clause,
:order => sort_clause, :limit => @entry_pages.items_per_page,
:limit => @entry_pages.items_per_page, :offset => @entry_pages.current.offset)
:offset => @entry_pages.current.offset) @total_hours = TimeEntry.visible.sum(:hours, :include => [:project, :issue], :conditions => cond.conditions).to_f
@total_hours = TimeEntry.sum(:hours, :include => [:project, :issue], :conditions => cond.conditions).to_f
render :layout => !request.xhr? render :layout => !request.xhr?
} }
format.api { format.api {
@entry_count = TimeEntry.count(:include => [:project, :issue], :conditions => cond.conditions) @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
@entry_pages = Paginator.new self, @entry_count, per_page_option, params['page'] @offset, @limit = api_offset_and_limit
@entries = TimeEntry.find(:all, @entries = TimeEntry.visible.find(:all,
:include => [:project, :activity, :user, {:issue => :tracker}], :include => [:project, :activity, :user, {:issue => :tracker}],
:conditions => cond.conditions, :conditions => cond.conditions,
:order => sort_clause, :order => sort_clause,
:limit => @entry_pages.items_per_page, :limit => @limit,
:offset => @entry_pages.current.offset) :offset => @offset)
} }
format.atom { format.atom {
entries = TimeEntry.find(:all, entries = TimeEntry.visible.find(:all,
:include => [:project, :activity, :user, {:issue => :tracker}], :include => [:project, :activity, :user, {:issue => :tracker}],
:conditions => cond.conditions, :conditions => cond.conditions,
:order => "#{TimeEntry.table_name}.created_on DESC", :order => "#{TimeEntry.table_name}.created_on DESC",
:limit => Setting.feeds_limit.to_i) :limit => Setting.feeds_limit.to_i)
render_feed(entries, :title => l(:label_spent_time)) render_feed(entries, :title => l(:label_spent_time))
} }
format.csv { format.csv {
# Export all entries # Export all entries
@entries = TimeEntry.find(:all, @entries = TimeEntry.visible.find(:all,
:include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
:conditions => cond.conditions, :conditions => cond.conditions,
:order => sort_clause) :order => sort_clause)
send_data(entries_to_csv(@entries), :type => 'text/csv; header=present', :filename => 'timelog.csv') send_data(entries_to_csv(@entries), :type => 'text/csv; header=present', :filename => 'timelog.csv')
} }
end
end end
end end
@@ -164,27 +162,55 @@ class TimelogController < ApplicationController
end end
end end
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed } def bulk_edit
def destroy @available_activities = TimeEntryActivity.shared.active
if @time_entry.destroy && @time_entry.destroyed? @custom_fields = TimeEntry.first.available_custom_fields
respond_to do |format| end
format.html {
flash[:notice] = l(:notice_successful_delete) def bulk_update
redirect_to :back attributes = parse_params_for_bulk_time_entry_attributes(params)
}
format.api { head :ok } unsaved_time_entry_ids = []
end @time_entries.each do |time_entry|
else time_entry.reload
respond_to do |format| time_entry.attributes = attributes
format.html { call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry })
flash[:error] = l(:notice_unable_delete_time_entry) unless time_entry.save
redirect_to :back # Keep unsaved time_entry ids to display them in flash error
} unsaved_time_entry_ids << time_entry.id
format.api { render_validation_errors(@time_entry) }
end end
end end
rescue ::ActionController::RedirectBackError set_flash_from_bulk_time_entry_save(@time_entries, unsaved_time_entry_ids)
redirect_to :action => 'index', :project_id => @time_entry.project redirect_back_or_default({:controller => 'timelog', :action => 'index', :project_id => @projects.first})
end
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
def destroy
@time_entries.each do |t|
begin
unless t.destroy && t.destroyed?
respond_to do |format|
format.html {
flash[:error] = l(:notice_unable_delete_time_entry)
redirect_to :back
}
format.api { render_validation_errors(t) }
end
return
end
rescue ::ActionController::RedirectBackError
redirect_to :action => 'index', :project_id => @projects.first
return
end
end
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_delete)
redirect_back_or_default(:action => 'index', :project_id => @projects.first)
}
format.api { head :ok }
end
end end
private private
@@ -199,6 +225,26 @@ private
render_404 render_404
end 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_project def find_project
if (issue_id = (params[:issue_id] || params[:time_entry] && params[:time_entry][:issue_id])).present? if (issue_id = (params[:issue_id] || params[:time_entry] && params[:time_entry][:issue_id])).present?
@issue = Issue.find(issue_id) @issue = Issue.find(issue_id)
@@ -269,4 +315,10 @@ private
@to ||= (TimeEntry.latest_date_for_project(@project) || Date.today) @to ||= (TimeEntry.latest_date_for_project(@project) || Date.today)
end 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 end
+24 -9
View File
@@ -1,5 +1,5 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2010 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -19,8 +19,8 @@ class UsersController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin, :except => :show before_filter :require_admin, :except => :show
before_filter :find_user, :only => [:show, :edit, :update, :edit_membership, :destroy_membership] before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership]
accept_key_auth :index, :show, :create, :update accept_api_auth :index, :show, :create, :update, :destroy
helper :sort helper :sort
include SortHelper include SortHelper
@@ -38,6 +38,9 @@ class UsersController < ApplicationController
@limit = per_page_option @limit = per_page_option
end end
scope = User
scope = scope.in_group(params[:group_id].to_i) if params[:group_id].present?
@status = params[:status] ? params[:status].to_i : 1 @status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status]) c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
@@ -46,24 +49,27 @@ class UsersController < ApplicationController
c << ["LOWER(login) LIKE ? OR LOWER(firstname) LIKE ? OR LOWER(lastname) LIKE ? OR LOWER(mail) LIKE ?", name, name, name, name] c << ["LOWER(login) LIKE ? OR LOWER(firstname) LIKE ? OR LOWER(lastname) LIKE ? OR LOWER(mail) LIKE ?", name, name, name, name]
end end
@user_count = User.count(:conditions => c.conditions) @user_count = scope.count(:conditions => c.conditions)
@user_pages = Paginator.new self, @user_count, @limit, params['page'] @user_pages = Paginator.new self, @user_count, @limit, params['page']
@offset ||= @user_pages.current.offset @offset ||= @user_pages.current.offset
@users = User.find :all, @users = scope.find :all,
:order => sort_clause, :order => sort_clause,
:conditions => c.conditions, :conditions => c.conditions,
:limit => @limit, :limit => @limit,
:offset => @offset :offset => @offset
respond_to do |format| respond_to do |format|
format.html { render :layout => !request.xhr? } format.html {
@groups = Group.all.sort
render :layout => !request.xhr?
}
format.api format.api
end end
end end
def show def show
# show projects based on current user visibility # show projects based on current user visibility
@memberships = @user.memberships.all(:conditions => Project.visible_by(User.current)) @memberships = @user.memberships.all(:conditions => Project.visible_condition(User.current))
events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10) events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
@events_by_day = events.group_by(&:event_date) @events_by_day = events.group_by(&:event_date)
@@ -177,6 +183,15 @@ class UsersController < ApplicationController
redirect_to :controller => 'users', :action => 'edit', :id => @user redirect_to :controller => 'users', :action => 'edit', :id => @user
end end
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
def destroy
@user.destroy
respond_to do |format|
format.html { redirect_to(users_url) }
format.api { head :ok }
end
end
def edit_membership def edit_membership
@membership = Member.edit_membership(params[:membership_id], params[:membership], @user) @membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
@membership.save if request.post? @membership.save if request.post?
+5 -13
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -76,21 +76,13 @@ private
def set_watcher(user, watching) def set_watcher(user, watching)
@watched.set_watcher(user, watching) @watched.set_watcher(user, watching)
if params[:replace].present?
if params[:replace].is_a? Array
replace_ids = params[:replace]
else
replace_ids = [params[:replace]]
end
else
replace_ids = ['watcher']
end
respond_to do |format| respond_to do |format|
format.html { redirect_to :back } format.html { redirect_to :back }
format.js do format.js do
render(:update) do |page| render(:update) do |page|
replace_ids.each do |replace_id| c = watcher_css(@watched)
page.replace_html replace_id, watcher_link(@watched, user, :replace => replace_ids) page.select(".#{c}").each do |item|
page.replace_html item, watcher_link(@watched, user)
end end
end end
end end
+46 -41
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -34,23 +34,27 @@ require 'diff'
class WikiController < ApplicationController class WikiController < ApplicationController
default_search_scope :wiki_pages default_search_scope :wiki_pages
before_filter :find_wiki, :authorize 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] before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
verify :method => :post, :only => [:protect], :redirect_to => { :action => :show }
helper :attachments helper :attachments
include AttachmentsHelper include AttachmentsHelper
helper :watchers helper :watchers
# List of pages, sorted alphabetically and by parent (hierarchy) # List of pages, sorted alphabetically and by parent (hierarchy)
def index def index
load_pages_grouped_by_date_without_content load_pages_for_index
@pages_by_parent_id = @pages.group_by(&:parent_id)
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 end
# display a page (in editing mode if it doesn't exist) # display a page (in editing mode if it doesn't exist)
def show def show
page_title = params[:id]
@page = @wiki.find_or_new_page(page_title)
if @page.new_record? if @page.new_record?
if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? if User.current.allowed_to?(:edit_wiki_pages, @project) && editable?
edit edit
@@ -79,13 +83,12 @@ class WikiController < ApplicationController
@editable = editable? @editable = editable?
render :action => 'show' render :action => 'show'
end end
# edit an existing page or a new one # edit an existing page or a new one
def edit def edit
@page = @wiki.find_or_new_page(params[:id])
return render_403 unless editable? return render_403 unless editable?
@page.content = WikiContent.new(:page => @page) if @page.new_record? @page.content = WikiContent.new(:page => @page) if @page.new_record?
@content = @page.content_for_version(params[:version]) @content = @page.content_for_version(params[:version])
@content.text = initial_page_content(@page) if @content.text.blank? @content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment # don't keep previous comment
@@ -93,18 +96,14 @@ class WikiController < ApplicationController
# To prevent StaleObjectError exception when reverting to a previous version # To prevent StaleObjectError exception when reverting to a previous version
@content.version = @page.content.version @content.version = @page.content.version
rescue ActiveRecord::StaleObjectError
# Optimistic locking exception
flash[:error] = l(:notice_locking_conflict)
end end
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
# Creates a new page or updates an existing one # Creates a new page or updates an existing one
def update def update
@page = @wiki.find_or_new_page(params[:id])
return render_403 unless editable? return render_403 unless editable?
@page.content = WikiContent.new(:page => @page) if @page.new_record? @page.content = WikiContent.new(:page => @page) if @page.new_record?
@content = @page.content_for_version(params[:version]) @content = @page.content_for_version(params[:version])
@content.text = initial_page_content(@page) if @content.text.blank? @content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment # don't keep previous comment
@@ -131,7 +130,8 @@ class WikiController < ApplicationController
rescue ActiveRecord::StaleObjectError rescue ActiveRecord::StaleObjectError
# Optimistic locking exception # Optimistic locking exception
flash[:error] = l(:notice_locking_conflict) flash.now[:error] = l(:notice_locking_conflict)
render :action => 'edit'
end end
# rename a page # rename a page
@@ -145,7 +145,8 @@ class WikiController < ApplicationController
redirect_to :action => 'show', :project_id => @project, :id => @page.title redirect_to :action => 'show', :project_id => @project, :id => @page.title
end end
end end
verify :method => :post, :only => :protect, :redirect_to => { :action => :show }
def protect def protect
@page.update_attribute :protected, params[:protected] @page.update_attribute :protected, params[:protected]
redirect_to :action => 'show', :project_id => @project, :id => @page.title redirect_to :action => 'show', :project_id => @project, :id => @page.title
@@ -155,8 +156,8 @@ class WikiController < ApplicationController
def history def history
@version_count = @page.content.versions.count @version_count = @page.content.versions.count
@version_pages = Paginator.new self, @version_count, per_page_option, params['p'] @version_pages = Paginator.new self, @version_count, per_page_option, params['p']
# don't load text # don't load text
@versions = @page.content.versions.find :all, @versions = @page.content.versions.find :all,
:select => "id, author_id, comments, updated_on, version", :select => "id, author_id, comments, updated_on, version",
:order => 'version DESC', :order => 'version DESC',
:limit => @version_pages.items_per_page + 1, :limit => @version_pages.items_per_page + 1,
@@ -164,12 +165,12 @@ class WikiController < ApplicationController
render :layout => false if request.xhr? render :layout => false if request.xhr?
end end
def diff def diff
@diff = @page.diff(params[:version], params[:version_from]) @diff = @page.diff(params[:version], params[:version_from])
render_404 unless @diff render_404 unless @diff
end end
def annotate def annotate
@annotate = @page.annotate(params[:version]) @annotate = @page.annotate(params[:version])
render_404 unless @annotate render_404 unless @annotate
@@ -180,7 +181,7 @@ class WikiController < ApplicationController
# Children can be either set as root pages, removed or reassigned to another parent page # Children can be either set as root pages, removed or reassigned to another parent page
def destroy def destroy
return render_403 unless editable? return render_403 unless editable?
@descendants_count = @page.descendants.size @descendants_count = @page.descendants.size
if @descendants_count > 0 if @descendants_count > 0
case params[:todo] case params[:todo]
@@ -216,10 +217,6 @@ class WikiController < ApplicationController
end end
end end
def date_index
load_pages_grouped_by_date_without_content
end
def preview def preview
page = @wiki.find_page(params[:id]) page = @wiki.find_page(params[:id])
# page is nil when previewing a new page # page is nil when previewing a new page
@@ -240,7 +237,7 @@ class WikiController < ApplicationController
end end
private private
def find_wiki def find_wiki
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
@wiki = @project.wiki @wiki = @project.wiki
@@ -248,13 +245,27 @@ private
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end 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 # Finds the requested page and returns a 404 error if it doesn't exist
def find_existing_page def find_existing_page
@page = @wiki.find_page(params[:id]) @page = @wiki.find_page(params[:id])
render_404 if @page.nil? if @page.nil?
render_404
return
end
if @wiki.page_found_with_redirect?
redirect_to params.update(:id => @page.title)
end
end end
# Returns true if the current user is allowed to edit the page, otherwise false # Returns true if the current user is allowed to edit the page, otherwise false
def editable?(page = @page) def editable?(page = @page)
page.editable_by?(User.current) page.editable_by?(User.current)
@@ -267,13 +278,7 @@ private
helper.instance_method(:initial_page_content).bind(self).call(page) helper.instance_method(:initial_page_content).bind(self).call(page)
end end
# eager load information about last updates, without loading text def load_pages_for_index
def load_pages_grouped_by_date_without_content @pages = @wiki.pages.with_updated_on.all(:order => 'title', :include => {:wiki => :project})
@pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
:joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
:order => 'title'
@pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
@pages_by_parent_id = @pages.group_by(&:parent_id)
end end
end end
+14 -3
View File
@@ -32,14 +32,17 @@ class WorkflowsController < ApplicationController
if request.post? if request.post?
Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id]) Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
(params[:issue_status] || []).each { |old, news| (params[:issue_status] || []).each { |status_id, transitions|
news.each { |new| transitions.each { |new_status_id, options|
@role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new) author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
@role.workflows.build(:tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
} }
} }
if @role.save if @role.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'edit', :role_id => @role, :tracker_id => @tracker redirect_to :action => 'edit', :role_id => @role, :tracker_id => @tracker
return
end end
end end
@@ -48,6 +51,14 @@ class WorkflowsController < ApplicationController
@statuses = @tracker.issue_statuses @statuses = @tracker.issue_statuses
end end
@statuses ||= IssueStatus.find(:all, :order => 'position') @statuses ||= IssueStatus.find(:all, :order => 'position')
if @tracker && @role && @statuses.any?
workflows = Workflow.all(:conditions => {:role_id => @role.id, :tracker_id => @tracker.id})
@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 end
def copy def copy
+126 -94
View File
@@ -1,5 +1,5 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2010 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -63,7 +63,7 @@ module ApplicationHelper
# Displays a link to +issue+ with its subject. # Displays a link to +issue+ with its subject.
# Examples: # Examples:
# #
# link_to_issue(issue) # => Defect #6: This is the subject # link_to_issue(issue) # => Defect #6: This is the subject
# link_to_issue(issue, :truncate => 6) # => Defect #6: This i... # link_to_issue(issue, :truncate => 6) # => Defect #6: This i...
# link_to_issue(issue, :subject => false) # => Defect #6 # link_to_issue(issue, :subject => false) # => Defect #6
@@ -80,7 +80,7 @@ module ApplicationHelper
subject = truncate(subject, :length => options[:truncate]) subject = truncate(subject, :length => options[:truncate])
end end
end end
s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue},
:class => issue.css_classes, :class => issue.css_classes,
:title => title :title => title
s << ": #{h subject}" if subject s << ": #{h subject}" if subject
@@ -104,13 +104,29 @@ module ApplicationHelper
# * :text - Link text (default to the formatted revision) # * :text - Link text (default to the formatted revision)
def link_to_revision(revision, project, options={}) def link_to_revision(revision, project, options={})
text = options.delete(:text) || format_revision(revision) text = options.delete(:text) || format_revision(revision)
rev = revision.respond_to?(:identifier) ? revision.identifier : revision
link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => revision}, :title => l(:label_revision_id, revision)) link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :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(
h(truncate(message.subject, :length => 60)),
{ :controller => 'messages', :action => 'show',
:board_id => message.board_id,
:id => message.root,
:r => (message.parent_id && message.id),
:anchor => (message.parent_id ? "message-#{message.id}" : nil)
}.merge(options),
html_options
)
end end
# Generates a link to a project if active # Generates a link to a project if active
# Examples: # Examples:
# #
# link_to_project(project) # => link to the specified project overview # link_to_project(project) # => link to the specified project overview
# link_to_project(project, :action=>'settings') # => link to project settings # link_to_project(project, :action=>'settings') # => link to project settings
# link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options
@@ -144,15 +160,15 @@ module ApplicationHelper
html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;" html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
link_to name, {}, html_options link_to name, {}, html_options
end end
def format_activity_title(text) def format_activity_title(text)
h(truncate_single_line(text, :length => 100)) h(truncate_single_line(text, :length => 100))
end end
def format_activity_day(date) def format_activity_day(date)
date == Date.today ? l(:label_today).titleize : format_date(date) date == Date.today ? l(:label_today).titleize : format_date(date)
end end
def format_activity_description(text) def format_activity_description(text)
h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />") h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />")
end end
@@ -164,29 +180,29 @@ module ApplicationHelper
h("#{version.project} - #{version}") h("#{version.project} - #{version}")
end end
end end
def due_date_distance_in_words(date) def due_date_distance_in_words(date)
if date if date
l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date)) l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date))
end end
end end
def render_page_hierarchy(pages, node=nil) def render_page_hierarchy(pages, node=nil, options={})
content = '' content = ''
if pages[node] if pages[node]
content << "<ul class=\"pages-hierarchy\">\n" content << "<ul class=\"pages-hierarchy\">\n"
pages[node].each do |page| pages[node].each do |page|
content << "<li>" content << "<li>"
content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}, content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title},
:title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : 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) if pages[page.id] content << "\n" + render_page_hierarchy(pages, page.id, options) if pages[page.id]
content << "</li>\n" content << "</li>\n"
end end
content << "</ul>\n" content << "</ul>\n"
end end
content content
end end
# Renders flash messages # Renders flash messages
def render_flash_messages def render_flash_messages
s = '' s = ''
@@ -195,7 +211,7 @@ module ApplicationHelper
end end
s s
end end
# Renders tabs and their content # Renders tabs and their content
def render_tabs(tabs) def render_tabs(tabs)
if tabs.any? if tabs.any?
@@ -204,11 +220,11 @@ module ApplicationHelper
content_tag 'p', l(:label_no_data), :class => "nodata" content_tag 'p', l(:label_no_data), :class => "nodata"
end end
end end
# Renders the project quick-jump box # Renders the project quick-jump box
def render_project_jump_box def render_project_jump_box
# Retrieve them now to avoid a COUNT query return unless User.current.logged?
projects = User.current.projects.all projects = User.current.memberships.collect(&:project).compact.uniq
if projects.any? if projects.any?
s = '<select onchange="if (this.value != \'\') { window.location = this.value; }">' + s = '<select onchange="if (this.value != \'\') { window.location = this.value; }">' +
"<option value=''>#{ l(:label_jump_to_a_project) }</option>" + "<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
@@ -220,7 +236,7 @@ module ApplicationHelper
s s
end end
end end
def project_tree_options_for_select(projects, options = {}) def project_tree_options_for_select(projects, options = {})
s = '' s = ''
project_tree(projects) do |project, level| project_tree(projects) do |project, level|
@@ -236,14 +252,14 @@ module ApplicationHelper
end end
s s
end end
# Yields the given block for each project with its level in the tree # Yields the given block for each project with its level in the tree
# #
# Wrapper for Project#project_tree # Wrapper for Project#project_tree
def project_tree(projects, &block) def project_tree(projects, &block)
Project.project_tree(projects, &block) Project.project_tree(projects, &block)
end end
def project_nested_ul(projects, &block) def project_nested_ul(projects, &block)
s = '' s = ''
if projects.any? if projects.any?
@@ -254,7 +270,7 @@ module ApplicationHelper
else else
ancestors.pop ancestors.pop
s << "</li>" s << "</li>"
while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
ancestors.pop ancestors.pop
s << "</ul></li>\n" s << "</ul></li>\n"
end end
@@ -267,20 +283,20 @@ module ApplicationHelper
end end
s s
end end
def principals_check_box_tags(name, principals) def principals_check_box_tags(name, principals)
s = '' s = ''
principals.sort.each do |principal| principals.sort.each do |principal|
s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n" s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n"
end end
s s
end end
# Truncates and returns the string as a single line # Truncates and returns the string as a single line
def truncate_single_line(string, *args) def truncate_single_line(string, *args)
truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ')
end end
# Truncates at line break after 250 characters or options[:length] # Truncates at line break after 250 characters or options[:length]
def truncate_lines(string, options={}) def truncate_lines(string, options={})
length = options[:length] || 250 length = options[:length] || 250
@@ -298,7 +314,7 @@ module ApplicationHelper
def authoring(created, author, options={}) def authoring(created, author, options={})
l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)) l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created))
end end
def time_tag(time) def time_tag(time)
text = distance_of_time_in_words(Time.now, time) text = distance_of_time_in_words(Time.now, time)
if @project if @project
@@ -320,20 +336,18 @@ module ApplicationHelper
page_param = options.delete(:page_param) || :page page_param = options.delete(:page_param) || :page
per_page_links = options.delete(:per_page_links) per_page_links = options.delete(:per_page_links)
url_param = params.dup url_param = params.dup
# don't reuse query params if filters are present
url_param.merge!(:fields => nil, :values => nil, :operators => nil) if url_param.delete(:set_filter)
html = '' html = ''
if paginator.current.previous if paginator.current.previous
html << link_to_remote_content_update('&#171; ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' ' html << link_to_content_update('&#171; ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' '
end end
html << (pagination_links_each(paginator, options) do |n| html << (pagination_links_each(paginator, options) do |n|
link_to_remote_content_update(n.to_s, url_param.merge(page_param => n)) link_to_content_update(n.to_s, url_param.merge(page_param => n))
end || '') end || '')
if paginator.current.next if paginator.current.next
html << ' ' + link_to_remote_content_update((l(:label_next) + ' &#187;'), url_param.merge(page_param => paginator.current.next)) html << ' ' + link_to_content_update((l(:label_next) + ' &#187;'), url_param.merge(page_param => paginator.current.next))
end end
unless count.nil? unless count.nil?
@@ -345,20 +359,14 @@ module ApplicationHelper
html html
end end
def per_page_links(selected=nil)
url_param = params.dup
url_param.clear if url_param.has_key?(:set_filter)
def per_page_links(selected=nil)
links = Setting.per_page_options_array.collect do |n| links = Setting.per_page_options_array.collect do |n|
n == selected ? n : link_to_remote(n, {:update => "content", n == selected ? n : link_to_content_update(n, params.merge(:per_page => n))
:url => params.dup.merge(:per_page => n),
:method => :get},
{:href => url_for(url_param.merge(:per_page => n))})
end end
links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil
end end
def reorder_links(name, url) def reorder_links(name, url)
link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => :post, :title => l(:label_sort_highest)) + link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => :post, :title => l(:label_sort_highest)) +
link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => :post, :title => l(:label_sort_higher)) + link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => :post, :title => l(:label_sort_higher)) +
@@ -370,19 +378,19 @@ module ApplicationHelper
elements = args.flatten elements = args.flatten
elements.any? ? content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb') : nil elements.any? ? content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb') : nil
end end
def other_formats_links(&block) def other_formats_links(&block)
concat('<p class="other-formats">' + l(:label_export_to)) concat('<p class="other-formats">' + l(:label_export_to))
yield Redmine::Views::OtherFormatsBuilder.new(self) yield Redmine::Views::OtherFormatsBuilder.new(self)
concat('</p>') concat('</p>')
end end
def page_header_title def page_header_title
if @project.nil? || @project.new_record? if @project.nil? || @project.new_record?
h(Setting.app_title) h(Setting.app_title)
else else
b = [] b = []
ancestors = (@project.root? ? [] : @project.ancestors.visible) ancestors = (@project.root? ? [] : @project.ancestors.visible.all)
if ancestors.any? if ancestors.any?
root = ancestors.shift root = ancestors.shift
b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') b << link_to_project(root, {:jump => current_menu_item}, :class => 'root')
@@ -449,21 +457,21 @@ module ApplicationHelper
only_path = options.delete(:only_path) == false ? false : true only_path = options.delete(:only_path) == false ? false : true
text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) } text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) }
@parsed_headings = [] @parsed_headings = []
text = parse_non_pre_blocks(text) do |text| text = parse_non_pre_blocks(text) do |text|
[:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name| [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name|
send method_name, text, project, obj, attr, only_path, options send method_name, text, project, obj, attr, only_path, options
end end
end end
if @parsed_headings.any? if @parsed_headings.any?
replace_toc(text, @parsed_headings) replace_toc(text, @parsed_headings)
end end
text text
end end
def parse_non_pre_blocks(text) def parse_non_pre_blocks(text)
s = StringScanner.new(text) s = StringScanner.new(text)
tags = [] tags = []
@@ -492,13 +500,13 @@ module ApplicationHelper
end end
parsed parsed
end end
def parse_inline_attachments(text, project, obj, attr, only_path, options) def parse_inline_attachments(text, project, obj, attr, only_path, options)
# when using an image link, try to use an attachment, if possible # when using an image link, try to use an attachment, if possible
if options[:attachments] || (obj && obj.respond_to?(:attachments)) if options[:attachments] || (obj && obj.respond_to?(:attachments))
attachments = nil attachments = nil
text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m|
filename, ext, alt, alttext = $1.downcase, $2, $3, $4 filename, ext, alt, alttext = $1.downcase, $2, $3, $4
attachments ||= (options[:attachments] || obj.attachments).sort_by(&:created_on).reverse attachments ||= (options[:attachments] || obj.attachments).sort_by(&:created_on).reverse
# search for the picture in attachments # search for the picture in attachments
if found = attachments.detect { |att| att.filename.downcase == filename } if found = attachments.detect { |att| att.filename.downcase == filename }
@@ -542,15 +550,20 @@ module ApplicationHelper
if page =~ /^(.+?)\#(.+)$/ if page =~ /^(.+?)\#(.+)$/
page, anchor = $1, $2 page, anchor = $1, $2
end end
anchor = sanitize_anchor_name(anchor) if anchor.present?
# check if page exists # check if page exists
wiki_page = link_project.wiki.find_page(page) wiki_page = link_project.wiki.find_page(page)
url = case options[:wiki_links] url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page
when :local; "#{title}.html" "##{anchor}"
else
case options[:wiki_links]
when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '')
when :anchor; "##{title}" # used for single-file wiki export when :anchor; "##{title}" # used for single-file wiki export
else else
wiki_page_id = page.present? ? Wiki.titleize(page) : nil wiki_page_id = page.present? ? Wiki.titleize(page) : nil
url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, :id => wiki_page_id, :anchor => anchor) url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, :id => wiki_page_id, :anchor => anchor)
end end
end
link_to((title || page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new'))) link_to((title || page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
else else
# project or wiki doesn't exist # project or wiki doesn't exist
@@ -561,7 +574,7 @@ module ApplicationHelper
end end
end end
end end
# Redmine links # Redmine links
# #
# Examples: # Examples:
@@ -586,16 +599,26 @@ module ApplicationHelper
# source:some/file#L120 -> Link to line 120 of the file # 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 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
# export:some/file -> Force the download of the file # export:some/file -> Force the download of the file
# Forum messages: # Forum messages:
# message#1218 -> Link to message with id 1218 # message#1218 -> Link to message with id 1218
#
# 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, project, obj, attr, only_path, options) def parse_redmine_links(text, project, obj, attr, only_path, options)
text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(attachment|document|version|commit|source|export|message|project)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|,|\s|\]|<|$)}) do |m| text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-]+):)?(attachment|document|version|commit|source|export|message|project)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|,|\s|\]|<|$)}) do |m|
leading, esc, prefix, sep, identifier = $1, $2, $3, $5 || $7, $6 || $8 leading, esc, project_prefix, project_identifier, prefix, sep, identifier = $1, $2, $3, $4, $5, $7 || $9, $8 || $10
link = nil link = nil
if project_identifier
project = Project.visible.find_by_identifier(project_identifier)
end
if esc.nil? if esc.nil?
if prefix.nil? && sep == 'r' if prefix.nil? && sep == 'r'
if project && (changeset = project.changesets.find_by_revision(identifier)) # project.changesets.visible raises an SQL error because of a double join on repositories
link = link_to("r#{identifier}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision}, if project && project.repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(project.repository.id, identifier))
link = link_to("#{project_prefix}r#{identifier}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
:class => 'changeset', :class => 'changeset',
:title => truncate_single_line(changeset.comments, :length => 100)) :title => truncate_single_line(changeset.comments, :length => 100))
end end
@@ -609,24 +632,18 @@ module ApplicationHelper
:title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})") :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
end end
when 'document' when 'document'
if document = Document.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current)) if document = Document.visible.find_by_id(oid)
link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
:class => 'document' :class => 'document'
end end
when 'version' when 'version'
if version = Version.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current)) if version = Version.visible.find_by_id(oid)
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
:class => 'version' :class => 'version'
end end
when 'message' when 'message'
if message = Message.find_by_id(oid, :include => [:parent, {:board => :project}], :conditions => Project.visible_by(User.current)) if message = Message.visible.find_by_id(oid, :include => :parent)
link = link_to h(truncate(message.subject, :length => 60)), {:only_path => only_path, link = link_to_message(message, {:only_path => only_path}, :class => 'message')
:controller => 'messages',
:action => 'show',
:board_id => message.board,
:id => message.root,
:anchor => (message.parent ? "message-#{message.id}" : nil)},
:class => 'message'
end end
when 'project' when 'project'
if p = Project.visible.find_by_id(oid) if p = Project.visible.find_by_id(oid)
@@ -638,26 +655,26 @@ module ApplicationHelper
name = identifier.gsub(%r{^"(.*)"$}, "\\1") name = identifier.gsub(%r{^"(.*)"$}, "\\1")
case prefix case prefix
when 'document' when 'document'
if project && document = project.documents.find_by_title(name) 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}, link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
:class => 'document' :class => 'document'
end end
when 'version' when 'version'
if project && version = project.versions.find_by_name(name) 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}, link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
:class => 'version' :class => 'version'
end end
when 'commit' when 'commit'
if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"])) if project && project.repository && (changeset = Changeset.visible.find(:first, :conditions => ["repository_id = ? AND scmid LIKE ?", project.repository.id, "#{name}%"]))
link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision}, link = link_to h("#{project_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.identifier},
:class => 'changeset', :class => 'changeset',
:title => truncate_single_line(changeset.comments, :length => 100) :title => truncate_single_line(changeset.comments, :length => 100)
end end
when 'source', 'export' when 'source', 'export'
if project && project.repository if project && project.repository && User.current.allowed_to?(:browse_repository, project)
name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$} name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
path, rev, anchor = $1, $3, $5 path, rev, anchor = $1, $3, $5
link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project, link = link_to h("#{project_prefix}#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project,
:path => to_path_param(path), :path => to_path_param(path),
:rev => rev, :rev => rev,
:anchor => anchor, :anchor => anchor,
@@ -677,28 +694,28 @@ module ApplicationHelper
end end
end end
end end
leading + (link || "#{prefix}#{sep}#{identifier}") leading + (link || "#{project_prefix}#{prefix}#{sep}#{identifier}")
end end
end end
HEADING_RE = /<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>/i unless const_defined?(:HEADING_RE) HEADING_RE = /<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>/i unless const_defined?(:HEADING_RE)
# Headings and TOC # Headings and TOC
# Adds ids and links to headings unless options[:headings] is set to false # Adds ids and links to headings unless options[:headings] is set to false
def parse_headings(text, project, obj, attr, only_path, options) def parse_headings(text, project, obj, attr, only_path, options)
return if options[:headings] == false return if options[:headings] == false
text.gsub!(HEADING_RE) do text.gsub!(HEADING_RE) do
level, attrs, content = $1.to_i, $2, $3 level, attrs, content = $1.to_i, $2, $3
item = strip_tags(content).strip item = strip_tags(content).strip
anchor = item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') anchor = sanitize_anchor_name(item)
@parsed_headings << [level, anchor, item] @parsed_headings << [level, anchor, item]
"<h#{level} #{attrs} id=\"#{anchor}\">#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a></h#{level}>" "<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a></h#{level}>"
end end
end end
TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
# Renders the TOC with given headings # Renders the TOC with given headings
def replace_toc(text, headings) def replace_toc(text, headings)
text.gsub!(TOC_RE) do text.gsub!(TOC_RE) do
@@ -781,13 +798,13 @@ module ApplicationHelper
), :class => 'progress', :style => "width: #{width};") + ), :class => 'progress', :style => "width: #{width};") +
content_tag('p', legend, :class => 'pourcent') content_tag('p', legend, :class => 'pourcent')
end end
def checked_image(checked=true) def checked_image(checked=true)
if checked if checked
image_tag 'toggle_check.png' image_tag 'toggle_check.png'
end end
end end
def context_menu(url) def context_menu(url)
unless @context_menu_included unless @context_menu_included
content_for :header_tags do content_for :header_tags do
@@ -835,13 +852,15 @@ module ApplicationHelper
'Calendar._FD = 1;' # Monday 'Calendar._FD = 1;' # Monday
when 7 when 7
'Calendar._FD = 0;' # Sunday 'Calendar._FD = 0;' # Sunday
when 6
'Calendar._FD = 6;' # Saturday
else else
'' # use language '' # use language
end end
javascript_include_tag('calendar/calendar') + javascript_include_tag('calendar/calendar') +
javascript_include_tag("calendar/lang/calendar-#{current_language.to_s.downcase}.js") + javascript_include_tag("calendar/lang/calendar-#{current_language.to_s.downcase}.js") +
javascript_tag(start_of_week) + javascript_tag(start_of_week) +
javascript_include_tag('calendar/calendar-setup') + javascript_include_tag('calendar/calendar-setup') +
stylesheet_link_tag('calendar') stylesheet_link_tag('calendar')
end end
@@ -875,10 +894,27 @@ module ApplicationHelper
end end
end end
def sanitize_anchor_name(anchor)
anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
end
# Returns the javascript tags that are included in the html layout head
def javascript_heads
tags = javascript_include_tag(:defaults)
unless User.current.pref.warn_on_leaving_unsaved == '0'
tags << "\n" + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });")
end
tags
end
def favicon def favicon
"<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />" "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />"
end end
def robot_exclusion_tag
'<meta name="robots" content="noindex,follow,noarchive" />'
end
# Returns true if arg is expected in the API response # Returns true if arg is expected in the API response
def include_in_api_response?(arg) def include_in_api_response?(arg)
unless @included_in_api_response unless @included_in_api_response
@@ -900,7 +936,7 @@ module ApplicationHelper
options options
end end
end end
private private
def wiki_helper def wiki_helper
@@ -908,12 +944,8 @@ module ApplicationHelper
extend helper extend helper
return self return self
end end
def link_to_remote_content_update(text, url_params) def link_to_content_update(text, url_params = {}, html_options = {})
link_to_remote(text, link_to(text, url_params, html_options)
{:url => url_params, :method => :get, :update => 'content', :complete => 'window.scrollTo(0,0)'},
{:href => url_for(:params => url_params)}
)
end end
end end
+19 -7
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -21,14 +21,26 @@ module AttachmentsHelper
# :author -- author names are not displayed if set to false # :author -- author names are not displayed if set to false
def link_to_attachments(container, options = {}) def link_to_attachments(container, options = {})
options.assert_valid_keys(:author) options.assert_valid_keys(:author)
if container.attachments.any? if container.attachments.any?
options = {:deletable => container.attachments_deletable?, :author => true}.merge(options) options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
render :partial => 'attachments/links', :locals => {:attachments => container.attachments, :options => options} render :partial => 'attachments/links', :locals => {:attachments => container.attachments, :options => options}
end end
end end
def to_utf8(str) def to_utf8(str)
str if str.respond_to?(:force_encoding)
str.force_encoding('UTF-8')
return str if str.valid_encoding?
else
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
end
begin
Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3]
rescue Iconv::InvalidEncoding
# "UTF-8//IGNORE" is not supported on some OS
str
end
end end
end end
+1 -9
View File
@@ -32,14 +32,6 @@ module CalendarsHelper
end end
def link_to_month(link_name, year, month, options={}) def link_to_month(link_name, year, month, options={})
project_id = options[:project].present? ? options[:project].to_param : nil link_to_content_update(link_name, params.merge(:year => year, :month => month))
link_target = calendar_path(:year => year, :month => month, :project_id => project_id)
link_to_remote(link_name,
{:update => "content", :url => link_target, :method => :put},
{:href => link_target})
end end
end end
+9 -9
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -37,7 +37,7 @@ module CustomFieldsHelper
field_id = "#{name}_custom_field_values_#{custom_field.id}" field_id = "#{name}_custom_field_values_#{custom_field.id}"
field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format) field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format)
case field_format.edit_as case field_format.try(:edit_as)
when "date" when "date"
text_field_tag(field_name, custom_value.value, :id => field_id, :size => 10) + text_field_tag(field_name, custom_value.value, :id => field_id, :size => 10) +
calendar_for(field_id) calendar_for(field_id)
@@ -49,7 +49,7 @@ module CustomFieldsHelper
blank_option = custom_field.is_required? ? blank_option = custom_field.is_required? ?
(custom_field.default_value.blank? ? "<option value=\"\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" : '') : (custom_field.default_value.blank? ? "<option value=\"\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" : '') :
'<option></option>' '<option></option>'
select_tag(field_name, blank_option + options_for_select(custom_field.possible_values, custom_value.value), :id => field_id) select_tag(field_name, blank_option + options_for_select(custom_field.possible_values_options(custom_value.customized), custom_value.value), :id => field_id)
else else
text_field_tag(field_name, custom_value.value, :id => field_id) text_field_tag(field_name, custom_value.value, :id => field_id)
end end
@@ -68,11 +68,11 @@ module CustomFieldsHelper
custom_field_label_tag(name, custom_value) + custom_field_tag(name, custom_value) custom_field_label_tag(name, custom_value) + custom_field_tag(name, custom_value)
end end
def custom_field_tag_for_bulk_edit(name, custom_field) def custom_field_tag_for_bulk_edit(name, custom_field, projects=nil)
field_name = "#{name}[custom_field_values][#{custom_field.id}]" field_name = "#{name}[custom_field_values][#{custom_field.id}]"
field_id = "#{name}_custom_field_values_#{custom_field.id}" field_id = "#{name}_custom_field_values_#{custom_field.id}"
field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format) field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format)
case field_format.edit_as case field_format.try(:edit_as)
when "date" when "date"
text_field_tag(field_name, '', :id => field_id, :size => 10) + text_field_tag(field_name, '', :id => field_id, :size => 10) +
calendar_for(field_id) calendar_for(field_id)
@@ -83,7 +83,7 @@ module CustomFieldsHelper
[l(:general_text_yes), '1'], [l(:general_text_yes), '1'],
[l(:general_text_no), '0']]), :id => field_id) [l(:general_text_no), '0']]), :id => field_id)
when "list" when "list"
select_tag(field_name, options_for_select([[l(:label_no_change_option), '']] + custom_field.possible_values), :id => field_id) select_tag(field_name, options_for_select([[l(:label_no_change_option), '']] + custom_field.possible_values_options(projects)), :id => field_id)
else else
text_field_tag(field_name, '', :id => field_id) text_field_tag(field_name, '', :id => field_id)
end end
@@ -101,8 +101,8 @@ module CustomFieldsHelper
end end
# Return an array of custom field formats which can be used in select_tag # Return an array of custom field formats which can be used in select_tag
def custom_field_formats_for_select def custom_field_formats_for_select(custom_field)
Redmine::CustomFieldFormat.as_select Redmine::CustomFieldFormat.as_select(custom_field.class.customized_class.name)
end end
# Renders the custom_values in api views # Renders the custom_values in api views
+8 -16
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -21,29 +21,21 @@ module GanttHelper
case in_or_out case in_or_out
when :in when :in
if gantt.zoom < 4 if gantt.zoom < 4
link_to_remote(l(:text_zoom_in), link_to_content_update l(:text_zoom_in),
{:url => gantt.params.merge(:zoom => (gantt.zoom+1)), :method => :get, :update => 'content'}, params.merge(gantt.params.merge(:zoom => (gantt.zoom+1))),
{:href => url_for(gantt.params.merge(:zoom => (gantt.zoom+1))), :class => 'icon icon-zoom-in'
:class => 'icon icon-zoom-in'})
else else
content_tag('span', l(:text_zoom_in), :class => 'icon icon-zoom-in') content_tag('span', l(:text_zoom_in), :class => 'icon icon-zoom-in')
end end
when :out when :out
if gantt.zoom > 1 if gantt.zoom > 1
link_to_remote(l(:text_zoom_out), link_to_content_update l(:text_zoom_out),
{:url => gantt.params.merge(:zoom => (gantt.zoom-1)), :method => :get, :update => 'content'}, params.merge(gantt.params.merge(:zoom => (gantt.zoom-1))),
{:href => url_for(gantt.params.merge(:zoom => (gantt.zoom-1))), :class => 'icon icon-zoom-out'
:class => 'icon icon-zoom-out'})
else else
content_tag('span', l(:text_zoom_out), :class => 'icon icon-zoom-out') content_tag('span', l(:text_zoom_out), :class => 'icon icon-zoom-out')
end end
end end
end end
def number_of_issues_on_versions(gantt)
versions = gantt.events.collect {|event| (event.is_a? Version) ? event : nil}.compact
versions.sum {|v| v.fixed_issues.for_gantt.with_query(@query).count}
end
end end
+84 -24
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -54,20 +54,30 @@ module IssuesHelper
"<strong>#{@cached_label_assigned_to}</strong>: #{issue.assigned_to}<br />" + "<strong>#{@cached_label_assigned_to}</strong>: #{issue.assigned_to}<br />" +
"<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}" "<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
end end
def issue_heading(issue)
h("#{issue.tracker} ##{issue.id}")
end
def render_issue_subject_with_tree(issue) def render_issue_subject_with_tree(issue)
s = '' s = ''
issue.ancestors.each do |ancestor| ancestors = issue.root? ? [] : issue.ancestors.visible.all
ancestors.each do |ancestor|
s << '<div>' + content_tag('p', link_to_issue(ancestor)) s << '<div>' + content_tag('p', link_to_issue(ancestor))
end end
s << '<div>' + content_tag('h3', h(issue.subject)) s << '<div>'
s << '</div>' * (issue.ancestors.size + 1) 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 s
end end
def render_descendants_tree(issue) def render_descendants_tree(issue)
s = '<form><table class="list issues">' s = '<form><table class="list issues">'
issue_list(issue.descendants.sort_by(&:lft)) do |child, level| issue_list(issue.descendants.visible.sort_by(&:lft)) do |child, level|
s << content_tag('tr', s << content_tag('tr',
content_tag('td', check_box_tag("ids[]", child.id, false, :id => nil), :class => 'checkbox') + content_tag('td', check_box_tag("ids[]", child.id, false, :id => nil), :class => 'checkbox') +
content_tag('td', link_to_issue(child, :truncate => 60), :class => 'subject') + content_tag('td', link_to_issue(child, :truncate => 60), :class => 'subject') +
@@ -79,7 +89,7 @@ module IssuesHelper
s << '</form></table>' s << '</form></table>'
s s
end end
def render_custom_fields_rows(issue) def render_custom_fields_rows(issue)
return if issue.custom_field_values.empty? return if issue.custom_field_values.empty?
ordered_values = [] ordered_values = []
@@ -98,21 +108,58 @@ module IssuesHelper
s << "</tr>\n" s << "</tr>\n"
s s
end 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 def sidebar_queries
unless @sidebar_queries unless @sidebar_queries
# User can see public queries and his own queries # User can see public queries and his own queries
visible = ARCondition.new(["is_public = ? OR user_id = ?", true, (User.current.logged? ? User.current.id : 0)]) visible = ARCondition.new(["is_public = ? OR user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
# Project specific queries and global queries # Project specific queries and global queries
visible << (@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id]) visible << (@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id])
@sidebar_queries = Query.find(:all, @sidebar_queries = Query.find(:all,
:select => 'id, name', :select => 'id, name, is_public',
:order => "name ASC", :order => "name ASC",
:conditions => visible.conditions) :conditions => visible.conditions)
end end
@sidebar_queries @sidebar_queries
end end
def query_links(title, queries)
# links to #index on issues/show
url_params = controller_name == 'issues' ? {:controller => 'issues', :action => 'index', :project_id => @project} : params
content_tag('h3', title) +
queries.collect {|query|
link_to(h(query.name), url_params.merge(:query_id => query))
}.join('<br />')
end
def render_sidebar_queries
out = ''
queries = sidebar_queries.select {|q| !q.is_public?}
out << query_links(l(:label_my_queries), queries) if queries.any?
queries = sidebar_queries.select {|q| q.is_public?}
out << query_links(l(:label_query_plural), queries) if queries.any?
out
end
def show_detail(detail, no_html=false) def show_detail(detail, no_html=false)
case detail.property case detail.property
when 'attr' when 'attr'
@@ -135,6 +182,10 @@ module IssuesHelper
label = l(:field_parent_issue) label = l(:field_parent_issue)
value = "##{detail.value}" unless detail.value.blank? value = "##{detail.value}" unless detail.value.blank?
old_value = "##{detail.old_value}" unless detail.old_value.blank? old_value = "##{detail.old_value}" unless detail.old_value.blank?
when detail.prop_key == '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 end
when 'cf' when 'cf'
custom_field = CustomField.find_by_id(detail.prop_key) custom_field = CustomField.find_by_id(detail.prop_key)
@@ -151,7 +202,7 @@ module IssuesHelper
label ||= detail.prop_key label ||= detail.prop_key
value ||= detail.value value ||= detail.value
old_value ||= detail.old_value old_value ||= detail.old_value
unless no_html unless no_html
label = content_tag('strong', label) label = content_tag('strong', label)
old_value = content_tag("i", h(old_value)) if detail.old_value old_value = content_tag("i", h(old_value)) if detail.old_value
@@ -163,8 +214,17 @@ module IssuesHelper
value = content_tag("i", h(value)) if value value = content_tag("i", h(value)) if value
end end
end end
if !detail.value.blank? 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},
:title => l(:label_view_diff)
s << " (#{ diff_link })"
end
s
elsif !detail.value.blank?
case detail.property case detail.property
when 'attr', 'cf' when 'attr', 'cf'
if !detail.old_value.blank? if !detail.old_value.blank?
@@ -188,7 +248,7 @@ module IssuesHelper
return record.name if record return record.name if record
end end
end end
# Renders issue children recursively # Renders issue children recursively
def render_api_issue_children(issue, api) def render_api_issue_children(issue, api)
return if issue.leaf? return if issue.leaf?
@@ -202,14 +262,14 @@ module IssuesHelper
end end
end end
end end
def issues_to_csv(issues, project = nil) def issues_to_csv(issues, project = nil)
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8') ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
decimal_separator = l(:general_csv_decimal_separator) decimal_separator = l(:general_csv_decimal_separator)
export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv| export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
# csv header fields # csv header fields
headers = [ "#", headers = [ "#",
l(:field_status), l(:field_status),
l(:field_project), l(:field_project),
l(:field_tracker), l(:field_tracker),
l(:field_priority), l(:field_priority),
@@ -236,9 +296,9 @@ module IssuesHelper
# csv lines # csv lines
issues.each do |issue| issues.each do |issue|
fields = [issue.id, fields = [issue.id,
issue.status.name, issue.status.name,
issue.project.name, issue.project.name,
issue.tracker.name, issue.tracker.name,
issue.priority.name, issue.priority.name,
issue.subject, issue.subject,
issue.assigned_to, issue.assigned_to,
@@ -250,7 +310,7 @@ module IssuesHelper
issue.done_ratio, issue.done_ratio,
issue.estimated_hours.to_s.gsub('.', decimal_separator), issue.estimated_hours.to_s.gsub('.', decimal_separator),
issue.parent_id, issue.parent_id,
format_time(issue.created_on), format_time(issue.created_on),
format_time(issue.updated_on) format_time(issue.updated_on)
] ]
custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) } custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) }
-10
View File
@@ -16,14 +16,4 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module MessagesHelper module MessagesHelper
def link_to_message(message)
return '' unless message
link_to h(truncate(message.subject, :length => 60)), :controller => 'messages',
:action => 'show',
:board_id => message.board_id,
:id => message.root,
:r => (message.parent_id && message.id),
:anchor => (message.parent_id ? "message-#{message.id}" : nil)
end
end end
+11 -11
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -20,7 +20,7 @@ module ProjectsHelper
return '' unless version && version.is_a?(Version) return '' unless version && version.is_a?(Version)
link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, options link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, options
end end
def project_settings_tabs def project_settings_tabs
tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural}, 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 => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
@@ -32,9 +32,9 @@ module ProjectsHelper
{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_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} {:name => 'activities', :action => :manage_project_activities, :partial => 'projects/settings/activities', :label => :enumeration_activities}
] ]
tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)} tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)}
end end
def parent_project_select_tag(project) def parent_project_select_tag(project)
selected = project.parent selected = project.parent
# retrieve the requested parent project # retrieve the requested parent project
@@ -42,13 +42,13 @@ module ProjectsHelper
if parent_id if parent_id
selected = (parent_id.blank? ? nil : Project.find(parent_id)) selected = (parent_id.blank? ? nil : Project.find(parent_id))
end end
options = '' options = ''
options << "<option value=''></option>" if project.allowed_parents.include?(nil) options << "<option value=''></option>" if project.allowed_parents.include?(nil)
options << project_tree_options_for_select(project.allowed_parents.compact, :selected => selected) options << project_tree_options_for_select(project.allowed_parents.compact, :selected => selected)
content_tag('select', options, :name => 'project[parent_id]', :id => 'project_parent_id') content_tag('select', options, :name => 'project[parent_id]', :id => 'project_parent_id')
end end
# Renders a tree of projects as a nested set of unordered lists # Renders a tree of projects as a nested set of unordered lists
# The given collection may be a subset of the whole project tree # The given collection may be a subset of the whole project tree
# (eg. some intermediate nodes are private and can not be seen) # (eg. some intermediate nodes are private and can not be seen)
@@ -65,7 +65,7 @@ module ProjectsHelper
else else
ancestors.pop ancestors.pop
s << "</li>" s << "</li>"
while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
ancestors.pop ancestors.pop
s << "</ul></li>\n" s << "</ul></li>\n"
end end
@@ -93,7 +93,7 @@ module ProjectsHelper
if selected && !versions.include?(selected) if selected && !versions.include?(selected)
grouped[selected.project.name] << [selected.name, selected.id] grouped[selected.project.name] << [selected.name, selected.id]
end end
if grouped.keys.size > 1 if grouped.keys.size > 1
grouped_options_for_select(grouped, selected && selected.id) grouped_options_for_select(grouped, selected && selected.id)
else else
+6 -5
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -70,6 +70,7 @@ module QueriesHelper
cond = "project_id IS NULL" cond = "project_id IS NULL"
cond << " OR project_id = #{@project.id}" if @project cond << " OR project_id = #{@project.id}" if @project
@query = Query.find(params[:query_id], :conditions => cond) @query = Query.find(params[:query_id], :conditions => cond)
raise ::Unauthorized unless @query.visible?
@query.project = @project @query.project = @project
session[:query] = {:id => @query.id, :project_id => @query.project_id} session[:query] = {:id => @query.id, :project_id => @query.project_id}
sort_clear sort_clear
@@ -78,16 +79,16 @@ module QueriesHelper
# Give it a name, required to be valid # Give it a name, required to be valid
@query = Query.new(:name => "_") @query = Query.new(:name => "_")
@query.project = @project @query.project = @project
if params[:fields] if params[:fields] || params[:f]
@query.filters = {} @query.filters = {}
@query.add_filters(params[:fields], params[:operators], params[:values]) @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v])
else else
@query.available_filters.keys.each do |field| @query.available_filters.keys.each do |field|
@query.add_short_filter(field, params[field]) if params[field] @query.add_short_filter(field, params[field]) if params[field]
end end
end end
@query.group_by = params[:group_by] @query.group_by = params[:group_by]
@query.column_names = params[:query] && params[:query][:column_names] @query.column_names = params[:c] || (params[:query] && params[:query][:column_names])
session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names} session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
else else
@query = Query.find_by_id(session[:query][:id]) if session[:query][:id] @query = Query.find_by_id(session[:query][:id]) if session[:query][:id]
+7 -7
View File
@@ -1,22 +1,22 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ReportsHelper module ReportsHelper
def aggregate(data, criteria) def aggregate(data, criteria)
a = 0 a = 0
data.each { |row| data.each { |row|
@@ -28,9 +28,9 @@ module ReportsHelper
} unless data.nil? } unless data.nil?
a a
end end
def aggregate_link(data, criteria, *args) def aggregate_link(data, criteria, *args)
a = aggregate data, criteria a = aggregate data, criteria
a > 0 ? link_to(a, *args) : '-' a > 0 ? link_to(a, *args) : '-'
end end
end end
+141 -45
View File
@@ -1,33 +1,38 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'iconv' require 'iconv'
require 'redmine/codeset_util'
module RepositoriesHelper module RepositoriesHelper
def format_revision(txt) def format_revision(revision)
txt.to_s[0,8] if revision.respond_to? :format_identifier
revision.format_identifier
else
revision.to_s
end
end end
def truncate_at_line_break(text, length = 255) def truncate_at_line_break(text, length = 255)
if text if text
text.gsub(%r{^(.{#{length}}[^\n]*)\n.+$}m, '\\1...') text.gsub(%r{^(.{#{length}}[^\n]*)\n.+$}m, '\\1...')
end end
end end
def render_properties(properties) def render_properties(properties)
unless properties.nil? || properties.empty? unless properties.nil? || properties.empty?
content = '' content = ''
@@ -37,14 +42,15 @@ module RepositoriesHelper
content_tag('ul', content, :class => 'properties') content_tag('ul', content, :class => 'properties')
end end
end end
def render_changeset_changes def render_changeset_changes
changes = @changeset.changes.find(:all, :limit => 1000, :order => 'path').collect do |change| changes = @changeset.changes.find(:all, :limit => 1000, :order => 'path').collect do |change|
case change.action case change.action
when 'A' when 'A'
# Detects moved/copied files # Detects moved/copied files
if !change.from_path.blank? if !change.from_path.blank?
change.action = @changeset.changes.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C' change.action =
@changeset.changes.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C'
end end
change change
when 'D' when 'D'
@@ -52,8 +58,8 @@ module RepositoriesHelper
else else
change change
end end
end.compact end.compact
tree = { } tree = { }
changes.each do |change| changes.each do |change|
p = tree p = tree
@@ -68,13 +74,11 @@ module RepositoriesHelper
end end
p[:c] = change p[:c] = change
end end
render_changes_tree(tree[:s]) render_changes_tree(tree[:s])
end end
def render_changes_tree(tree) def render_changes_tree(tree)
return '' if tree.nil? return '' if tree.nil?
output = '' output = ''
output << '<ul>' output << '<ul>'
tree.keys.sort.each do |file| tree.keys.sort.each do |file|
@@ -87,7 +91,7 @@ module RepositoriesHelper
:action => 'show', :action => 'show',
:id => @project, :id => @project,
:path => path_param, :path => path_param,
:rev => @changeset.revision) :rev => @changeset.identifier)
output << "<li class='#{style}'>#{text}</li>" output << "<li class='#{style}'>#{text}</li>"
output << render_changes_tree(s) output << render_changes_tree(s)
elsif c = tree[file][:c] elsif c = tree[file][:c]
@@ -97,13 +101,13 @@ module RepositoriesHelper
:action => 'entry', :action => 'entry',
:id => @project, :id => @project,
:path => path_param, :path => path_param,
:rev => @changeset.revision) unless c.action == 'D' :rev => @changeset.identifier) unless c.action == 'D'
text << " - #{c.revision}" unless c.revision.blank? text << " - #{c.revision}" unless c.revision.blank?
text << ' (' + link_to('diff', :controller => 'repositories', text << ' (' + link_to('diff', :controller => 'repositories',
:action => 'diff', :action => 'diff',
:id => @project, :id => @project,
:path => path_param, :path => path_param,
:rev => @changeset.revision) + ') ' if c.action == 'M' :rev => @changeset.identifier) + ') ' if c.action == 'M'
text << ' ' + content_tag('span', c.from_path, :class => 'copied-from') unless c.from_path.blank? text << ' ' + content_tag('span', c.from_path, :class => 'copied-from') unless c.from_path.blank?
output << "<li class='#{style}'>#{text}</li>" output << "<li class='#{style}'>#{text}</li>"
end end
@@ -111,9 +115,26 @@ module RepositoriesHelper
output << '</ul>' output << '</ul>'
output output
end end
def to_utf8(str) def to_utf8(str)
return str if str.nil?
str = to_utf8_internal(str)
if str.respond_to?(:force_encoding)
str.force_encoding('UTF-8')
end
str
end
def to_utf8_internal(str)
return str if str.nil?
if str.respond_to?(:force_encoding)
str.force_encoding('ASCII-8BIT')
end
return str if str.empty?
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
if str.respond_to?(:force_encoding)
str.force_encoding('UTF-8')
end
@encodings ||= Setting.repositories_encodings.split(',').collect(&:strip) @encodings ||= Setting.repositories_encodings.split(',').collect(&:strip)
@encodings.each do |encoding| @encodings.each do |encoding|
begin begin
@@ -122,67 +143,142 @@ module RepositoriesHelper
# do nothing here and try the next encoding # do nothing here and try the next encoding
end end
end end
str str = Redmine::CodesetUtil.replace_invalid_utf8(str)
end end
private :to_utf8_internal
def repository_field_tags(form, repository)
def repository_field_tags(form, repository)
method = repository.class.name.demodulize.underscore + "_field_tags" method = repository.class.name.demodulize.underscore + "_field_tags"
send(method, form, repository) if repository.is_a?(Repository) && respond_to?(method) && method != 'repository_field_tags' if repository.is_a?(Repository) &&
respond_to?(method) && method != 'repository_field_tags'
send(method, form, repository)
end
end end
def scm_select_tag(repository) def scm_select_tag(repository)
scm_options = [["--- #{l(:actionview_instancetag_blank_option)} ---", '']] scm_options = [["--- #{l(:actionview_instancetag_blank_option)} ---", '']]
Redmine::Scm::Base.all.each do |scm| Redmine::Scm::Base.all.each do |scm|
scm_options << ["Repository::#{scm}".constantize.scm_name, scm] if Setting.enabled_scm.include?(scm) || (repository && repository.class.name.demodulize == scm) if Setting.enabled_scm.include?(scm) ||
(repository && repository.class.name.demodulize == scm)
scm_options << ["Repository::#{scm}".constantize.scm_name, scm]
end
end end
select_tag('repository_scm',
select_tag('repository_scm',
options_for_select(scm_options, repository.class.name.demodulize), options_for_select(scm_options, repository.class.name.demodulize),
:disabled => (repository && !repository.new_record?), :disabled => (repository && !repository.new_record?),
:onchange => remote_function(:url => { :controller => 'repositories', :action => 'edit', :id => @project }, :method => :get, :with => "Form.serialize(this.form)") :onchange => remote_function(
) :url => {
:controller => 'repositories',
:action => 'edit',
:id => @project
},
:method => :get,
:with => "Form.serialize(this.form)")
)
end end
def with_leading_slash(path) def with_leading_slash(path)
path.to_s.starts_with?('/') ? path : "/#{path}" path.to_s.starts_with?('/') ? path : "/#{path}"
end end
def without_leading_slash(path) def without_leading_slash(path)
path.gsub(%r{^/+}, '') path.gsub(%r{^/+}, '')
end end
def subversion_field_tags(form, repository) def subversion_field_tags(form, repository)
content_tag('p', form.text_field(:url, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) + content_tag('p', form.text_field(:url, :size => 60, :required => true,
:disabled => (repository && !repository.root_url.blank?)) +
'<br />(file:///, http://, https://, svn://, svn+[tunnelscheme]://)') + '<br />(file:///, http://, https://, svn://, svn+[tunnelscheme]://)') +
content_tag('p', form.text_field(:login, :size => 30)) + content_tag('p', form.text_field(:login, :size => 30)) +
content_tag('p', form.password_field(:password, :size => 30, :name => 'ignore', content_tag('p', form.password_field(
:value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)), :password, :size => 30, :name => 'ignore',
:onfocus => "this.value=''; this.name='repository[password]';", :value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)),
:onchange => "this.name='repository[password]';")) :onfocus => "this.value=''; this.name='repository[password]';",
:onchange => "this.name='repository[password]';"))
end end
def darcs_field_tags(form, repository) def darcs_field_tags(form, repository)
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.new_record?))) content_tag('p', form.text_field(
:url, :label => l(:field_path_to_repository),
:size => 60, :required => true,
:disabled => (repository && !repository.new_record?))) +
content_tag('p', form.select(
:log_encoding, [nil] + Setting::ENCODINGS,
:label => l(:field_commit_logs_encoding), :required => true))
end end
def mercurial_field_tags(form, repository) def mercurial_field_tags(form, repository)
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?))) content_tag('p', form.text_field(
:url, :label => l(:field_path_to_repository),
:size => 60, :required => true,
:disabled => (repository && !repository.root_url.blank?)
) +
'<br />' + l(:text_mercurial_repository_note)) +
content_tag('p', form.select(
:path_encoding, [nil] + Setting::ENCODINGS,
:label => l(:field_scm_path_encoding)
) +
'<br />' + l(:text_scm_path_encoding_note))
end end
def git_field_tags(form, repository) def git_field_tags(form, repository)
content_tag('p', form.text_field(:url, :label => 'Path to .git directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?))) content_tag('p', form.text_field(
:url, :label => l(:field_path_to_repository),
:size => 60, :required => true,
:disabled => (repository && !repository.root_url.blank?)
) +
'<br />' + l(:text_git_repository_note)) +
content_tag('p', form.select(
:path_encoding, [nil] + Setting::ENCODINGS,
:label => l(:field_scm_path_encoding)
) +
'<br />' + l(:text_scm_path_encoding_note)) +
content_tag('p', form.check_box(
:extra_report_last_commit,
:label => l(:label_git_report_last_commit)
))
end end
def cvs_field_tags(form, repository) def cvs_field_tags(form, repository)
content_tag('p', form.text_field(:root_url, :label => 'CVSROOT', :size => 60, :required => true, :disabled => !repository.new_record?)) + content_tag('p', form.text_field(
content_tag('p', form.text_field(:url, :label => 'Module', :size => 30, :required => true, :disabled => !repository.new_record?)) :root_url,
:label => l(:field_cvsroot),
:size => 60, :required => true,
:disabled => !repository.new_record?)) +
content_tag('p', form.text_field(
:url,
:label => l(:field_cvs_module),
:size => 30, :required => true,
:disabled => !repository.new_record?)) +
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 />' + l(:text_scm_path_encoding_note))
end end
def bazaar_field_tags(form, repository) def bazaar_field_tags(form, repository)
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.new_record?))) content_tag('p', form.text_field(
:url, :label => l(:field_path_to_repository),
:size => 60, :required => true,
:disabled => (repository && !repository.new_record?))) +
content_tag('p', form.select(
:log_encoding, [nil] + Setting::ENCODINGS,
:label => l(:field_commit_logs_encoding), :required => true))
end end
def filesystem_field_tags(form, repository) def filesystem_field_tags(form, repository)
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?))) content_tag('p', form.text_field(
:url, :label => l(:field_root_directory),
:size => 60, :required => true,
:disabled => (repository && !repository.root_url.blank?))) +
content_tag('p', form.select(
:path_encoding, [nil] + Setting::ENCODINGS,
:label => l(:field_scm_path_encoding)
) +
'<br />' + l(:text_scm_path_encoding_note))
end end
end end
+3 -3
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -57,7 +57,7 @@ module SearchHelper
c = results_by_type[t] c = results_by_type[t]
next if c == 0 next if c == 0
text = "#{type_label(t)} (#{c})" text = "#{type_label(t)} (#{c})"
links << link_to(text, :q => params[:q], :titles_only => params[:title_only], :all_words => params[:all_words], :scope => params[:scope], t => 1) links << link_to(text, :q => params[:q], :titles_only => params[:titles_only], :all_words => params[:all_words], :scope => params[:scope], t => 1)
end end
('<ul>' + links.map {|link| content_tag('li', link)}.join(' ') + '</ul>') unless links.empty? ('<ul>' + links.map {|link| content_tag('li', link)}.join(' ') + '</ul>') unless links.empty?
end end
+23 -16
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2009 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -27,46 +27,53 @@ module SettingsHelper
{:name => 'repositories', :partial => 'settings/repositories', :label => :label_repository_plural} {:name => 'repositories', :partial => 'settings/repositories', :label => :label_repository_plural}
] ]
end end
def setting_select(setting, choices, options={}) def setting_select(setting, choices, options={})
if blank_text = options.delete(:blank) if blank_text = options.delete(:blank)
choices = [[blank_text.is_a?(Symbol) ? l(blank_text) : blank_text, '']] + choices choices = [[blank_text.is_a?(Symbol) ? l(blank_text) : blank_text, '']] + choices
end end
setting_label(setting, options) + setting_label(setting, options) +
select_tag("settings[#{setting}]", options_for_select(choices, Setting.send(setting).to_s), options) select_tag("settings[#{setting}]",
options_for_select(choices, Setting.send(setting).to_s),
options)
end end
def setting_multiselect(setting, choices, options={}) def setting_multiselect(setting, choices, options={})
setting_values = Setting.send(setting) setting_values = Setting.send(setting)
setting_values = [] unless setting_values.is_a?(Array) setting_values = [] unless setting_values.is_a?(Array)
setting_label(setting, options) + setting_label(setting, options) +
hidden_field_tag("settings[#{setting}][]", '') + hidden_field_tag("settings[#{setting}][]", '') +
choices.collect do |choice| choices.collect do |choice|
text, value = (choice.is_a?(Array) ? choice : [choice, choice]) text, value = (choice.is_a?(Array) ? choice : [choice, choice])
content_tag('label', content_tag(
check_box_tag("settings[#{setting}][]", value, Setting.send(setting).include?(value)) + text.to_s, 'label',
check_box_tag(
"settings[#{setting}][]",
value,
Setting.send(setting).include?(value)
) + text.to_s,
:class => 'block' :class => 'block'
) )
end.join end.join
end end
def setting_text_field(setting, options={}) def setting_text_field(setting, options={})
setting_label(setting, options) + setting_label(setting, options) +
text_field_tag("settings[#{setting}]", Setting.send(setting), options) text_field_tag("settings[#{setting}]", Setting.send(setting), options)
end end
def setting_text_area(setting, options={}) def setting_text_area(setting, options={})
setting_label(setting, options) + setting_label(setting, options) +
text_area_tag("settings[#{setting}]", Setting.send(setting), options) text_area_tag("settings[#{setting}]", Setting.send(setting), options)
end end
def setting_check_box(setting, options={}) def setting_check_box(setting, options={})
setting_label(setting, options) + setting_label(setting, options) +
hidden_field_tag("settings[#{setting}]", 0) + hidden_field_tag("settings[#{setting}]", 0) +
check_box_tag("settings[#{setting}]", 1, Setting.send("#{setting}?"), options) check_box_tag("settings[#{setting}]", 1, Setting.send("#{setting}?"), options)
end end
def setting_label(setting, options={}) def setting_label(setting, options={})
label = options.delete(:label) label = options.delete(:label)
label != false ? content_tag("label", l(label || "setting_#{setting}")) : '' label != false ? content_tag("label", l(label || "setting_#{setting}")) : ''
+2 -6
View File
@@ -200,16 +200,12 @@ module SortHelper
caption = column.to_s.humanize unless caption caption = column.to_s.humanize unless caption
sort_options = { :sort => @sort_criteria.add(column.to_s, order).to_param } sort_options = { :sort => @sort_criteria.add(column.to_s, order).to_param }
# don't reuse params if filters are present url_options = params.merge(sort_options)
url_options = params.has_key?(:set_filter) ? sort_options : params.merge(sort_options)
# Add project_id to url_options # Add project_id to url_options
url_options = url_options.merge(:project_id => params[:project_id]) if params.has_key?(:project_id) url_options = url_options.merge(:project_id => params[:project_id]) if params.has_key?(:project_id)
link_to_remote(caption, link_to_content_update(caption, url_options, :class => css)
{:update => "content", :url => url_options, :method => :get},
{:href => url_for(url_options),
:class => css})
end end
# Returns a table header <th> tag with a sort link for the named column # Returns a table header <th> tag with a sort link for the named column
+4 -5
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -17,11 +17,10 @@
module VersionsHelper module VersionsHelper
STATUS_BY_CRITERIAS = %w(category tracker priority author assigned_to) STATUS_BY_CRITERIAS = %w(category tracker status priority author assigned_to)
def render_issue_status_by(version, criteria) def render_issue_status_by(version, criteria)
criteria ||= 'category' criteria = 'category' unless STATUS_BY_CRITERIAS.include?(criteria)
raise 'Unknown criteria' unless STATUS_BY_CRITERIAS.include?(criteria)
h = Hash.new {|k,v| k[v] = [0, 0]} h = Hash.new {|k,v| k[v] = [0, 0]}
begin begin
+12 -17
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -16,28 +16,18 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module WatchersHelper module WatchersHelper
# Valid options def watcher_tag(object, user, options={})
# * :id - the element id content_tag("span", watcher_link(object, user), :class => watcher_css(object))
# * :replace - a string or array of element ids that will be
# replaced
def watcher_tag(object, user, options={:replace => 'watcher'})
id = options[:id]
id ||= options[:replace] if options[:replace].is_a? String
content_tag("span", watcher_link(object, user, options), :id => id)
end end
# Valid options def watcher_link(object, user)
# * :replace - a string or array of element ids that will be
# replaced
def watcher_link(object, user, options={:replace => 'watcher'})
return '' unless user && user.logged? && object.respond_to?('watched_by?') return '' unless user && user.logged? && object.respond_to?('watched_by?')
watched = object.watched_by?(user) watched = object.watched_by?(user)
url = {:controller => 'watchers', url = {:controller => 'watchers',
:action => (watched ? 'unwatch' : 'watch'), :action => (watched ? 'unwatch' : 'watch'),
:object_type => object.class.to_s.underscore, :object_type => object.class.to_s.underscore,
:object_id => object.id, :object_id => object.id}
:replace => options[:replace]}
link_to_remote((watched ? l(:button_unwatch) : l(:button_watch)), link_to_remote((watched ? l(:button_unwatch) : l(:button_watch)),
{:url => url}, {:url => url},
:href => url_for(url), :href => url_for(url),
@@ -45,6 +35,11 @@ module WatchersHelper
end end
# Returns the css class used to identify watch links for a given +object+
def watcher_css(object)
"#{object.class.to_s.underscore}-#{object.id}-watcher"
end
# Returns a comma separated list of users watching the given object # Returns a comma separated list of users watching the given object
def watchers_list(object) def watchers_list(object)
remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project) remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
+12 -46
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -18,52 +18,18 @@
module WikiHelper module WikiHelper
def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0) def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0)
pages = pages.group_by(&:parent) unless pages.is_a?(Hash)
s = '' s = ''
pages.select {|p| p.parent == parent}.each do |page| if pages.has_key?(parent)
attrs = "value='#{page.id}'" pages[parent].each do |page|
attrs << " selected='selected'" if selected == page attrs = "value='#{page.id}'"
indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : nil attrs << " selected='selected'" if selected == page
indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : nil
s << "<option #{attrs}>#{indent}#{h page.pretty_title}</option>\n" +
wiki_page_options_for_select(pages, selected, page, level + 1) s << "<option #{attrs}>#{indent}#{h page.pretty_title}</option>\n" +
wiki_page_options_for_select(pages, selected, page, level + 1)
end
end end
s s
end end
def html_diff(wdiff)
words = wdiff.words.collect{|word| h(word)}
words_add = 0
words_del = 0
dels = 0
del_off = 0
wdiff.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 << ' ' + h(change[2])
words_del += 1
end
end
if add_at
words[add_at] = '<span class="diff_in">' + words[add_at]
words[add_to] = words[add_to] + '</span>'
end
if del_at
words.insert del_at - del_off + dels + words_add, '<span class="diff_out">' + deleted + '</span>'
dels += 1
del_off += words_del
words_del = 0
end
end
simple_format_without_paragraph(words.join(' '))
end
end end
+23 -23
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -20,7 +20,7 @@ require "digest/md5"
class Attachment < ActiveRecord::Base class Attachment < ActiveRecord::Base
belongs_to :container, :polymorphic => true belongs_to :container, :polymorphic => true
belongs_to :author, :class_name => "User", :foreign_key => "author_id" belongs_to :author, :class_name => "User", :foreign_key => "author_id"
validates_presence_of :container, :filename, :author validates_presence_of :container, :filename, :author
validates_length_of :filename, :maximum => 255 validates_length_of :filename, :maximum => 255
validates_length_of :disk_filename, :maximum => 255 validates_length_of :disk_filename, :maximum => 255
@@ -31,20 +31,20 @@ class Attachment < ActiveRecord::Base
acts_as_activity_provider :type => 'files', acts_as_activity_provider :type => 'files',
:permission => :view_files, :permission => :view_files,
:author_key => :author_id, :author_key => :author_id,
:find_options => {:select => "#{Attachment.table_name}.*", :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 " + :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 )"} "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', acts_as_activity_provider :type => 'documents',
:permission => :view_documents, :permission => :view_documents,
:author_key => :author_id, :author_key => :author_id,
:find_options => {:select => "#{Attachment.table_name}.*", :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 " + :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"} "LEFT JOIN #{Project.table_name} ON #{Document.table_name}.project_id = #{Project.table_name}.id"}
cattr_accessor :storage_path cattr_accessor :storage_path
@@storage_path = "#{RAILS_ROOT}/files" @@storage_path = Redmine::Configuration['attachments_storage_path'] || "#{RAILS_ROOT}/files"
def validate def validate
if self.filesize > Setting.attachment_max_size.to_i.kilobytes if self.filesize > Setting.attachment_max_size.to_i.kilobytes
errors.add(:base, :too_long, :count => Setting.attachment_max_size.to_i.kilobytes) errors.add(:base, :too_long, :count => Setting.attachment_max_size.to_i.kilobytes)
@@ -76,7 +76,7 @@ class Attachment < ActiveRecord::Base
if @temp_file && (@temp_file.size > 0) if @temp_file && (@temp_file.size > 0)
logger.debug("saving '#{self.diskfile}'") logger.debug("saving '#{self.diskfile}'")
md5 = Digest::MD5.new md5 = Digest::MD5.new
File.open(diskfile, "wb") do |f| File.open(diskfile, "wb") do |f|
buffer = "" buffer = ""
while (buffer = @temp_file.read(8192)) while (buffer = @temp_file.read(8192))
f.write(buffer) f.write(buffer)
@@ -100,7 +100,7 @@ class Attachment < ActiveRecord::Base
def diskfile def diskfile
"#{@@storage_path}/#{self.disk_filename}" "#{@@storage_path}/#{self.disk_filename}"
end end
def increment_download def increment_download
increment!(:downloads) increment!(:downloads)
end end
@@ -108,27 +108,27 @@ class Attachment < ActiveRecord::Base
def project def project
container.project container.project
end end
def visible?(user=User.current) def visible?(user=User.current)
container.attachments_visible?(user) container.attachments_visible?(user)
end end
def deletable?(user=User.current) def deletable?(user=User.current)
container.attachments_deletable?(user) container.attachments_deletable?(user)
end end
def image? def image?
self.filename =~ /\.(jpe?g|gif|png)$/i self.filename =~ /\.(jpe?g|gif|png)$/i
end end
def is_text? def is_text?
Redmine::MimeType.is_type?('text', filename) Redmine::MimeType.is_type?('text', filename)
end end
def is_diff? def is_diff?
self.filename =~ /\.(patch|diff)$/i self.filename =~ /\.(patch|diff)$/i
end end
# Returns true if the file is readable # Returns true if the file is readable
def readable? def readable?
File.readable?(diskfile) File.readable?(diskfile)
@@ -145,7 +145,7 @@ class Attachment < ActiveRecord::Base
attachments.each_value do |attachment| attachments.each_value do |attachment|
file = attachment['file'] file = attachment['file']
next unless file && file.size > 0 next unless file && file.size > 0
a = Attachment.create(:container => obj, a = Attachment.create(:container => obj,
:file => file, :file => file,
:description => attachment['description'].to_s.strip, :description => attachment['description'].to_s.strip,
:author => User.current) :author => User.current)
@@ -160,18 +160,18 @@ class Attachment < ActiveRecord::Base
end end
{:files => attached, :unsaved => obj.unsaved_attachments} {:files => attached, :unsaved => obj.unsaved_attachments}
end end
private private
def sanitize_filename(value) def sanitize_filename(value)
# get only the filename, not the whole path # get only the filename, not the whole path
just_filename = value.gsub(/^.*(\\|\/)/, '') just_filename = value.gsub(/^.*(\\|\/)/, '')
# NOTE: File.basename doesn't work right with Windows paths on Unix # NOTE: File.basename doesn't work right with Windows paths on Unix
# INCORRECT: just_filename = File.basename(value.gsub('\\\\', '/')) # INCORRECT: just_filename = File.basename(value.gsub('\\\\', '/'))
# Finally, replace all non alphanumeric, hyphens or periods with underscore # Finally, replace all non alphanumeric, hyphens or periods with underscore
@filename = just_filename.gsub(/[^\w\.\-]/,'_') @filename = just_filename.gsub(/[^\w\.\-]/,'_')
end end
# Returns an ASCII or hashed filename # Returns an ASCII or hashed filename
def self.disk_filename(filename) def self.disk_filename(filename)
timestamp = DateTime.now.strftime("%y%m%d%H%M%S") timestamp = DateTime.now.strftime("%y%m%d%H%M%S")
+10
View File
@@ -16,6 +16,8 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AuthSource < ActiveRecord::Base class AuthSource < ActiveRecord::Base
include Redmine::Ciphering
has_many :users has_many :users
validates_presence_of :name validates_presence_of :name
@@ -31,6 +33,14 @@ class AuthSource < ActiveRecord::Base
def auth_method_name def auth_method_name
"Abstract" "Abstract"
end end
def account_password
read_ciphered_attribute(:account_password)
end
def account_password=(arg)
write_ciphered_attribute(:account_password, arg)
end
def allow_password_changes? def allow_password_changes?
self.class.allow_password_changes? self.class.allow_password_changes?
+2 -2
View File
@@ -20,8 +20,8 @@ require 'iconv'
class AuthSourceLdap < AuthSource class AuthSourceLdap < AuthSource
validates_presence_of :host, :port, :attr_login validates_presence_of :host, :port, :attr_login
validates_length_of :name, :host, :account_password, :maximum => 60, :allow_nil => true validates_length_of :name, :host, :maximum => 60, :allow_nil => true
validates_length_of :account, :base_dn, :maximum => 255, :allow_nil => true validates_length_of :account, :account_password, :base_dn, :maximum => 255, :allow_nil => true
validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => 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 :port, :only_integer => true
+12 -7
View File
@@ -1,30 +1,35 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Change < ActiveRecord::Base class Change < ActiveRecord::Base
belongs_to :changeset belongs_to :changeset
validates_presence_of :changeset_id, :action, :path validates_presence_of :changeset_id, :action, :path
before_save :init_path before_save :init_path
def relative_path def relative_path
changeset.repository.relative_path(path) changeset.repository.relative_path(path)
end end
def before_validation
self.path = Redmine::CodesetUtil.replace_invalid_utf8(self.path)
self.from_path = Redmine::CodesetUtil.replace_invalid_utf8(self.from_path)
end
def init_path def init_path
self.path ||= "" self.path ||= ""
end end
+114 -70
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2010 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -23,70 +23,85 @@ class Changeset < ActiveRecord::Base
has_many :changes, :dependent => :delete_all has_many :changes, :dependent => :delete_all
has_and_belongs_to_many :issues has_and_belongs_to_many :issues
acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.revision}" + (o.short_comments.blank? ? '' : (': ' + o.short_comments))}, acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.format_identifier}" + (o.short_comments.blank? ? '' : (': ' + o.short_comments))},
:description => :long_comments, :description => :long_comments,
:datetime => :committed_on, :datetime => :committed_on,
:url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :rev => o.revision}} :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :rev => o.identifier}}
acts_as_searchable :columns => 'comments', acts_as_searchable :columns => 'comments',
:include => {:repository => :project}, :include => {:repository => :project},
:project_key => "#{Repository.table_name}.project_id", :project_key => "#{Repository.table_name}.project_id",
:date_column => 'committed_on' :date_column => 'committed_on'
acts_as_activity_provider :timestamp => "#{table_name}.committed_on", acts_as_activity_provider :timestamp => "#{table_name}.committed_on",
:author_key => :user_id, :author_key => :user_id,
:find_options => {:include => [:user, {:repository => :project}]} :find_options => {:include => [:user, {:repository => :project}]}
validates_presence_of :repository_id, :revision, :committed_on, :commit_date validates_presence_of :repository_id, :revision, :committed_on, :commit_date
validates_uniqueness_of :revision, :scope => :repository_id validates_uniqueness_of :revision, :scope => :repository_id
validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
named_scope :visible, lambda {|*args| { :include => {:repository => :project}, named_scope :visible, lambda {|*args| { :include => {:repository => :project},
:conditions => Project.allowed_to_condition(args.first || User.current, :view_changesets) } } :conditions => Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args) } }
def revision=(r) def revision=(r)
write_attribute :revision, (r.nil? ? nil : r.to_s) write_attribute :revision, (r.nil? ? nil : r.to_s)
end end
def comments=(comment) # Returns the identifier of this changeset; depending on repository backends
write_attribute(:comments, Changeset.normalize_comments(comment)) def identifier
if repository.class.respond_to? :changeset_identifier
repository.class.changeset_identifier self
else
revision.to_s
end
end end
def committed_on=(date) def committed_on=(date)
self.commit_date = date self.commit_date = date
super super
end end
def committer=(arg) # Returns the readable identifier
write_attribute(:committer, self.class.to_utf8(arg.to_s)) def format_identifier
if repository.class.respond_to? :format_changeset_identifier
repository.class.format_changeset_identifier self
else
identifier
end
end end
def project def project
repository.project repository.project
end end
def author def author
user || committer.to_s.split('<').first user || committer.to_s.split('<').first
end end
def before_create def before_create
self.user = repository.find_committer_user(committer) 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 end
def after_create def after_create
scan_comment_for_issue_ids scan_comment_for_issue_ids
end end
TIMELOG_RE = / TIMELOG_RE = /
( (
(\d+([.,]\d+)?)h? ((\d+)(h|hours?))((\d+)(m|min)?)?
|
((\d+)(h|hours?|m|min))
| |
(\d+):(\d+) (\d+):(\d+)
| |
((\d+)(h|hours?))?((\d+)(m|min)?)? (\d+([\.,]\d+)?)h?
) )
/x /x
def scan_comment_for_issue_ids def scan_comment_for_issue_ids
return if comments.blank? return if comments.blank?
# keywords used to reference issues # keywords used to reference issues
@@ -94,15 +109,15 @@ class Changeset < ActiveRecord::Base
ref_keywords_any = ref_keywords.delete('*') ref_keywords_any = ref_keywords.delete('*')
# keywords used to fix issues # keywords used to fix issues
fix_keywords = Setting.commit_fix_keywords.downcase.split(",").collect(&:strip) fix_keywords = Setting.commit_fix_keywords.downcase.split(",").collect(&:strip)
kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|") kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|")
referenced_issues = [] referenced_issues = []
comments.scan(/([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)/i) do |match| comments.scan(/([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)/i) do |match|
action, refs = match[2], match[3] action, refs = match[2], match[3]
next unless action.present? || ref_keywords_any next unless action.present? || ref_keywords_any
refs.scan(/#(\d+)(\s+@#{TIMELOG_RE})?/).each do |m| refs.scan(/#(\d+)(\s+@#{TIMELOG_RE})?/).each do |m|
issue, hours = find_referenced_issue_by_id(m[0].to_i), m[2] issue, hours = find_referenced_issue_by_id(m[0].to_i), m[2]
if issue if issue
@@ -112,15 +127,15 @@ class Changeset < ActiveRecord::Base
end end
end end
end end
referenced_issues.uniq! referenced_issues.uniq!
self.issues = referenced_issues unless referenced_issues.empty? self.issues = referenced_issues unless referenced_issues.empty?
end end
def short_comments def short_comments
@short_comments || split_comments.first @short_comments || split_comments.first
end end
def long_comments def long_comments
@long_comments || split_comments.last @long_comments || split_comments.last
end end
@@ -132,31 +147,32 @@ class Changeset < ActiveRecord::Base
"r#{revision}" "r#{revision}"
end end
end end
# Returns the previous changeset # Returns the previous changeset
def previous def previous
@previous ||= Changeset.find(:first, :conditions => ['id < ? AND repository_id = ?', self.id, self.repository_id], :order => 'id DESC') @previous ||= Changeset.find(:first,
:conditions => ['id < ? AND repository_id = ?',
self.id, self.repository_id],
:order => 'id DESC')
end end
# Returns the next changeset # Returns the next changeset
def next def next
@next ||= Changeset.find(:first, :conditions => ['id > ? AND repository_id = ?', self.id, self.repository_id], :order => 'id ASC') @next ||= Changeset.find(:first,
end :conditions => ['id > ? AND repository_id = ?',
self.id, self.repository_id],
# Strips and reencodes a commit log before insertion into the database :order => 'id ASC')
def self.normalize_comments(str)
to_utf8(str.to_s.strip)
end end
# Creates a new Change from it's common parameters # Creates a new Change from it's common parameters
def create_change(change) def create_change(change)
Change.create(:changeset => self, Change.create(:changeset => self,
:action => change[:action], :action => change[:action],
:path => change[:path], :path => change[:path],
:from_path => change[:from_path], :from_path => change[:from_path],
:from_revision => change[:from_revision]) :from_revision => change[:from_revision])
end end
private private
# Finds an issue that can be referenced by the commit message # Finds an issue that can be referenced by the commit message
@@ -165,25 +181,27 @@ class Changeset < ActiveRecord::Base
return nil if id.blank? return nil if id.blank?
issue = Issue.find_by_id(id.to_i, :include => :project) issue = Issue.find_by_id(id.to_i, :include => :project)
if issue if issue
unless project == issue.project || project.is_ancestor_of?(issue.project) || project.is_descendant_of?(issue.project) unless issue.project &&
(project == issue.project || project.is_ancestor_of?(issue.project) ||
project.is_descendant_of?(issue.project))
issue = nil issue = nil
end end
end end
issue issue
end end
def fix_issue(issue) def fix_issue(issue)
status = IssueStatus.find_by_id(Setting.commit_fix_status_id.to_i) status = IssueStatus.find_by_id(Setting.commit_fix_status_id.to_i)
if status.nil? if status.nil?
logger.warn("No status macthes commit_fix_status_id setting (#{Setting.commit_fix_status_id})") if logger logger.warn("No status matches commit_fix_status_id setting (#{Setting.commit_fix_status_id})") if logger
return issue return issue
end end
# the issue may have been updated by the closure of another one (eg. duplicate) # the issue may have been updated by the closure of another one (eg. duplicate)
issue.reload issue.reload
# don't change the status is the issue is closed # don't change the status is the issue is closed
return if issue.status && issue.status.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)) journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag))
issue.status = status issue.status = status
unless Setting.commit_fix_done_ratio.blank? unless Setting.commit_fix_done_ratio.blank?
@@ -196,29 +214,30 @@ class Changeset < ActiveRecord::Base
end end
issue issue
end end
def log_time(issue, hours) def log_time(issue, hours)
time_entry = TimeEntry.new( time_entry = TimeEntry.new(
:user => user, :user => user,
:hours => hours, :hours => hours,
:issue => issue, :issue => issue,
:spent_on => commit_date, :spent_on => commit_date,
:comments => l(:text_time_logged_by_changeset, :value => text_tag, :locale => Setting.default_language) :comments => l(:text_time_logged_by_changeset, :value => text_tag,
:locale => Setting.default_language)
) )
time_entry.activity = log_time_activity unless log_time_activity.nil? time_entry.activity = log_time_activity unless log_time_activity.nil?
unless time_entry.save unless time_entry.save
logger.warn("TimeEntry could not be created by changeset #{id}: #{time_entry.errors.full_messages}") if logger logger.warn("TimeEntry could not be created by changeset #{id}: #{time_entry.errors.full_messages}") if logger
end end
time_entry time_entry
end end
def log_time_activity def log_time_activity
if Setting.commit_logtime_activity_id.to_i > 0 if Setting.commit_logtime_activity_id.to_i > 0
TimeEntryActivity.find_by_id(Setting.commit_logtime_activity_id.to_i) TimeEntryActivity.find_by_id(Setting.commit_logtime_activity_id.to_i)
end end
end end
def split_comments def split_comments
comments =~ /\A(.+?)\r?\n(.*)$/m comments =~ /\A(.+?)\r?\n(.*)$/m
@short_comments = $1 || comments @short_comments = $1 || comments
@@ -226,22 +245,47 @@ class Changeset < ActiveRecord::Base
return @short_comments, @long_comments return @short_comments, @long_comments
end end
def self.to_utf8(str) public
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
encoding = Setting.commit_logs_encoding.to_s.strip # Strips and reencodes a commit log before insertion into the database
unless encoding.blank? || encoding == 'UTF-8' def self.normalize_comments(str, encoding)
begin Changeset.to_utf8(str.to_s.strip, encoding)
str = Iconv.conv('UTF-8', encoding, str) end
rescue Iconv::Failure
# do nothing here def self.to_utf8(str, encoding)
return str if str.nil?
str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
if str.empty?
str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
return str
end
enc = encoding.blank? ? "UTF-8" : encoding
if str.respond_to?(:force_encoding)
if enc.upcase != "UTF-8"
str.force_encoding(enc)
str = str.encode("UTF-8", :invalid => :replace,
:undef => :replace, :replace => '?')
else
str.force_encoding("UTF-8")
if ! str.valid_encoding?
str = str.encode("US-ASCII", :invalid => :replace,
:undef => :replace, :replace => '?').encode("UTF-8")
end
end end
else
ic = Iconv.new('UTF-8', enc)
txtar = ""
begin
txtar += ic.iconv(str)
rescue Iconv::IllegalSequence
txtar += $!.success
str = '?' + $!.failed[1,$!.failed.length]
retry
rescue
txtar += $!.success
end
str = txtar
end end
# removes invalid UTF8 sequences str
begin
Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3]
rescue Iconv::InvalidEncoding
# "UTF-8//IGNORE" is not supported on some OS
str
end
end end
end end
+24
View File
@@ -0,0 +1,24 @@
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public 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 CommentObserver < ActiveRecord::Observer
def after_create(comment)
if comment.commented.is_a?(News) && Setting.notified_events.include?('news_comment_added')
Mailer.deliver_news_comment_added(comment)
end
end
end
+41 -3
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -23,7 +23,6 @@ class CustomField < ActiveRecord::Base
validates_presence_of :name, :field_format validates_presence_of :name, :field_format
validates_uniqueness_of :name, :scope => :type validates_uniqueness_of :name, :scope => :type
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
validates_format_of :name, :with => /^[\w\s\.\'\-]*$/i
validates_inclusion_of :field_format, :in => Redmine::CustomFieldFormat.available_formats validates_inclusion_of :field_format, :in => Redmine::CustomFieldFormat.available_formats
def initialize(attributes = nil) def initialize(attributes = nil)
@@ -43,12 +42,49 @@ class CustomField < ActiveRecord::Base
errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array
end end
if regexp.present?
begin
Regexp.new(regexp)
rescue
errors.add(:regexp, :invalid)
end
end
# validate default value # validate default value
v = CustomValue.new(:custom_field => self.clone, :value => default_value, :customized => nil) v = CustomValue.new(:custom_field => self.clone, :value => default_value, :customized => nil)
v.custom_field.is_required = false v.custom_field.is_required = false
errors.add(:default_value, :invalid) unless v.valid? errors.add(:default_value, :invalid) unless v.valid?
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)}.inject {|memo, v| memo & v}
else
[]
end
else
read_attribute :possible_values
end
end
def possible_values(obj=nil)
case field_format
when 'user', 'version'
possible_values_options(obj).collect(&:last)
else
read_attribute :possible_values
end
end
# Makes possible_values accept a multiline string # Makes possible_values accept a multiline string
def possible_values=(arg) def possible_values=(arg)
if arg.is_a?(Array) if arg.is_a?(Array)
@@ -72,6 +108,8 @@ class CustomField < ActiveRecord::Base
casted = value.to_i casted = value.to_i
when 'float' when 'float'
casted = value.to_f casted = value.to_f
when 'user', 'version'
casted = (value.blank? ? nil : field_format.classify.constantize.find_by_id(value.to_i))
end end
end end
casted casted
+1 -1
View File
@@ -62,7 +62,7 @@ protected
when 'float' when 'float'
begin; Kernel.Float(value); rescue; errors.add(:value, :invalid) end begin; Kernel.Float(value); rescue; errors.add(:value, :invalid) end
when 'date' when 'date'
errors.add(:value, :not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ errors.add(:value, :not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ && begin; value.to_date; rescue; false end
when 'list' when 'list'
errors.add(:value, :inclusion) unless custom_field.possible_values.include?(value) errors.add(:value, :inclusion) unless custom_field.possible_values.include?(value)
end end
+11 -8
View File
@@ -1,16 +1,16 @@
# redMine - project management software # RedMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -25,20 +25,23 @@ class Document < ActiveRecord::Base
:author => Proc.new {|o| (a = o.attachments.find(:first, :order => "#{Attachment.table_name}.created_on ASC")) ? a.author : nil }, :author => Proc.new {|o| (a = o.attachments.find(:first, :order => "#{Attachment.table_name}.created_on ASC")) ? a.author : nil },
:url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}} :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
acts_as_activity_provider :find_options => {:include => :project} acts_as_activity_provider :find_options => {:include => :project}
validates_presence_of :project, :title, :category validates_presence_of :project, :title, :category
validates_length_of :title, :maximum => 60 validates_length_of :title, :maximum => 60
named_scope :visible, lambda {|*args| { :include => :project,
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_documents, *args) } }
def visible?(user=User.current) def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_documents, project) !user.nil? && user.allowed_to?(:view_documents, project)
end end
def after_initialize def after_initialize
if new_record? if new_record?
self.category ||= DocumentCategory.default self.category ||= DocumentCategory.default
end end
end end
def updated_on def updated_on
unless @updated_on unless @updated_on
a = attachments.find(:first, :order => 'created_on DESC') a = attachments.find(:first, :order => 'created_on DESC')
+4 -4
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+4 -5
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -20,4 +20,3 @@ class DocumentCategoryCustomField < CustomField
:enumeration_doc_categories :enumeration_doc_categories
end end
end end
+4 -4
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+7 -7
View File
@@ -1,30 +1,30 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2009 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class EnabledModule < ActiveRecord::Base class EnabledModule < ActiveRecord::Base
belongs_to :project belongs_to :project
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name, :scope => :project_id validates_uniqueness_of :name, :scope => :project_id
after_create :module_enabled after_create :module_enabled
private private
# after_create callback used to do things when a module is enabled # after_create callback used to do things when a module is enabled
def module_enabled def module_enabled
case name case name
+1
View File
@@ -32,6 +32,7 @@ class Enumeration < ActiveRecord::Base
named_scope :shared, :conditions => { :project_id => nil } named_scope :shared, :conditions => { :project_id => nil }
named_scope :active, :conditions => { :active => true } named_scope :active, :conditions => { :active => true }
named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
def self.default def self.default
# Creates a fake default scope so Enumeration.default will check # Creates a fake default scope so Enumeration.default will check
+164 -115
View File
@@ -1,23 +1,23 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Issue < ActiveRecord::Base class Issue < ActiveRecord::Base
include Redmine::SafeAttributes include Redmine::SafeAttributes
belongs_to :project belongs_to :project
belongs_to :tracker belongs_to :tracker
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id' belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
@@ -30,11 +30,11 @@ class Issue < ActiveRecord::Base
has_many :journals, :as => :journalized, :dependent => :destroy has_many :journals, :as => :journalized, :dependent => :destroy
has_many :time_entries, :dependent => :delete_all 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_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_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 has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
acts_as_nested_set :scope => 'root_id' acts_as_nested_set :scope => 'root_id', :dependent => :destroy
acts_as_attachable :after_remove => :attachment_removed acts_as_attachable :after_remove => :attachment_removed
acts_as_customizable acts_as_customizable
acts_as_watchable acts_as_watchable
@@ -45,7 +45,7 @@ class Issue < ActiveRecord::Base
acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id} (#{o.status}): #{o.subject}"}, 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}}, :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}},
:type => Proc.new {|o| 'issue' + (o.closed? ? ' closed' : '') } :type => Proc.new {|o| 'issue' + (o.closed? ? ' closed' : '') }
acts_as_activity_provider :find_options => {:include => [:project, :author, :tracker]}, acts_as_activity_provider :find_options => {:include => [:project, :author, :tracker]},
:author_key => :author_id :author_key => :author_id
@@ -60,19 +60,14 @@ class Issue < ActiveRecord::Base
validates_numericality_of :estimated_hours, :allow_nil => true validates_numericality_of :estimated_hours, :allow_nil => true
named_scope :visible, lambda {|*args| { :include => :project, named_scope :visible, lambda {|*args| { :include => :project,
:conditions => Project.allowed_to_condition(args.first || User.current, :view_issues) } } :conditions => Issue.visible_condition(args.shift || User.current, *args) } }
named_scope :open, :conditions => ["#{IssueStatus.table_name}.is_closed = ?", false], :include => :status named_scope :open, :conditions => ["#{IssueStatus.table_name}.is_closed = ?", false], :include => :status
named_scope :recently_updated, :order => "#{Issue.table_name}.updated_on DESC" named_scope :recently_updated, :order => "#{Issue.table_name}.updated_on DESC"
named_scope :with_limit, lambda { |limit| { :limit => limit} } named_scope :with_limit, lambda { |limit| { :limit => limit} }
named_scope :on_active_project, :include => [:status, :project, :tracker], named_scope :on_active_project, :include => [:status, :project, :tracker],
:conditions => ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"] :conditions => ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"]
named_scope :for_gantt, lambda {
{
:include => [:tracker, :status, :assigned_to, :priority, :project, :fixed_version]
}
}
named_scope :without_version, lambda { named_scope :without_version, lambda {
{ {
@@ -89,14 +84,40 @@ class Issue < ActiveRecord::Base
before_create :default_assign before_create :default_assign
before_save :close_duplicates, :update_done_ratio_from_issue_status before_save :close_duplicates, :update_done_ratio_from_issue_status
after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal
after_destroy :destroy_children
after_destroy :update_parent_attributes after_destroy :update_parent_attributes
# 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|
case role.issues_visibility
when 'all'
nil
when 'default'
"(#{table_name}.is_private = #{connection.quoted_false} OR #{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id = #{user.id})"
when 'own'
"(#{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id = #{user.id})"
else
'1=0'
end
end
end
# Returns true if usr or current user is allowed to view the issue # Returns true if usr or current user is allowed to view the issue
def visible?(usr=nil) def visible?(usr=nil)
(usr || User.current).allowed_to?(:view_issues, self.project) (usr || User.current).allowed_to?(:view_issues, self.project) do |role, user|
case role.issues_visibility
when 'all'
true
when 'default'
!self.is_private? || self.author == user || self.assigned_to == user
when 'own'
self.author == user || self.assigned_to == user
else
false
end
end
end end
def after_initialize def after_initialize
if new_record? if new_record?
# set default values for new records only # set default values for new records only
@@ -104,12 +125,12 @@ class Issue < ActiveRecord::Base
self.priority ||= IssuePriority.default self.priority ||= IssuePriority.default
end end
end end
# Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields # Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
def available_custom_fields def available_custom_fields
(project && tracker) ? project.all_issue_custom_fields.select {|c| tracker.custom_fields.include? c } : [] (project && tracker) ? (project.all_issue_custom_fields & tracker.custom_fields.all) : []
end end
def copy_from(arg) def copy_from(arg)
issue = arg.is_a?(Issue) ? arg : Issue.visible.find(arg) 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.attributes = issue.attributes.dup.except("id", "root_id", "parent_id", "lft", "rgt", "created_on", "updated_on")
@@ -117,7 +138,7 @@ class Issue < ActiveRecord::Base
self.status = issue.status self.status = issue.status
self self
end end
# Moves/copies an issue to a new project and tracker # Moves/copies an issue to a new project and tracker
# Returns the moved/copied issue on success, false on failure # Returns the moved/copied issue on success, false on failure
def move_to_project(*args) def move_to_project(*args)
@@ -125,11 +146,11 @@ class Issue < ActiveRecord::Base
move_to_project_without_transaction(*args) || raise(ActiveRecord::Rollback) move_to_project_without_transaction(*args) || raise(ActiveRecord::Rollback)
end || false end || false
end end
def move_to_project_without_transaction(new_project, new_tracker = nil, options = {}) def move_to_project_without_transaction(new_project, new_tracker = nil, options = {})
options ||= {} options ||= {}
issue = options[:copy] ? self.class.new.copy_from(self) : self issue = options[:copy] ? self.class.new.copy_from(self) : self
if new_project && issue.project_id != new_project.id if new_project && issue.project_id != new_project.id
# delete issue relations # delete issue relations
unless Setting.cross_project_issue_relations? unless Setting.cross_project_issue_relations?
@@ -154,6 +175,7 @@ class Issue < ActiveRecord::Base
issue.reset_custom_values! issue.reset_custom_values!
end end
if options[:copy] if options[:copy]
issue.author = User.current
issue.custom_field_values = self.custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h} issue.custom_field_values = self.custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
issue.status = if options[:attributes] && options[:attributes][:status_id] issue.status = if options[:attributes] && options[:attributes][:status_id]
IssueStatus.find_by_id(options[:attributes][:status_id]) IssueStatus.find_by_id(options[:attributes][:status_id])
@@ -166,10 +188,16 @@ class Issue < ActiveRecord::Base
issue.attributes = options[:attributes] issue.attributes = options[:attributes]
end end
if issue.save if issue.save
unless options[:copy] if options[:copy]
if current_journal && current_journal.notes.present?
issue.init_journal(current_journal.user, current_journal.notes)
issue.current_journal.notify = false
issue.save
end
else
# Manually update project_id on related time entries # Manually update project_id on related time entries
TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id}) TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
issue.children.each do |child| issue.children.each do |child|
unless child.move_to_project_without_transaction(new_project) unless child.move_to_project_without_transaction(new_project)
# Move failed and transaction was rollback'd # Move failed and transaction was rollback'd
@@ -187,7 +215,7 @@ class Issue < ActiveRecord::Base
self.status = nil self.status = nil
write_attribute(:status_id, sid) write_attribute(:status_id, sid)
end end
def priority_id=(pid) def priority_id=(pid)
self.priority = nil self.priority = nil
write_attribute(:priority_id, pid) write_attribute(:priority_id, pid)
@@ -200,6 +228,13 @@ class Issue < ActiveRecord::Base
result result
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 attributes= so that tracker_id gets assigned first # Overrides attributes= so that tracker_id gets assigned first
def attributes_with_tracker_first=(new_attributes, *args) def attributes_with_tracker_first=(new_attributes, *args)
return if new_attributes.nil? return if new_attributes.nil?
@@ -211,11 +246,11 @@ class Issue < ActiveRecord::Base
end end
# Do not redefine alias chain on reload (see #4838) # Do not redefine alias chain on reload (see #4838)
alias_method_chain(:attributes=, :tracker_first) unless method_defined?(:attributes_without_tracker_first=) alias_method_chain(:attributes=, :tracker_first) unless method_defined?(:attributes_without_tracker_first=)
def estimated_hours=(h) def estimated_hours=(h)
write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h) write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h)
end end
safe_attributes 'tracker_id', safe_attributes 'tracker_id',
'status_id', 'status_id',
'parent_issue_id', 'parent_issue_id',
@@ -233,13 +268,19 @@ class Issue < ActiveRecord::Base
'custom_fields', 'custom_fields',
'lock_version', 'lock_version',
:if => lambda {|issue, user| issue.new_record? || user.allowed_to?(:edit_issues, issue.project) } :if => lambda {|issue, user| issue.new_record? || user.allowed_to?(:edit_issues, issue.project) }
safe_attributes 'status_id', safe_attributes 'status_id',
'assigned_to_id', 'assigned_to_id',
'fixed_version_id', 'fixed_version_id',
'done_ratio', 'done_ratio',
:if => lambda {|issue, user| issue.new_statuses_allowed_to(user).any? } :if => lambda {|issue, user| issue.new_statuses_allowed_to(user).any? }
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))
}
# Safely sets attributes # Safely sets attributes
# Should be called from controllers instead of #attributes= # Should be called from controllers instead of #attributes=
# attr_accessible is too rough because we still want things like # attr_accessible is too rough because we still want things like
@@ -247,26 +288,26 @@ class Issue < ActiveRecord::Base
# TODO: move workflow/permission checks from controllers to here # TODO: move workflow/permission checks from controllers to here
def safe_attributes=(attrs, user=User.current) def safe_attributes=(attrs, user=User.current)
return unless attrs.is_a?(Hash) return unless attrs.is_a?(Hash)
# User can change issue attributes only if he has :edit permission or if a workflow transition is allowed # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed
attrs = delete_unsafe_attributes(attrs, user) attrs = delete_unsafe_attributes(attrs, user)
return if attrs.empty? return if attrs.empty?
# Tracker must be set before since new_statuses_allowed_to depends on it. # Tracker must be set before since new_statuses_allowed_to depends on it.
if t = attrs.delete('tracker_id') if t = attrs.delete('tracker_id')
self.tracker_id = t self.tracker_id = t
end end
if attrs['status_id'] if attrs['status_id']
unless new_statuses_allowed_to(user).collect(&:id).include?(attrs['status_id'].to_i) unless new_statuses_allowed_to(user).collect(&:id).include?(attrs['status_id'].to_i)
attrs.delete('status_id') attrs.delete('status_id')
end end
end end
unless leaf? unless leaf?
attrs.reject! {|k,v| %w(priority_id done_ratio start_date due_date estimated_hours).include?(k)} attrs.reject! {|k,v| %w(priority_id done_ratio start_date due_date estimated_hours).include?(k)}
end end
if attrs.has_key?('parent_issue_id') if attrs.has_key?('parent_issue_id')
if !user.allowed_to?(:manage_subtasks, project) if !user.allowed_to?(:manage_subtasks, project)
attrs.delete('parent_issue_id') attrs.delete('parent_issue_id')
@@ -274,10 +315,10 @@ class Issue < ActiveRecord::Base
attrs.delete('parent_issue_id') unless Issue.visible(user).exists?(attrs['parent_issue_id'].to_i) attrs.delete('parent_issue_id') unless Issue.visible(user).exists?(attrs['parent_issue_id'].to_i)
end end
end end
self.attributes = attrs self.attributes = attrs
end end
def done_ratio def done_ratio
if Issue.use_status_for_done_ratio? && status && status.default_done_ratio if Issue.use_status_for_done_ratio? && status && status.default_done_ratio
status.default_done_ratio status.default_done_ratio
@@ -293,20 +334,20 @@ class Issue < ActiveRecord::Base
def self.use_field_for_done_ratio? def self.use_field_for_done_ratio?
Setting.issue_done_ratio == 'issue_field' Setting.issue_done_ratio == 'issue_field'
end end
def validate def validate
if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty? if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
errors.add :due_date, :not_a_date errors.add :due_date, :not_a_date
end end
if self.due_date and self.start_date and self.due_date < self.start_date if self.due_date and self.start_date and self.due_date < self.start_date
errors.add :due_date, :greater_than_start_date errors.add :due_date, :greater_than_start_date
end end
if start_date && soonest_start && start_date < soonest_start if start_date && soonest_start && start_date < soonest_start
errors.add :start_date, :invalid errors.add :start_date, :invalid
end end
if fixed_version if fixed_version
if !assignable_versions.include?(fixed_version) if !assignable_versions.include?(fixed_version)
errors.add :fixed_version_id, :inclusion errors.add :fixed_version_id, :inclusion
@@ -314,14 +355,14 @@ class Issue < ActiveRecord::Base
errors.add_to_base I18n.t(:error_can_not_reopen_issue_on_closed_version) errors.add_to_base I18n.t(:error_can_not_reopen_issue_on_closed_version)
end end
end end
# Checks that the issue can not be added/moved to a disabled tracker # Checks that the issue can not be added/moved to a disabled tracker
if project && (tracker_id_changed? || project_id_changed?) if project && (tracker_id_changed? || project_id_changed?)
unless project.trackers.include?(tracker) unless project.trackers.include?(tracker)
errors.add :tracker_id, :inclusion errors.add :tracker_id, :inclusion
end end
end end
# Checks parent issue assignment # Checks parent issue assignment
if @parent_issue if @parent_issue
if @parent_issue.project_id != project_id if @parent_issue.project_id != project_id
@@ -338,7 +379,7 @@ class Issue < ActiveRecord::Base
end end
end end
end end
# Set the done_ratio using the status if that setting is set. This will keep the done_ratios # 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 # even if the user turns off the setting later
def update_done_ratio_from_issue_status def update_done_ratio_from_issue_status
@@ -346,7 +387,7 @@ class Issue < ActiveRecord::Base
self.done_ratio = status.default_done_ratio self.done_ratio = status.default_done_ratio
end end
end end
def init_journal(user, notes = "") def init_journal(user, notes = "")
@current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes) @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes)
@issue_before_change = self.clone @issue_before_change = self.clone
@@ -357,12 +398,12 @@ class Issue < ActiveRecord::Base
updated_on_will_change! updated_on_will_change!
@current_journal @current_journal
end end
# Return true if the issue is closed, otherwise false # Return true if the issue is closed, otherwise false
def closed? def closed?
self.status.is_closed? self.status.is_closed?
end end
# Return true if the issue is being reopened # Return true if the issue is being reopened
def reopened? def reopened?
if !new_record? && status_id_changed? if !new_record? && status_id_changed?
@@ -386,7 +427,7 @@ class Issue < ActiveRecord::Base
end end
false false
end end
# Returns true if the issue is overdue # Returns true if the issue is overdue
def overdue? def overdue?
!due_date.nil? && (due_date < Date.today) && !status.is_closed? !due_date.nil? && (due_date < Date.today) && !status.is_closed?
@@ -403,33 +444,39 @@ class Issue < ActiveRecord::Base
def children? def children?
!leaf? !leaf?
end end
# Users the issue can be assigned to # Users the issue can be assigned to
def assignable_users def assignable_users
users = project.assignable_users users = project.assignable_users
users << author if author users << author if author
users << assigned_to if assigned_to
users.uniq.sort users.uniq.sort
end end
# Versions that the issue can be assigned to # Versions that the issue can be assigned to
def assignable_versions def assignable_versions
@assignable_versions ||= (project.shared_versions.open + [Version.find_by_id(fixed_version_id_was)]).compact.uniq.sort @assignable_versions ||= (project.shared_versions.open + [Version.find_by_id(fixed_version_id_was)]).compact.uniq.sort
end end
# Returns true if this issue is blocked by another issue that is still open # Returns true if this issue is blocked by another issue that is still open
def blocked? def blocked?
!relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil? !relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
end end
# Returns an array of status that user is able to apply # Returns an array of status that user is able to apply
def new_statuses_allowed_to(user, include_default=false) def new_statuses_allowed_to(user, include_default=false)
statuses = status.find_new_statuses_allowed_to(user.roles_for_project(project), tracker) statuses = status.find_new_statuses_allowed_to(
user.roles_for_project(project),
tracker,
author == user,
assigned_to_id_changed? ? assigned_to_id_was == user.id : assigned_to_id == user.id
)
statuses << status unless statuses.empty? statuses << status unless statuses.empty?
statuses << IssueStatus.default if include_default statuses << IssueStatus.default if include_default
statuses = statuses.uniq.sort statuses = statuses.uniq.sort
blocked? ? statuses.reject {|s| s.is_closed?} : statuses blocked? ? statuses.reject {|s| s.is_closed?} : statuses
end end
# Returns the mail adresses of users that should be notified # Returns the mail adresses of users that should be notified
def recipients def recipients
notified = project.notified_users notified = project.notified_users
@@ -442,7 +489,7 @@ class Issue < ActiveRecord::Base
notified.reject! {|user| !visible?(user)} notified.reject! {|user| !visible?(user)}
notified.collect(&:mail) notified.collect(&:mail)
end end
# Returns the total number of hours spent on this issue and its descendants # Returns the total number of hours spent on this issue and its descendants
# #
# Example: # Example:
@@ -451,47 +498,50 @@ class Issue < ActiveRecord::Base
def spent_hours def spent_hours
@spent_hours ||= self_and_descendants.sum("#{TimeEntry.table_name}.hours", :include => :time_entries).to_f || 0.0 @spent_hours ||= self_and_descendants.sum("#{TimeEntry.table_name}.hours", :include => :time_entries).to_f || 0.0
end end
def relations def relations
(relations_from + relations_to).sort (relations_from + relations_to).sort
end end
def all_dependent_issues def all_dependent_issues(except=[])
except << self
dependencies = [] dependencies = []
relations_from.each do |relation| relations_from.each do |relation|
dependencies << relation.issue_to if relation.issue_to && !except.include?(relation.issue_to)
dependencies += relation.issue_to.all_dependent_issues dependencies << relation.issue_to
dependencies += relation.issue_to.all_dependent_issues(except)
end
end end
dependencies dependencies
end end
# Returns an array of issues that duplicate this one # Returns an array of issues that duplicate this one
def duplicates def duplicates
relations_to.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.issue_from} relations_to.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.issue_from}
end end
# Returns the due date or the target due date if any # Returns the due date or the target due date if any
# Used on gantt chart # Used on gantt chart
def due_before def due_before
due_date || (fixed_version ? fixed_version.effective_date : nil) due_date || (fixed_version ? fixed_version.effective_date : nil)
end end
# Returns the time scheduled for this issue. # Returns the time scheduled for this issue.
# #
# Example: # Example:
# Start Date: 2/26/09, End Date: 3/04/09 # Start Date: 2/26/09, End Date: 3/04/09
# duration => 6 # duration => 6
def duration def duration
(start_date && due_date) ? due_date - start_date : 0 (start_date && due_date) ? due_date - start_date : 0
end end
def soonest_start def soonest_start
@soonest_start ||= ( @soonest_start ||= (
relations_to.collect{|relation| relation.successor_soonest_start} + relations_to.collect{|relation| relation.successor_soonest_start} +
ancestors.collect(&:soonest_start) ancestors.collect(&:soonest_start)
).compact.max ).compact.max
end end
def reschedule_after(date) def reschedule_after(date)
return if date.nil? return if date.nil?
if leaf? if leaf?
@@ -505,7 +555,7 @@ class Issue < ActiveRecord::Base
end end
end end
end end
def <=>(issue) def <=>(issue)
if issue.nil? if issue.nil?
-1 -1
@@ -515,16 +565,19 @@ class Issue < ActiveRecord::Base
(lft || 0) <=> (issue.lft || 0) (lft || 0) <=> (issue.lft || 0)
end end
end end
def to_s def to_s
"#{tracker} ##{id}: #{subject}" "#{tracker} ##{id}: #{subject}"
end end
# Returns a string of css classes that apply to the issue # Returns a string of css classes that apply to the issue
def css_classes def css_classes
s = "issue status-#{status.position} priority-#{priority.position}" s = "issue status-#{status.position} priority-#{priority.position}"
s << ' closed' if closed? s << ' closed' if closed?
s << ' overdue' if overdue? s << ' overdue' if overdue?
s << ' child' if child?
s << ' parent' unless leaf?
s << ' private' if is_private?
s << ' created-by-me' if User.current.logged? && author_id == User.current.id s << ' created-by-me' if User.current.logged? && author_id == User.current.id
s << ' assigned-to-me' if User.current.logged? && assigned_to_id == User.current.id s << ' assigned-to-me' if User.current.logged? && assigned_to_id == User.current.id
s s
@@ -534,7 +587,7 @@ class Issue < ActiveRecord::Base
# Returns false if save fails # Returns false if save fails
def save_issue_with_child_records(params, existing_time_entry=nil) def save_issue_with_child_records(params, existing_time_entry=nil)
Issue.transaction do Issue.transaction do
if params[:time_entry] && params[:time_entry][:hours].present? && User.current.allowed_to?(:log_time, project) if params[:time_entry] && (params[:time_entry][:hours].present? || params[:time_entry][:comments].present?) && User.current.allowed_to?(:log_time, project)
@time_entry = existing_time_entry || TimeEntry.new @time_entry = existing_time_entry || TimeEntry.new
@time_entry.project = project @time_entry.project = project
@time_entry.issue = self @time_entry.issue = self
@@ -543,10 +596,10 @@ class Issue < ActiveRecord::Base
@time_entry.attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
self.time_entries << @time_entry self.time_entries << @time_entry
end end
if valid? if valid?
attachments = Attachment.attach_files(self, params[:attachments]) attachments = Attachment.attach_files(self, params[:attachments])
attachments[:files].each {|a| @current_journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)} attachments[:files].each {|a| @current_journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)}
# TODO: Rename hook # TODO: Rename hook
Redmine::Hook.call_hook(:controller_issues_edit_before_save, { :params => params, :issue => self, :time_entry => @time_entry, :journal => @current_journal}) Redmine::Hook.call_hook(:controller_issues_edit_before_save, { :params => params, :issue => self, :time_entry => @time_entry, :journal => @current_journal})
@@ -571,7 +624,7 @@ class Issue < ActiveRecord::Base
# Update issues assigned to the version # Update issues assigned to the version
update_versions(["#{Issue.table_name}.fixed_version_id = ?", version.id]) update_versions(["#{Issue.table_name}.fixed_version_id = ?", version.id])
end end
# Unassigns issues from versions that are no longer shared # Unassigns issues from versions that are no longer shared
# after +project+ was moved # after +project+ was moved
def self.update_versions_from_hierarchy_change(project) def self.update_versions_from_hierarchy_change(project)
@@ -589,7 +642,7 @@ class Issue < ActiveRecord::Base
nil nil
end end
end end
def parent_issue_id def parent_issue_id
if instance_variable_defined? :@parent_issue if instance_variable_defined? :@parent_issue
@parent_issue.nil? ? nil : @parent_issue.id @parent_issue.nil? ? nil : @parent_issue.id
@@ -638,17 +691,19 @@ class Issue < ActiveRecord::Base
def self.by_subproject(project) def self.by_subproject(project)
ActiveRecord::Base.connection.select_all("select s.id as status_id, ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed, s.is_closed as closed,
i.project_id as project_id, #{Issue.table_name}.project_id as project_id,
count(i.id) as total count(#{Issue.table_name}.id) as total
from from
#{Issue.table_name} i, #{IssueStatus.table_name} s #{Issue.table_name}, #{Project.table_name}, #{IssueStatus.table_name} s
where where
i.status_id=s.id #{Issue.table_name}.status_id=s.id
and i.project_id IN (#{project.descendants.active.collect{|p| p.id}.join(',')}) and #{Issue.table_name}.project_id = #{Project.table_name}.id
group by s.id, s.is_closed, i.project_id") if project.descendants.active.any? 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
# End ReportsController extraction # End ReportsController extraction
# Returns an array of projects that current user can move issues to # Returns an array of projects that current user can move issues to
def self.allowed_target_projects_on_move def self.allowed_target_projects_on_move
projects = [] projects = []
@@ -664,9 +719,9 @@ class Issue < ActiveRecord::Base
end end
projects projects
end end
private private
def update_nested_set_attributes def update_nested_set_attributes
if root_id.nil? if root_id.nil?
# issue was just created # issue was just created
@@ -713,7 +768,7 @@ class Issue < ActiveRecord::Base
end end
remove_instance_variable(:@parent_issue) if instance_variable_defined?(:@parent_issue) remove_instance_variable(:@parent_issue) if instance_variable_defined?(:@parent_issue)
end end
def update_parent_attributes def update_parent_attributes
recalculate_attributes_for(parent_id) if parent_id recalculate_attributes_for(parent_id) if parent_id
end end
@@ -724,14 +779,14 @@ class Issue < ActiveRecord::Base
if priority_position = p.children.maximum("#{IssuePriority.table_name}.position", :include => :priority) if priority_position = p.children.maximum("#{IssuePriority.table_name}.position", :include => :priority)
p.priority = IssuePriority.find_by_position(priority_position) p.priority = IssuePriority.find_by_position(priority_position)
end end
# start/due dates = lowest/highest dates of children # start/due dates = lowest/highest dates of children
p.start_date = p.children.minimum(:start_date) p.start_date = p.children.minimum(:start_date)
p.due_date = p.children.maximum(:due_date) p.due_date = p.children.maximum(:due_date)
if p.start_date && p.due_date && p.due_date < p.start_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 p.start_date, p.due_date = p.due_date, p.start_date
end end
# done ratio = weighted average ratio of leaves # done ratio = weighted average ratio of leaves
unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
leaves_count = p.leaves.count leaves_count = p.leaves.count
@@ -745,24 +800,16 @@ class Issue < ActiveRecord::Base
p.done_ratio = progress.round p.done_ratio = progress.round
end end
end end
# estimate = sum of leaves estimates # estimate = sum of leaves estimates
p.estimated_hours = p.leaves.sum(:estimated_hours).to_f p.estimated_hours = p.leaves.sum(:estimated_hours).to_f
p.estimated_hours = nil if p.estimated_hours == 0.0 p.estimated_hours = nil if p.estimated_hours == 0.0
# ancestors will be recursively updated # ancestors will be recursively updated
p.save(false) p.save(false)
end end
end end
def destroy_children
unless leaf?
children.each do |child|
child.destroy
end
end
end
# Update issues so their versions are not pointing to a # Update issues so their versions are not pointing to a
# fixed_version that is not shared with the issue's project # fixed_version that is not shared with the issue's project
def self.update_versions(conditions=nil) def self.update_versions(conditions=nil)
@@ -782,7 +829,7 @@ class Issue < ActiveRecord::Base
end end
end end
end end
# Callback on attachment deletion # Callback on attachment deletion
def attachment_removed(obj) def attachment_removed(obj)
journal = init_journal(User.current) journal = init_journal(User.current)
@@ -791,7 +838,7 @@ class Issue < ActiveRecord::Base
:old_value => obj.filename) :old_value => obj.filename)
journal.save journal.save
end end
# Default assignment based on category # Default assignment based on category
def default_assign def default_assign
if assigned_to.nil? && category && category.assigned_to if assigned_to.nil? && category && category.assigned_to
@@ -824,27 +871,30 @@ class Issue < ActiveRecord::Base
end end
end end
end end
# Saves the changes in a Journal # Saves the changes in a Journal
# Called after_save # Called after_save
def create_journal def create_journal
if @current_journal if @current_journal
# attributes changes # attributes changes
(Issue.column_names - %w(id description root_id lft rgt lock_version created_on updated_on)).each {|c| (Issue.column_names - %w(id root_id lft rgt lock_version created_on updated_on)).each {|c|
before = @issue_before_change.send(c)
after = send(c)
next if before == after || (before.blank? && after.blank?)
@current_journal.details << JournalDetail.new(:property => 'attr', @current_journal.details << JournalDetail.new(:property => 'attr',
:prop_key => c, :prop_key => c,
:old_value => @issue_before_change.send(c), :old_value => @issue_before_change.send(c),
:value => send(c)) unless send(c)==@issue_before_change.send(c) :value => send(c))
} }
# custom fields changes # custom fields changes
custom_values.each {|c| custom_values.each {|c|
next if (@custom_values_before_change[c.custom_field_id]==c.value || next if (@custom_values_before_change[c.custom_field_id]==c.value ||
(@custom_values_before_change[c.custom_field_id].blank? && c.value.blank?)) (@custom_values_before_change[c.custom_field_id].blank? && c.value.blank?))
@current_journal.details << JournalDetail.new(:property => 'cf', @current_journal.details << JournalDetail.new(:property => 'cf',
:prop_key => c.custom_field_id, :prop_key => c.custom_field_id,
:old_value => @custom_values_before_change[c.custom_field_id], :old_value => @custom_values_before_change[c.custom_field_id],
:value => c.value) :value => c.value)
} }
@current_journal.save @current_journal.save
# reset current journal # reset current journal
init_journal @current_journal.user, @current_journal.notes init_journal @current_journal.user, @current_journal.notes
@@ -863,20 +913,19 @@ class Issue < ActiveRecord::Base
select_field = options.delete(:field) select_field = options.delete(:field)
joins = options.delete(:joins) joins = options.delete(:joins)
where = "i.#{select_field}=j.id" where = "#{Issue.table_name}.#{select_field}=j.id"
ActiveRecord::Base.connection.select_all("select s.id as status_id, ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed, s.is_closed as closed,
j.id as #{select_field}, j.id as #{select_field},
count(i.id) as total count(#{Issue.table_name}.id) as total
from from
#{Issue.table_name} i, #{IssueStatus.table_name} s, #{joins} j #{Issue.table_name}, #{Project.table_name}, #{IssueStatus.table_name} s, #{joins} j
where where
i.status_id=s.id #{Issue.table_name}.status_id=s.id
and #{where} and #{where}
and i.project_id=#{project.id} 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") group by s.id, s.is_closed, j.id")
end end
end end
+4 -2
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -24,6 +24,8 @@ class IssueCategory < ActiveRecord::Base
validates_uniqueness_of :name, :scope => [:project_id] validates_uniqueness_of :name, :scope => [:project_id]
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
alias :destroy_without_reassign :destroy alias :destroy_without_reassign :destroy
# Destroy the category # Destroy the category
+6 -1
View File
@@ -47,7 +47,12 @@ class IssueRelation < ActiveRecord::Base
if issue_from && issue_to if issue_from && issue_to
errors.add :issue_to_id, :invalid if issue_from_id == issue_to_id errors.add :issue_to_id, :invalid if issue_from_id == issue_to_id
errors.add :issue_to_id, :not_same_project unless issue_from.project_id == issue_to.project_id || Setting.cross_project_issue_relations? errors.add :issue_to_id, :not_same_project unless issue_from.project_id == issue_to.project_id || Setting.cross_project_issue_relations?
errors.add_to_base :circular_dependency if issue_to.all_dependent_issues.include? issue_from #detect circular dependencies depending wether the relation should be reversed
if TYPES.has_key?(relation_type) && TYPES[relation_type][:reverse]
errors.add_to_base :circular_dependency if issue_from.all_dependent_issues.include? issue_to
else
errors.add_to_base :circular_dependency if issue_to.all_dependent_issues.include? issue_from
end
errors.add_to_base :cant_link_an_issue_with_a_descendant if issue_from.is_descendant_of?(issue_to) || issue_from.is_ancestor_of?(issue_to) errors.add_to_base :cant_link_an_issue_with_a_descendant if issue_from.is_descendant_of?(issue_to) || issue_from.is_ancestor_of?(issue_to)
end end
end end
+20 -16
View File
@@ -25,8 +25,9 @@ class IssueStatus < ActiveRecord::Base
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name validates_uniqueness_of :name
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
validates_inclusion_of :default_done_ratio, :in => 0..100, :allow_nil => true validates_inclusion_of :default_done_ratio, :in => 0..100, :allow_nil => true
named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
def after_save def after_save
IssueStatus.update_all("is_default=#{connection.quoted_false}", ['id <> ?', id]) if self.is_default? IssueStatus.update_all("is_default=#{connection.quoted_false}", ['id <> ?', id]) if self.is_default?
@@ -51,10 +52,15 @@ class IssueStatus < ActiveRecord::Base
# Returns an array of all statuses the given role can switch to # Returns an array of all statuses the given role can switch to
# Uses association cache when called more than one time # Uses association cache when called more than one time
def new_statuses_allowed_to(roles, tracker) def new_statuses_allowed_to(roles, tracker, author=false, assignee=false)
if roles && tracker if roles && tracker
role_ids = roles.collect(&:id) role_ids = roles.collect(&:id)
new_statuses = workflows.select {|w| role_ids.include?(w.role_id) && w.tracker_id == tracker.id}.collect{|w| w.new_status}.compact.sort 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.collect{|w| w.new_status}.compact.sort
else else
[] []
end end
@@ -62,24 +68,22 @@ class IssueStatus < ActiveRecord::Base
# Same thing as above but uses a database query # Same thing as above but uses a database query
# More efficient than the previous method if called just once # More efficient than the previous method if called just once
def find_new_statuses_allowed_to(roles, tracker) def find_new_statuses_allowed_to(roles, tracker, author=false, assignee=false)
if roles && tracker if roles.present? && tracker
conditions = "(author = :false AND assignee = :false)"
conditions << " OR author = :true" if author
conditions << " OR assignee = :true" if assignee
workflows.find(:all, workflows.find(:all,
:include => :new_status, :include => :new_status,
:conditions => { :role_id => roles.collect(&:id), :conditions => ["role_id IN (:role_ids) AND tracker_id = :tracker_id AND (#{conditions})",
:tracker_id => tracker.id}).collect{ |w| w.new_status }.compact.sort {:role_ids => roles.collect(&:id), :tracker_id => tracker.id, :true => true, :false => false}
]
).collect{|w| w.new_status}.compact.sort
else else
[] []
end end
end end
def new_status_allowed_to?(status, roles, tracker)
if status && roles && tracker
!workflows.find(:first, :conditions => {:new_status_id => status.id, :role_id => roles.collect(&:id), :tracker_id => tracker.id}).nil?
else
false
end
end
def <=>(status) def <=>(status)
position <=> status.position position <=> status.position
+15 -3
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -32,12 +32,16 @@ class Journal < ActiveRecord::Base
:url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id, :anchor => "change-#{o.id}"}} :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id, :anchor => "change-#{o.id}"}}
acts_as_activity_provider :type => 'issues', acts_as_activity_provider :type => 'issues',
:permission => :view_issues,
:author_key => :user_id, :author_key => :user_id,
:find_options => {:include => [{:issue => :project}, :details, :user], :find_options => {:include => [{:issue => :project}, :details, :user],
:conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" + :conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" +
" (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"} " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"}
named_scope :visible, lambda {|*args| {
:include => {:issue => :project},
:conditions => Issue.visible_condition(args.shift || User.current, *args)
}}
def save(*args) def save(*args)
# Do not save an empty journal # Do not save an empty journal
(details.empty? && notes.blank?) ? false : super (details.empty? && notes.blank?) ? false : super
@@ -73,4 +77,12 @@ class Journal < ActiveRecord::Base
s << ' has-details' unless details.blank? s << ' has-details' unless details.blank?
s s
end end
def notify?
@notify != false
end
def notify=(arg)
@notify = arg
end
end end
+18 -5
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -17,9 +17,22 @@
class JournalDetail < ActiveRecord::Base class JournalDetail < ActiveRecord::Base
belongs_to :journal belongs_to :journal
before_save :normalize_values
def before_save private
self.value = value[0..254] if value && value.is_a?(String)
self.old_value = old_value[0..254] if old_value && old_value.is_a?(String) def normalize_values
self.value = normalize(value)
self.old_value = normalize(old_value)
end
def normalize(v)
if v == true
"1"
elsif v == false
"0"
else
v
end
end end
end end
+8 -6
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -17,10 +17,12 @@
class JournalObserver < ActiveRecord::Observer class JournalObserver < ActiveRecord::Observer
def after_create(journal) def after_create(journal)
if Setting.notified_events.include?('issue_updated') || if journal.notify? &&
(Setting.notified_events.include?('issue_note_added') && journal.notes.present?) || (Setting.notified_events.include?('issue_updated') ||
(Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) || (Setting.notified_events.include?('issue_note_added') && journal.notes.present?) ||
(Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?) (Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) ||
(Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?)
)
Mailer.deliver_issue_edit(journal) Mailer.deliver_issue_edit(journal)
end end
end end
+52 -47
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -21,25 +21,25 @@ class MailHandler < ActionMailer::Base
class UnauthorizedAction < StandardError; end class UnauthorizedAction < StandardError; end
class MissingInformation < StandardError; end class MissingInformation < StandardError; end
attr_reader :email, :user attr_reader :email, :user
def self.receive(email, options={}) def self.receive(email, options={})
@@handler_options = options.dup @@handler_options = options.dup
@@handler_options[:issue] ||= {} @@handler_options[:issue] ||= {}
@@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip) if @@handler_options[:allow_override].is_a?(String) @@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip) if @@handler_options[:allow_override].is_a?(String)
@@handler_options[:allow_override] ||= [] @@handler_options[:allow_override] ||= []
# Project needs to be overridable if not specified # Project needs to be overridable if not specified
@@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project) @@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project)
# Status overridable by default # Status overridable by default
@@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status) @@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
@@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1' ? true : false) @@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1' ? true : false)
super email super email
end end
# Processes incoming emails # Processes incoming emails
# Returns the created object (eg. an issue, a message) or false # Returns the created object (eg. an issue, a message) or false
def receive(email) def receive(email)
@@ -78,13 +78,13 @@ class MailHandler < ActionMailer::Base
User.current = @user User.current = @user
dispatch dispatch
end end
private private
MESSAGE_ID_RE = %r{^<redmine\.([a-z0-9_]+)\-(\d+)\.\d+@} MESSAGE_ID_RE = %r{^<redmine\.([a-z0-9_]+)\-(\d+)\.\d+@}
ISSUE_REPLY_SUBJECT_RE = %r{\[[^\]]*#(\d+)\]} ISSUE_REPLY_SUBJECT_RE = %r{\[[^\]]*#(\d+)\]}
MESSAGE_REPLY_SUBJECT_RE = %r{\[[^\]]*msg(\d+)\]} MESSAGE_REPLY_SUBJECT_RE = %r{\[[^\]]*msg(\d+)\]}
def dispatch def dispatch
headers = [email.in_reply_to, email.references].flatten.compact headers = [email.in_reply_to, email.references].flatten.compact
if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE} if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE}
@@ -100,7 +100,7 @@ class MailHandler < ActionMailer::Base
elsif m = email.subject.match(MESSAGE_REPLY_SUBJECT_RE) elsif m = email.subject.match(MESSAGE_REPLY_SUBJECT_RE)
receive_message_reply(m[1].to_i) receive_message_reply(m[1].to_i)
else else
receive_issue dispatch_to_default
end end
rescue ActiveRecord::RecordInvalid => e rescue ActiveRecord::RecordInvalid => e
# TODO: send a email to the user # TODO: send a email to the user
@@ -113,7 +113,11 @@ class MailHandler < ActionMailer::Base
logger.error "MailHandler: unauthorized attempt from #{user}" if logger logger.error "MailHandler: unauthorized attempt from #{user}" if logger
false false
end end
def dispatch_to_default
receive_issue
end
# Creates a new issue # Creates a new issue
def receive_issue def receive_issue
project = target_project project = target_project
@@ -130,7 +134,7 @@ class MailHandler < ActionMailer::Base
issue.subject = '(no subject)' issue.subject = '(no subject)'
end end
issue.description = cleaned_up_text_body issue.description = cleaned_up_text_body
# add To and Cc as watchers before saving so the watchers can reply to Redmine # add To and Cc as watchers before saving so the watchers can reply to Redmine
add_watchers(issue) add_watchers(issue)
issue.save! issue.save!
@@ -138,7 +142,7 @@ class MailHandler < ActionMailer::Base
logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
issue issue
end end
# Adds a note to an existing issue # Adds a note to an existing issue
def receive_issue_reply(issue_id) def receive_issue_reply(issue_id)
issue = Issue.find_by_id(issue_id) issue = Issue.find_by_id(issue_id)
@@ -147,19 +151,20 @@ class MailHandler < ActionMailer::Base
unless @@handler_options[:no_permission_check] unless @@handler_options[:no_permission_check]
raise UnauthorizedAction unless user.allowed_to?(:add_issue_notes, issue.project) || user.allowed_to?(:edit_issues, issue.project) raise UnauthorizedAction unless user.allowed_to?(:add_issue_notes, issue.project) || user.allowed_to?(:edit_issues, issue.project)
end end
# ignore CLI-supplied defaults for new issues # ignore CLI-supplied defaults for new issues
@@handler_options[:issue].clear @@handler_options[:issue].clear
journal = issue.init_journal(user, cleaned_up_text_body) journal = issue.init_journal(user)
issue.safe_attributes = issue_attributes_from_keywords(issue) issue.safe_attributes = issue_attributes_from_keywords(issue)
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
journal.notes = cleaned_up_text_body
add_attachments(issue) add_attachments(issue)
issue.save! issue.save!
logger.info "MailHandler: issue ##{issue.id} updated by #{user}" if logger && logger.info logger.info "MailHandler: issue ##{issue.id} updated by #{user}" if logger && logger.info
journal journal
end end
# Reply will be added to the issue # Reply will be added to the issue
def receive_journal_reply(journal_id) def receive_journal_reply(journal_id)
journal = Journal.find_by_id(journal_id) journal = Journal.find_by_id(journal_id)
@@ -167,17 +172,17 @@ class MailHandler < ActionMailer::Base
receive_issue_reply(journal.journalized_id) receive_issue_reply(journal.journalized_id)
end end
end end
# Receives a reply to a forum message # Receives a reply to a forum message
def receive_message_reply(message_id) def receive_message_reply(message_id)
message = Message.find_by_id(message_id) message = Message.find_by_id(message_id)
if message if message
message = message.root message = message.root
unless @@handler_options[:no_permission_check] unless @@handler_options[:no_permission_check]
raise UnauthorizedAction unless user.allowed_to?(:add_messages, message.project) raise UnauthorizedAction unless user.allowed_to?(:add_messages, message.project)
end end
if !message.locked? if !message.locked?
reply = Message.new(:subject => email.subject.gsub(%r{^.*msg\d+\]}, '').strip, reply = Message.new(:subject => email.subject.gsub(%r{^.*msg\d+\]}, '').strip,
:content => cleaned_up_text_body) :content => cleaned_up_text_body)
@@ -191,9 +196,9 @@ class MailHandler < ActionMailer::Base
end end
end end
end end
def add_attachments(obj) def add_attachments(obj)
if email.has_attachments? if email.attachments && email.attachments.any?
email.attachments.each do |attachment| email.attachments.each do |attachment|
Attachment.create(:container => obj, Attachment.create(:container => obj,
:file => attachment, :file => attachment,
@@ -202,7 +207,7 @@ class MailHandler < ActionMailer::Base
end end
end end
end end
# Adds To and Cc as watchers of the given object if the sender has the # Adds To and Cc as watchers of the given object if the sender has the
# appropriate permission # appropriate permission
def add_watchers(obj) def add_watchers(obj)
@@ -214,7 +219,7 @@ class MailHandler < ActionMailer::Base
end end
end end
end end
def get_keyword(attr, options={}) def get_keyword(attr, options={})
@keywords ||= {} @keywords ||= {}
if @keywords.has_key?(attr) if @keywords.has_key?(attr)
@@ -229,14 +234,14 @@ class MailHandler < ActionMailer::Base
end end
end end
end end
# Destructively extracts the value for +attr+ in +text+ # Destructively extracts the value for +attr+ in +text+
# Returns nil if no matching keyword found # Returns nil if no matching keyword found
def extract_keyword!(text, attr, format=nil) def extract_keyword!(text, attr, format=nil)
keys = [attr.to_s.humanize] keys = [attr.to_s.humanize]
if attr.is_a?(Symbol) if attr.is_a?(Symbol)
keys << l("field_#{attr}", :default => '', :locale => user.language) if user keys << l("field_#{attr}", :default => '', :locale => user.language) if user && user.language.present?
keys << l("field_#{attr}", :default => '', :locale => Setting.default_language) keys << l("field_#{attr}", :default => '', :locale => Setting.default_language) if Setting.default_language.present?
end end
keys.reject! {|k| k.blank?} keys.reject! {|k| k.blank?}
keys.collect! {|k| Regexp.escape(k)} keys.collect! {|k| Regexp.escape(k)}
@@ -253,34 +258,34 @@ class MailHandler < ActionMailer::Base
raise MissingInformation.new('Unable to determine target project') if target.nil? raise MissingInformation.new('Unable to determine target project') if target.nil?
target target
end end
# Returns a Hash of issue attributes extracted from keywords in the email body # Returns a Hash of issue attributes extracted from keywords in the email body
def issue_attributes_from_keywords(issue) def issue_attributes_from_keywords(issue)
assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_user_from_keyword(k) assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_user_from_keyword(k)
assigned_to = nil if assigned_to && !issue.assignable_users.include?(assigned_to) assigned_to = nil if assigned_to && !issue.assignable_users.include?(assigned_to)
attrs = { attrs = {
'tracker_id' => (k = get_keyword(:tracker)) && issue.project.trackers.find_by_name(k).try(:id), 'tracker_id' => (k = get_keyword(:tracker)) && issue.project.trackers.named(k).first.try(:id),
'status_id' => (k = get_keyword(:status)) && IssueStatus.find_by_name(k).try(:id), 'status_id' => (k = get_keyword(:status)) && IssueStatus.named(k).first.try(:id),
'priority_id' => (k = get_keyword(:priority)) && IssuePriority.find_by_name(k).try(:id), 'priority_id' => (k = get_keyword(:priority)) && IssuePriority.named(k).first.try(:id),
'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.find_by_name(k).try(:id), 'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.named(k).first.try(:id),
'assigned_to_id' => assigned_to.try(:id), 'assigned_to_id' => assigned_to.try(:id),
'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) && issue.project.shared_versions.find_by_name(k).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}'), '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}'), 'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
'estimated_hours' => get_keyword(:estimated_hours, :override => true), 'estimated_hours' => get_keyword(:estimated_hours, :override => true),
'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0') 'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0')
}.delete_if {|k, v| v.blank? } }.delete_if {|k, v| v.blank? }
if issue.new_record? && attrs['tracker_id'].nil? if issue.new_record? && attrs['tracker_id'].nil?
attrs['tracker_id'] = issue.project.trackers.find(:first).try(:id) attrs['tracker_id'] = issue.project.trackers.find(:first).try(:id)
end end
attrs attrs
end end
# Returns a Hash of issue custom field values extracted from keywords in the email body # Returns a Hash of issue custom field values extracted from keywords in the email body
def custom_field_values_from_keywords(customized) def custom_field_values_from_keywords(customized)
customized.custom_field_values.inject({}) do |h, v| customized.custom_field_values.inject({}) do |h, v|
if value = get_keyword(v.custom_field.name, :override => true) if value = get_keyword(v.custom_field.name, :override => true)
h[v.custom_field.id.to_s] = value h[v.custom_field.id.to_s] = value
@@ -288,7 +293,7 @@ class MailHandler < ActionMailer::Base
h h
end end
end end
# Returns the text/plain part of the email # Returns the text/plain part of the email
# If not found (eg. HTML-only email), returns the body with tags removed # If not found (eg. HTML-only email), returns the body with tags removed
def plain_text_body def plain_text_body
@@ -309,7 +314,7 @@ class MailHandler < ActionMailer::Base
@plain_text_body.strip! @plain_text_body.strip!
@plain_text_body @plain_text_body
end end
def cleaned_up_text_body def cleaned_up_text_body
cleanup_body(plain_text_body) cleanup_body(plain_text_body)
end end
@@ -317,19 +322,19 @@ class MailHandler < ActionMailer::Base
def self.full_sanitizer def self.full_sanitizer
@full_sanitizer ||= HTML::FullSanitizer.new @full_sanitizer ||= HTML::FullSanitizer.new
end end
# Creates a user account for the +email+ sender # Creates a user account for the +email+ sender
def self.create_user_from_email(email) def self.create_user_from_email(email)
addr = email.from_addrs.to_a.first addr = email.from_addrs.to_a.first
if addr && !addr.spec.blank? if addr && !addr.spec.blank?
user = User.new user = User.new
user.mail = addr.spec user.mail = addr.spec
names = addr.name.blank? ? addr.spec.gsub(/@.*$/, '').split('.') : addr.name.split names = addr.name.blank? ? addr.spec.gsub(/@.*$/, '').split('.') : addr.name.split
user.firstname = names.shift user.firstname = names.shift
user.lastname = names.join(' ') user.lastname = names.join(' ')
user.lastname = '-' if user.lastname.blank? user.lastname = '-' if user.lastname.blank?
user.login = user.mail user.login = user.mail
user.password = ActiveSupport::SecureRandom.hex(5) user.password = ActiveSupport::SecureRandom.hex(5)
user.language = Setting.default_language user.language = Setting.default_language
@@ -338,7 +343,7 @@ class MailHandler < ActionMailer::Base
end end
private private
# Removes the email body of text after the truncation configurations. # Removes the email body of text after the truncation configurations.
def cleanup_body(body) def cleanup_body(body)
delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)} delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)}
+45 -27
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -31,7 +31,7 @@ class Mailer < ActionMailer::Base
h = h.to_s.gsub(%r{\/.*$}, '') unless Redmine::Utils.relative_url_root.blank? h = h.to_s.gsub(%r{\/.*$}, '') unless Redmine::Utils.relative_url_root.blank?
{ :host => h, :protocol => Setting.protocol } { :host => h, :protocol => Setting.protocol }
end end
# Builds a tmail object used to email recipients of the added issue. # Builds a tmail object used to email recipients of the added issue.
# #
# Example: # Example:
@@ -85,7 +85,7 @@ class Mailer < ActionMailer::Base
subject l(:mail_subject_reminder, :count => issues.size, :days => days) subject l(:mail_subject_reminder, :count => issues.size, :days => days)
body :issues => issues, body :issues => issues,
:days => days, :days => days,
:issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort_key => 'due_date', :sort_order => 'asc') :issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort => 'due_date:asc')
render_multipart('reminder', body) render_multipart('reminder', body)
end end
@@ -114,11 +114,11 @@ class Mailer < ActionMailer::Base
added_to_url = '' added_to_url = ''
case container.class.name case container.class.name
when 'Project' when 'Project'
added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container) added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
added_to = "#{l(:label_project)}: #{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} recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
when 'Version' when 'Version'
added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container.project_id) added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
added_to = "#{l(:label_version)}: #{container.name}" 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} recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
when 'Document' when 'Document'
@@ -133,7 +133,7 @@ class Mailer < ActionMailer::Base
:added_to_url => added_to_url :added_to_url => added_to_url
render_multipart('attachments_added', body) render_multipart('attachments_added', body)
end end
# Builds a tmail object used to email recipients of a news' project when a news item is added. # Builds a tmail object used to email recipients of a news' project when a news item is added.
# #
# Example: # Example:
@@ -149,7 +149,25 @@ class Mailer < ActionMailer::Base
render_multipart('news_added', body) render_multipart('news_added', body)
end end
# Builds a tmail object used to email the recipients of the specified message that was posted. # Builds a tmail object used to email recipients of a news' project when a news comment is added.
#
# Example:
# news_comment_added(comment) => tmail 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
message_id comment
recipients news.recipients
cc news.watcher_recipients
subject "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
body :news => news,
:comment => comment,
:news_url => url_for(:controller => 'news', :action => 'show', :id => news)
render_multipart('news_comment_added', body)
end
# Builds a tmail object used to email the recipients of the specified message that was posted.
# #
# Example: # Example:
# message_posted(message) => tmail object # message_posted(message) => tmail object
@@ -166,8 +184,8 @@ class Mailer < ActionMailer::Base
:message_url => url_for(message.event_url) :message_url => url_for(message.event_url)
render_multipart('message_posted', body) render_multipart('message_posted', body)
end end
# Builds a tmail object used to email the recipients of a project of the specified wiki content was added. # Builds a tmail object used to email the recipients of a project of the specified wiki content was added.
# #
# Example: # Example:
# wiki_content_added(wiki_content) => tmail object # wiki_content_added(wiki_content) => tmail object
@@ -183,8 +201,8 @@ class Mailer < ActionMailer::Base
:wiki_content_url => url_for(:controller => 'wiki', :action => 'show', :project_id => wiki_content.project, :id => wiki_content.page.title) :wiki_content_url => url_for(:controller => 'wiki', :action => 'show', :project_id => wiki_content.project, :id => wiki_content.page.title)
render_multipart('wiki_content_added', body) render_multipart('wiki_content_added', body)
end end
# Builds a tmail object used to email the recipients of a project of the specified wiki content was updated. # Builds a tmail object used to email the recipients of a project of the specified wiki content was updated.
# #
# Example: # Example:
# wiki_content_updated(wiki_content) => tmail object # wiki_content_updated(wiki_content) => tmail object
@@ -278,7 +296,7 @@ class Mailer < ActionMailer::Base
return false if (recipients.nil? || recipients.empty?) && return false if (recipients.nil? || recipients.empty?) &&
(cc.nil? || cc.empty?) && (cc.nil? || cc.empty?) &&
(bcc.nil? || bcc.empty?) (bcc.nil? || bcc.empty?)
# Set Message-Id and References # Set Message-Id and References
if @message_id_object if @message_id_object
mail.message_id = self.class.message_id_for(@message_id_object) mail.message_id = self.class.message_id_for(@message_id_object)
@@ -286,7 +304,7 @@ class Mailer < ActionMailer::Base
if @references_objects if @references_objects
mail.references = @references_objects.collect {|o| self.class.message_id_for(o)} mail.references = @references_objects.collect {|o| self.class.message_id_for(o)}
end end
# Log errors when raise_delivery_errors is set to false, Rails does not # Log errors when raise_delivery_errors is set to false, Rails does not
raise_errors = self.class.raise_delivery_errors raise_errors = self.class.raise_delivery_errors
self.class.raise_delivery_errors = true self.class.raise_delivery_errors = true
@@ -296,7 +314,7 @@ class Mailer < ActionMailer::Base
if raise_errors if raise_errors
raise e raise e
elsif mylogger elsif mylogger
mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/email.yml." mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/configuration.yml."
end end
ensure ensure
self.class.raise_delivery_errors = raise_errors self.class.raise_delivery_errors = raise_errors
@@ -326,10 +344,10 @@ class Mailer < ActionMailer::Base
:conditions => s.conditions :conditions => s.conditions
).group_by(&:assigned_to) ).group_by(&:assigned_to)
issues_by_assignee.each do |assignee, issues| issues_by_assignee.each do |assignee, issues|
deliver_reminder(assignee, issues, days) unless assignee.nil? deliver_reminder(assignee, issues, days) if assignee && assignee.active?
end end
end end
# Activates/desactivates email deliveries during +block+ # Activates/desactivates email deliveries during +block+
def self.with_deliveries(enabled = true, &block) def self.with_deliveries(enabled = true, &block)
was_enabled = ActionMailer::Base.perform_deliveries was_enabled = ActionMailer::Base.perform_deliveries
@@ -345,7 +363,7 @@ class Mailer < ActionMailer::Base
@initial_language = current_language @initial_language = current_language
set_language_if_valid Setting.default_language set_language_if_valid Setting.default_language
from Setting.mail_from from Setting.mail_from
# Common headers # Common headers
headers 'X-Mailer' => 'Redmine', headers 'X-Mailer' => 'Redmine',
'X-Redmine-Host' => Setting.host_name, 'X-Redmine-Host' => Setting.host_name,
@@ -368,11 +386,11 @@ class Mailer < ActionMailer::Base
recipients.delete(@author.mail) if recipients recipients.delete(@author.mail) if recipients
cc.delete(@author.mail) if cc cc.delete(@author.mail) if cc
end end
notified_users = [recipients, cc].flatten.compact.uniq notified_users = [recipients, cc].flatten.compact.uniq
# Rails would log recipients only, not cc and bcc # Rails would log recipients only, not cc and bcc
mylogger.info "Sending email notification to: #{notified_users.join(', ')}" if mylogger mylogger.info "Sending email notification to: #{notified_users.join(', ')}" if mylogger
# Blind carbon copy recipients # Blind carbon copy recipients
if Setting.bcc_recipients? if Setting.bcc_recipients?
bcc(notified_users) bcc(notified_users)
@@ -388,7 +406,7 @@ class Mailer < ActionMailer::Base
# #
# https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type # https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type
# https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts # https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts
def render_multipart(method_name, body) def render_multipart(method_name, body)
if Setting.plain_text_mail? if Setting.plain_text_mail?
content_type "text/plain" content_type "text/plain"
@@ -404,29 +422,29 @@ class Mailer < ActionMailer::Base
def self.controller_path def self.controller_path
'' ''
end unless respond_to?('controller_path') end unless respond_to?('controller_path')
# Returns a predictable Message-Id for the given object # Returns a predictable Message-Id for the given object
def self.message_id_for(object) def self.message_id_for(object)
# id + timestamp should reduce the odds of a collision # id + timestamp should reduce the odds of a collision
# as far as we don't send multiple emails for the same object # as far as we don't send multiple emails for the same object
timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on) 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")}" hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
host = Setting.mail_from.to_s.gsub(%r{^.*@}, '') host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
host = "#{::Socket.gethostname}.redmine" if host.empty? host = "#{::Socket.gethostname}.redmine" if host.empty?
"<#{hash}@#{host}>" "<#{hash}@#{host}>"
end end
private private
def message_id(object) def message_id(object)
@message_id_object = object @message_id_object = object
end end
def references(object) def references(object)
@references_objects ||= [] @references_objects ||= []
@references_objects << object @references_objects << object
end end
def mylogger def mylogger
RAILS_DEFAULT_LOGGER RAILS_DEFAULT_LOGGER
end end
+21 -18
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -21,10 +21,10 @@ class Message < ActiveRecord::Base
acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC" acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
acts_as_attachable acts_as_attachable
belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id' belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
acts_as_searchable :columns => ['subject', 'content'], acts_as_searchable :columns => ['subject', 'content'],
:include => {:board => :project}, :include => {:board => :project},
:project_key => 'project_id', :project_key => "#{Board.table_name}.project_id",
:date_column => "#{table_name}.created_on" :date_column => "#{table_name}.created_on"
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"}, acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
:description => :content, :description => :content,
@@ -35,29 +35,32 @@ class Message < ActiveRecord::Base
acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]}, acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
:author_key => :author_id :author_key => :author_id
acts_as_watchable acts_as_watchable
attr_protected :locked, :sticky attr_protected :locked, :sticky
validates_presence_of :board, :subject, :content validates_presence_of :board, :subject, :content
validates_length_of :subject, :maximum => 255 validates_length_of :subject, :maximum => 255
after_create :add_author_as_watcher after_create :add_author_as_watcher
named_scope :visible, lambda {|*args| { :include => {:board => :project},
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_messages, *args) } }
def visible?(user=User.current) def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_messages, project) !user.nil? && user.allowed_to?(:view_messages, project)
end end
def validate_on_create def validate_on_create
# Can not reply to a locked topic # Can not reply to a locked topic
errors.add_to_base 'Topic is locked' if root.locked? && self != root errors.add_to_base 'Topic is locked' if root.locked? && self != root
end end
def after_create def after_create
if parent if parent
parent.reload.update_attribute(:last_reply_id, self.id) parent.reload.update_attribute(:last_reply_id, self.id)
end end
board.reset_counters! board.reset_counters!
end end
def after_update def after_update
if board_id_changed? if board_id_changed?
Message.update_all("board_id = #{board_id}", ["id = ? OR parent_id = ?", root.id, root.id]) Message.update_all("board_id = #{board_id}", ["id = ? OR parent_id = ?", root.id, root.id])
@@ -65,19 +68,19 @@ class Message < ActiveRecord::Base
Board.reset_counters!(board_id) Board.reset_counters!(board_id)
end end
end end
def after_destroy def after_destroy
board.reset_counters! board.reset_counters!
end end
def sticky=(arg) def sticky=(arg)
write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0) write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
end end
def sticky? def sticky?
sticky == 1 sticky == 1
end end
def project def project
board.project board.project
end end
@@ -89,9 +92,9 @@ class Message < ActiveRecord::Base
def destroyable_by?(usr) def destroyable_by?(usr)
usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project))) usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
end end
private private
def add_author_as_watcher def add_author_as_watcher
Watcher.create(:watchable => self.root, :user => author) Watcher.create(:watchable => self.root, :user => author)
end end
+4 -4
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+18 -9
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2008 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -19,7 +19,7 @@ class News < ActiveRecord::Base
belongs_to :project belongs_to :project
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on" has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
validates_presence_of :title, :description validates_presence_of :title, :description
validates_length_of :title, :maximum => 60 validates_length_of :title, :maximum => 60
validates_length_of :summary, :maximum => 255 validates_length_of :summary, :maximum => 255
@@ -28,18 +28,27 @@ class News < ActiveRecord::Base
acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}} acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
acts_as_activity_provider :find_options => {:include => [:project, :author]}, acts_as_activity_provider :find_options => {:include => [:project, :author]},
:author_key => :author_id :author_key => :author_id
acts_as_watchable
named_scope :visible, lambda {|*args| {
after_create :add_author_as_watcher
named_scope :visible, lambda {|*args| {
:include => :project, :include => :project,
:conditions => Project.allowed_to_condition(args.first || User.current, :view_news) :conditions => Project.allowed_to_condition(args.shift || User.current, :view_news, *args)
}} }}
def visible?(user=User.current) def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_news, project) !user.nil? && user.allowed_to?(:view_news, project)
end end
# returns latest news for projects visible by user # returns latest news for projects visible by user
def self.latest(user = User.current, count = 5) def self.latest(user = User.current, count = 5)
find(:all, :limit => count, :conditions => Project.allowed_to_condition(user, :view_news), :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC") find(:all, :limit => count, :conditions => Project.allowed_to_condition(user, :view_news), :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
end end
private
def add_author_as_watcher
Watcher.create(:watchable => self, :user => author)
end
end end
+101 -51
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -43,7 +43,7 @@ class Project < ActiveRecord::Base
has_many :time_entries, :dependent => :delete_all has_many :time_entries, :dependent => :delete_all
has_many :queries, :dependent => :delete_all has_many :queries, :dependent => :delete_all
has_many :documents, :dependent => :destroy has_many :documents, :dependent => :destroy
has_many :news, :dependent => :delete_all, :include => :author has_many :news, :dependent => :destroy, :include => :author
has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name" has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
has_many :boards, :dependent => :destroy, :order => "position ASC" has_many :boards, :dependent => :destroy, :order => "position ASC"
has_one :repository, :dependent => :destroy has_one :repository, :dependent => :destroy
@@ -56,7 +56,7 @@ class Project < ActiveRecord::Base
:join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
:association_foreign_key => 'custom_field_id' :association_foreign_key => 'custom_field_id'
acts_as_nested_set :order => 'name' acts_as_nested_set :order => 'name', :dependent => :destroy
acts_as_attachable :view_permission => :view_files, acts_as_attachable :view_permission => :view_files,
:delete_permission => :manage_files :delete_permission => :manage_files
@@ -66,7 +66,7 @@ class Project < ActiveRecord::Base
:url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o}}, :url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o}},
:author => nil :author => nil
attr_protected :status, :enabled_module_names attr_protected :status
validates_presence_of :name, :identifier validates_presence_of :name, :identifier
validates_uniqueness_of :identifier validates_uniqueness_of :identifier
@@ -79,12 +79,12 @@ class Project < ActiveRecord::Base
# reserved words # reserved words
validates_exclusion_of :identifier, :in => %w( new ) validates_exclusion_of :identifier, :in => %w( new )
before_destroy :delete_all_members, :destroy_children before_destroy :delete_all_members
named_scope :has_module, lambda { |mod| { :conditions => ["#{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name=?)", mod.to_s] } } named_scope :has_module, lambda { |mod| { :conditions => ["#{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name=?)", mod.to_s] } }
named_scope :active, { :conditions => "#{Project.table_name}.status = #{STATUS_ACTIVE}"} named_scope :active, { :conditions => "#{Project.table_name}.status = #{STATUS_ACTIVE}"}
named_scope :all_public, { :conditions => { :is_public => true } } named_scope :all_public, { :conditions => { :is_public => true } }
named_scope :visible, lambda { { :conditions => Project.visible_by(User.current) } } named_scope :visible, lambda {|*args| {:conditions => Project.visible_condition(args.shift || User.current, *args) }}
def initialize(attributes = nil) def initialize(attributes = nil)
super super
@@ -115,27 +115,36 @@ class Project < ActiveRecord::Base
# returns latest created projects # returns latest created projects
# non public projects will be returned only if user is a member of those # non public projects will be returned only if user is a member of those
def self.latest(user=nil, count=5) def self.latest(user=nil, count=5)
find(:all, :limit => count, :conditions => visible_by(user), :order => "created_on DESC") visible(user).find(:all, :limit => count, :order => "created_on DESC")
end end
# Returns a SQL :conditions string used to find all active projects for the specified user. # Returns true if the project is visible to +user+ or to the current user.
# def visible?(user=User.current)
# Examples: user.allowed_to?(:view_project, self)
# Projects.visible_by(admin) => "projects.status = 1"
# Projects.visible_by(normal_user) => "projects.status = 1 AND projects.is_public = 1"
def self.visible_by(user=nil)
user ||= User.current
if user && user.admin?
return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
elsif user && user.memberships.any?
return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND (#{Project.table_name}.is_public = #{connection.quoted_true} or #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')}))"
else
return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = #{connection.quoted_true}"
end
end end
def self.visible_by(user=nil)
ActiveSupport::Deprecation.warn "Project.visible_by is deprecated and will be removed in Redmine 1.3.0. Use Project.visible_condition instead."
visible_condition(user || User.current)
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={}) def self.allowed_to_condition(user, permission, options={})
statements = []
base_statement = "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}" base_statement = "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
if perm = Redmine::AccessControl.permission(permission) if perm = Redmine::AccessControl.permission(permission)
unless perm.project_module.nil? unless perm.project_module.nil?
@@ -148,24 +157,37 @@ class Project < ActiveRecord::Base
project_statement << " OR (#{Project.table_name}.lft > #{options[:project].lft} AND #{Project.table_name}.rgt < #{options[:project].rgt})" if options[:with_subprojects] 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})" base_statement = "(#{project_statement}) AND (#{base_statement})"
end end
if user.admin? if user.admin?
# no restriction base_statement
else else
statements << "1=0" statement_by_role = {}
if user.logged? unless options[:member]
if Role.non_member.allowed_to?(permission) && !options[:member] role = user.logged? ? Role.non_member : Role.anonymous
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if role.allowed_to?(permission)
statement_by_role[role] = "#{Project.table_name}.is_public = #{connection.quoted_true}"
end end
allowed_project_ids = user.memberships.select {|m| m.roles.detect {|role| role.allowed_to?(permission)}}.collect {|m| m.project_id} end
statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any? if user.logged?
user.projects_by_role.each do |role, projects|
if role.allowed_to?(permission)
statement_by_role[role] = "#{Project.table_name}.id IN (#{projects.collect(&:id).join(',')})"
end
end
end
if statement_by_role.empty?
"1=0"
else else
if Role.anonymous.allowed_to?(permission) && !options[:member] if block_given?
# anonymous user allowed on public project statement_by_role.each do |role, statement|
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if s = yield(role, user)
end statement_by_role[role] = "(#{statement} AND (#{s}))"
end
end
end
"((#{base_statement}) AND (#{statement_by_role.values.join(' OR ')}))"
end end
end end
statements.empty? ? base_statement : "((#{base_statement}) AND (#{statements.join(' OR ')}))"
end end
# Returns the Systemwide and project specific activities # Returns the Systemwide and project specific activities
@@ -347,7 +369,7 @@ class Project < ActiveRecord::Base
# Returns an array of the trackers used by the project and its active sub projects # Returns an array of the trackers used by the project and its active sub projects
def rolled_up_trackers def rolled_up_trackers
@rolled_up_trackers ||= @rolled_up_trackers ||=
Tracker.find(:all, :include => :projects, Tracker.find(:all, :joins => :projects,
:select => "DISTINCT #{Tracker.table_name}.*", :select => "DISTINCT #{Tracker.table_name}.*",
:conditions => ["#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status = #{STATUS_ACTIVE}", lft, rgt], :conditions => ["#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status = #{STATUS_ACTIVE}", lft, rgt],
:order => "#{Tracker.table_name}.position") :order => "#{Tracker.table_name}.position")
@@ -373,15 +395,17 @@ class Project < ActiveRecord::Base
# Returns a scope of the Versions used by the project # Returns a scope of the Versions used by the project
def shared_versions def shared_versions
@shared_versions ||= @shared_versions ||= begin
r = root? ? self : root
Version.scoped(:include => :project, Version.scoped(:include => :project,
:conditions => "#{Project.table_name}.id = #{id}" + :conditions => "#{Project.table_name}.id = #{id}" +
" OR (#{Project.table_name}.status = #{Project::STATUS_ACTIVE} AND (" + " OR (#{Project.table_name}.status = #{Project::STATUS_ACTIVE} AND (" +
" #{Version.table_name}.sharing = 'system'" + " #{Version.table_name}.sharing = 'system'" +
" OR (#{Project.table_name}.lft >= #{root.lft} AND #{Project.table_name}.rgt <= #{root.rgt} AND #{Version.table_name}.sharing = 'tree')" + " 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 IN ('hierarchy', 'descendants'))" +
" OR (#{Project.table_name}.lft > #{lft} AND #{Project.table_name}.rgt < #{rgt} AND #{Version.table_name}.sharing = 'hierarchy')" + " 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 # Returns a hash of project users grouped by role
@@ -423,6 +447,12 @@ class Project < ActiveRecord::Base
def all_issue_custom_fields def all_issue_custom_fields
@all_issue_custom_fields ||= (IssueCustomField.for_all + issue_custom_fields).uniq.sort @all_issue_custom_fields ||= (IssueCustomField.for_all + issue_custom_fields).uniq.sort
end 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 def project
self self
@@ -509,10 +539,7 @@ class Project < ActiveRecord::Base
def enabled_module_names=(module_names) def enabled_module_names=(module_names)
if module_names && module_names.is_a?(Array) if module_names && module_names.is_a?(Array)
module_names = module_names.collect(&:to_s).reject(&:blank?) module_names = module_names.collect(&:to_s).reject(&:blank?)
# remove disabled modules self.enabled_modules = module_names.collect {|name| enabled_modules.detect {|mod| mod.name == name} || EnabledModule.new(:name => name)}
enabled_modules.each {|mod| mod.destroy unless module_names.include?(mod.name)}
# add new modules
module_names.reject {|name| module_enabled?(name)}.each {|name| enabled_modules << EnabledModule.new(:name => name)}
else else
enabled_modules.clear enabled_modules.clear
end end
@@ -522,7 +549,27 @@ class Project < ActiveRecord::Base
def enabled_module_names def enabled_module_names
enabled_modules.collect(&:name) enabled_modules.collect(&:name)
end 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', safe_attributes 'name',
'description', 'description',
'homepage', 'homepage',
@@ -533,6 +580,9 @@ class Project < ActiveRecord::Base
'tracker_ids', 'tracker_ids',
'issue_custom_field_ids' 'issue_custom_field_ids'
safe_attributes 'enabled_module_names',
:if => lambda {|project, user| project.new_record? || user.allowed_to?(:select_project_modules, project) }
# Returns an array of projects that are in this project's hierarchy # Returns an array of projects that are in this project's hierarchy
# #
# Example: parents, children, siblings # Example: parents, children, siblings
@@ -618,13 +668,6 @@ class Project < ActiveRecord::Base
private private
# Destroys children before destroying self
def destroy_children
children.each do |child|
child.destroy
end
end
# Copies wiki from +project+ # Copies wiki from +project+
def copy_wiki(project) def copy_wiki(project)
# Check that the source project has a wiki first # Check that the source project has a wiki first
@@ -671,6 +714,7 @@ class Project < ActiveRecord::Base
end end
# Copies issues from +project+ # Copies issues from +project+
# Note: issues assigned to a closed version won't be copied due to validation rules
def copy_issues(project) def copy_issues(project)
# Stores the source issue id as a key and the copied issues as the # Stores the source issue id as a key and the copied issues as the
# value. Used to map the two togeather for issue relations. # value. Used to map the two togeather for issue relations.
@@ -740,7 +784,12 @@ class Project < ActiveRecord::Base
# Copies members from +project+ # Copies members from +project+
def copy_members(project) def copy_members(project)
project.memberships.each do |member| # 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 = Member.new
new_member.attributes = member.attributes.dup.except("id", "project_id", "created_on") new_member.attributes = member.attributes.dup.except("id", "project_id", "created_on")
# only copy non inherited roles # only copy non inherited roles
@@ -760,6 +809,7 @@ class Project < ActiveRecord::Base
new_query.attributes = query.attributes.dup.except("id", "project_id", "sort_criteria") 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.sort_criteria = query.sort_criteria if query.sort_criteria
new_query.project = self new_query.project = self
new_query.user_id = query.user_id
self.queries << new_query self.queries << new_query
end end
end end
+138 -104
View File
@@ -1,24 +1,24 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2008 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class QueryColumn class QueryColumn
attr_accessor :name, :sortable, :groupable, :default_order attr_accessor :name, :sortable, :groupable, :default_order
include Redmine::I18n include Redmine::I18n
def initialize(name, options={}) def initialize(name, options={})
self.name = name self.name = name
self.sortable = options[:sortable] self.sortable = options[:sortable]
@@ -29,19 +29,23 @@ class QueryColumn
self.default_order = options[:default_order] self.default_order = options[:default_order]
@caption_key = options[:caption] || "field_#{name}" @caption_key = options[:caption] || "field_#{name}"
end end
def caption def caption
l(@caption_key) l(@caption_key)
end end
# Returns true if the column is sortable, otherwise false # Returns true if the column is sortable, otherwise false
def sortable? def sortable?
!sortable.nil? !sortable.nil?
end end
def value(issue) def value(issue)
issue.send name issue.send name
end end
def css_classes
name
end
end end
class QueryCustomFieldColumn < QueryColumn class QueryCustomFieldColumn < QueryColumn
@@ -55,37 +59,41 @@ class QueryCustomFieldColumn < QueryColumn
self.groupable ||= false self.groupable ||= false
@cf = custom_field @cf = custom_field
end end
def caption def caption
@cf.name @cf.name
end end
def custom_field def custom_field
@cf @cf
end end
def value(issue) def value(issue)
cv = issue.custom_values.detect {|v| v.custom_field_id == @cf.id} cv = issue.custom_values.detect {|v| v.custom_field_id == @cf.id}
cv && @cf.cast_value(cv.value) cv && @cf.cast_value(cv.value)
end end
def css_classes
@css_classes ||= "#{name} #{@cf.field_format}"
end
end end
class Query < ActiveRecord::Base class Query < ActiveRecord::Base
class StatementInvalid < ::ActiveRecord::StatementInvalid class StatementInvalid < ::ActiveRecord::StatementInvalid
end end
belongs_to :project belongs_to :project
belongs_to :user belongs_to :user
serialize :filters serialize :filters
serialize :column_names serialize :column_names
serialize :sort_criteria, Array serialize :sort_criteria, Array
attr_protected :project_id, :user_id attr_protected :project_id, :user_id
validates_presence_of :name, :on => :save validates_presence_of :name, :on => :save
validates_length_of :name, :maximum => 255 validates_length_of :name, :maximum => 255
@@operators = { "=" => :label_equals, @@operators = { "=" => :label_equals,
"!" => :label_not_equals, "!" => :label_not_equals,
"o" => :label_open_issues, "o" => :label_open_issues,
"c" => :label_closed_issues, "c" => :label_closed_issues,
@@ -105,7 +113,7 @@ class Query < ActiveRecord::Base
"!~" => :label_not_contains } "!~" => :label_not_contains }
cattr_reader :operators cattr_reader :operators
@@operators_by_filter_type = { :list => [ "=", "!" ], @@operators_by_filter_type = { :list => [ "=", "!" ],
:list_status => [ "o", "=", "!", "c", "*" ], :list_status => [ "o", "=", "!", "c", "*" ],
:list_optional => [ "=", "!", "!*", "*" ], :list_optional => [ "=", "!", "!*", "*" ],
@@ -137,27 +145,32 @@ class Query < ActiveRecord::Base
QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'), QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'),
] ]
cattr_reader :available_columns cattr_reader :available_columns
def initialize(attributes = nil) def initialize(attributes = nil)
super attributes super attributes
self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} } self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
end end
def after_initialize def after_initialize
# Store the fact that project is nil (used in #editable_by?) # Store the fact that project is nil (used in #editable_by?)
@is_for_all = project.nil? @is_for_all = project.nil?
end end
def validate def validate
filters.each_key do |field| filters.each_key do |field|
errors.add label_for(field), :blank unless errors.add label_for(field), :blank unless
# filter requires one or more values # filter requires one or more values
(values_for(field) and !values_for(field).first.blank?) or (values_for(field) and !values_for(field).first.blank?) or
# filter doesn't require any value # filter doesn't require any value
["o", "c", "!*", "*", "t", "w"].include? operator_for(field) ["o", "c", "!*", "*", "t", "w"].include? operator_for(field)
end if filters end if filters
end end
# Returns true if the query is visible to +user+ or the current user.
def visible?(user=User.current)
self.is_public? || self.user_id == user.id
end
def editable_by?(user) def editable_by?(user)
return false unless user return false unless user
# Admin can edit them all and regular users can edit their private queries # Admin can edit them all and regular users can edit their private queries
@@ -165,23 +178,23 @@ class Query < ActiveRecord::Base
# Members can not edit public queries that are for all project (only admin is allowed to) # 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) is_public && !@is_for_all && user.allowed_to?(:manage_public_queries, project)
end end
def available_filters def available_filters
return @available_filters if @available_filters return @available_filters if @available_filters
trackers = project.nil? ? Tracker.find(:all, :order => 'position') : project.rolled_up_trackers trackers = project.nil? ? Tracker.find(:all, :order => 'position') : project.rolled_up_trackers
@available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } }, @available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
"tracker_id" => { :type => :list, :order => 2, :values => trackers.collect{|s| [s.name, s.id.to_s] } }, "tracker_id" => { :type => :list, :order => 2, :values => trackers.collect{|s| [s.name, s.id.to_s] } },
"priority_id" => { :type => :list, :order => 3, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] } }, "priority_id" => { :type => :list, :order => 3, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] } },
"subject" => { :type => :text, :order => 8 }, "subject" => { :type => :text, :order => 8 },
"created_on" => { :type => :date_past, :order => 9 }, "created_on" => { :type => :date_past, :order => 9 },
"updated_on" => { :type => :date_past, :order => 10 }, "updated_on" => { :type => :date_past, :order => 10 },
"start_date" => { :type => :date, :order => 11 }, "start_date" => { :type => :date, :order => 11 },
"due_date" => { :type => :date, :order => 12 }, "due_date" => { :type => :date, :order => 12 },
"estimated_hours" => { :type => :integer, :order => 13 }, "estimated_hours" => { :type => :integer, :order => 13 },
"done_ratio" => { :type => :integer, :order => 14 }} "done_ratio" => { :type => :integer, :order => 14 }}
user_values = [] user_values = []
user_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? user_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
if project if project
@@ -191,7 +204,7 @@ class Query < ActiveRecord::Base
if all_projects.any? if all_projects.any?
# members of visible projects # members of visible projects
user_values += User.active.find(:all, :conditions => ["#{User.table_name}.id IN (SELECT DISTINCT user_id FROM members WHERE project_id IN (?))", all_projects.collect(&:id)]).sort.collect{|s| [s.name, s.id.to_s] } user_values += User.active.find(:all, :conditions => ["#{User.table_name}.id IN (SELECT DISTINCT user_id FROM members WHERE project_id IN (?))", all_projects.collect(&:id)]).sort.collect{|s| [s.name, s.id.to_s] }
# project filter # project filter
project_values = [] project_values = []
Project.project_tree(all_projects) do |p, level| Project.project_tree(all_projects) do |p, level|
@@ -209,21 +222,26 @@ class Query < ActiveRecord::Base
role_values = Role.givable.collect {|r| [r.name, r.id.to_s] } role_values = Role.givable.collect {|r| [r.name, r.id.to_s] }
@available_filters["assigned_to_role"] = { :type => :list_optional, :order => 7, :values => role_values } unless role_values.empty? @available_filters["assigned_to_role"] = { :type => :list_optional, :order => 7, :values => role_values } unless role_values.empty?
if User.current.logged? if User.current.logged?
@available_filters["watcher_id"] = { :type => :list, :order => 15, :values => [["<< #{l(:label_me)} >>", "me"]] } @available_filters["watcher_id"] = { :type => :list, :order => 15, :values => [["<< #{l(:label_me)} >>", "me"]] }
end end
if project if project
# project specific filters # project specific filters
unless @project.issue_categories.empty? categories = @project.issue_categories.all
@available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } } unless categories.empty?
@available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => categories.collect{|s| [s.name, s.id.to_s] } }
end end
unless @project.shared_versions.empty? versions = @project.shared_versions.all
@available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.shared_versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } } unless versions.empty?
@available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } }
end end
unless @project.descendants.active.empty? unless @project.leaf?
@available_filters["subproject_id"] = { :type => :list_subprojects, :order => 13, :values => @project.descendants.visible.collect{|s| [s.name, s.id.to_s] } } subprojects = @project.descendants.visible.all
unless subprojects.empty?
@available_filters["subproject_id"] = { :type => :list_subprojects, :order => 13, :values => subprojects.collect{|s| [s.name, s.id.to_s] } }
end
end end
add_custom_fields_filters(@project.all_issue_custom_fields) add_custom_fields_filters(@project.all_issue_custom_fields)
else else
@@ -236,7 +254,7 @@ class Query < ActiveRecord::Base
end end
@available_filters @available_filters
end end
def add_filter(field, operator, values) def add_filter(field, operator, values)
# values must be an array # values must be an array
return unless values and values.is_a? Array # and !values.first.empty? return unless values and values.is_a? Array # and !values.first.empty?
@@ -251,7 +269,7 @@ class Query < ActiveRecord::Base
filters[field] = {:operator => operator, :values => values } filters[field] = {:operator => operator, :values => values }
end end
end end
def add_short_filter(field, expression) def add_short_filter(field, expression)
return unless expression return unless expression
parms = expression.scan(/^(o|c|!\*|!|\*)?(.*)$/).first parms = expression.scan(/^(o|c|!\*|!|\*)?(.*)$/).first
@@ -266,19 +284,19 @@ class Query < ActiveRecord::Base
end end
end end
end end
def has_filter?(field) def has_filter?(field)
filters and filters[field] filters and filters[field]
end end
def operator_for(field) def operator_for(field)
has_filter?(field) ? filters[field][:operator] : nil has_filter?(field) ? filters[field][:operator] : nil
end end
def values_for(field) def values_for(field)
has_filter?(field) ? filters[field][:values] : nil has_filter?(field) ? filters[field][:values] : nil
end end
def label_for(field) def label_for(field)
label = available_filters[field][:name] if available_filters.has_key?(field) label = available_filters[field][:name] if available_filters.has_key?(field)
label ||= field.gsub(/\_id$/, "") label ||= field.gsub(/\_id$/, "")
@@ -290,17 +308,17 @@ class Query < ActiveRecord::Base
@available_columns += (project ? @available_columns += (project ?
project.all_issue_custom_fields : project.all_issue_custom_fields :
IssueCustomField.find(:all) IssueCustomField.find(:all)
).collect {|cf| QueryCustomFieldColumn.new(cf) } ).collect {|cf| QueryCustomFieldColumn.new(cf) }
end end
def self.available_columns=(v) def self.available_columns=(v)
self.available_columns = (v) self.available_columns = (v)
end end
def self.add_available_column(column) def self.add_available_column(column)
self.available_columns << (column) if column.is_a?(QueryColumn) self.available_columns << (column) if column.is_a?(QueryColumn)
end end
# Returns an array of columns that can be used to group the results # Returns an array of columns that can be used to group the results
def groupable_columns def groupable_columns
available_columns.select {|c| c.groupable} available_columns.select {|c| c.groupable}
@@ -313,39 +331,42 @@ class Query < ActiveRecord::Base
h h
}) })
end end
def columns def columns
if has_default_columns? # preserve the column_names order
available_columns.select do |c| (has_default_columns? ? default_columns_names : column_names).collect do |name|
# Adds the project column by default for cross-project lists available_columns.find { |col| col.name == name }
Setting.issue_list_default_columns.include?(c.name.to_s) || (c.name == :project && project.nil?) end.compact
end end
else
# preserve the column_names order def default_columns_names
column_names.collect {|name| available_columns.find {|col| col.name == name}}.compact @default_columns_names ||= begin
default_columns = Setting.issue_list_default_columns.map(&:to_sym)
project.present? ? default_columns : [:project] | default_columns
end end
end end
def column_names=(names) def column_names=(names)
if names if names
names = names.select {|n| n.is_a?(Symbol) || !n.blank? } names = names.select {|n| n.is_a?(Symbol) || !n.blank? }
names = names.collect {|n| n.is_a?(Symbol) ? n : n.to_sym } names = names.collect {|n| n.is_a?(Symbol) ? n : n.to_sym }
# Set column_names to nil if default columns # Set column_names to nil if default columns
if names.map(&:to_s) == Setting.issue_list_default_columns if names == default_columns_names
names = nil names = nil
end end
end end
write_attribute(:column_names, names) write_attribute(:column_names, names)
end end
def has_column?(column) def has_column?(column)
column_names && column_names.include?(column.name) column_names && column_names.include?(column.name)
end end
def has_default_columns? def has_default_columns?
column_names.nil? || column_names.empty? column_names.nil? || column_names.empty?
end end
def sort_criteria=(arg) def sort_criteria=(arg)
c = [] c = []
if arg.is_a?(Hash) if arg.is_a?(Hash)
@@ -354,19 +375,19 @@ class Query < ActiveRecord::Base
c = arg.select {|k,o| !k.to_s.blank?}.slice(0,3).collect {|k,o| [k.to_s, o == 'desc' ? o : 'asc']} c = arg.select {|k,o| !k.to_s.blank?}.slice(0,3).collect {|k,o| [k.to_s, o == 'desc' ? o : 'asc']}
write_attribute(:sort_criteria, c) write_attribute(:sort_criteria, c)
end end
def sort_criteria def sort_criteria
read_attribute(:sort_criteria) || [] read_attribute(:sort_criteria) || []
end end
def sort_criteria_key(arg) def sort_criteria_key(arg)
sort_criteria && sort_criteria[arg] && sort_criteria[arg].first sort_criteria && sort_criteria[arg] && sort_criteria[arg].first
end end
def sort_criteria_order(arg) def sort_criteria_order(arg)
sort_criteria && sort_criteria[arg] && sort_criteria[arg].last sort_criteria && sort_criteria[arg] && sort_criteria[arg].last
end end
# Returns the SQL sort order that should be prepended for grouping # Returns the SQL sort order that should be prepended for grouping
def group_by_sort_order def group_by_sort_order
if grouped? && (column = group_by_column) if grouped? && (column = group_by_column)
@@ -375,20 +396,20 @@ class Query < ActiveRecord::Base
"#{column.sortable} #{column.default_order}" "#{column.sortable} #{column.default_order}"
end end
end end
# Returns true if the query is a grouped query # Returns true if the query is a grouped query
def grouped? def grouped?
!group_by_column.nil? !group_by_column.nil?
end end
def group_by_column def group_by_column
groupable_columns.detect {|c| c.groupable && c.name.to_s == group_by} groupable_columns.detect {|c| c.groupable && c.name.to_s == group_by}
end end
def group_by_statement def group_by_statement
group_by_column.try(:groupable) group_by_column.try(:groupable)
end end
def project_statement def project_statement
project_clauses = [] project_clauses = []
if project && !@project.descendants.active.empty? if project && !@project.descendants.active.empty?
@@ -411,8 +432,7 @@ class Query < ActiveRecord::Base
elsif project elsif project
project_clauses << "#{Project.table_name}.id = %d" % project.id project_clauses << "#{Project.table_name}.id = %d" % project.id
end end
project_clauses << Project.allowed_to_condition(User.current, :view_issues) project_clauses.any? ? project_clauses.join(' AND ') : nil
project_clauses.join(' AND ')
end end
def statement def statement
@@ -423,12 +443,12 @@ class Query < ActiveRecord::Base
v = values_for(field).clone v = values_for(field).clone
next unless v and !v.empty? next unless v and !v.empty?
operator = operator_for(field) operator = operator_for(field)
# "me" value subsitution # "me" value subsitution
if %w(assigned_to_id author_id watcher_id).include?(field) if %w(assigned_to_id author_id watcher_id).include?(field)
v.push(User.current.logged? ? User.current.id.to_s : "0") if v.delete("me") v.push(User.current.logged? ? User.current.id.to_s : "0") if v.delete("me")
end end
sql = '' sql = ''
if field =~ /^cf_(\d+)$/ if field =~ /^cf_(\d+)$/
# custom field # custom field
@@ -460,7 +480,7 @@ class Query < ActiveRecord::Base
end end
user_ids.flatten.uniq.compact user_ids.flatten.uniq.compact
}.sort.collect(&:to_s) }.sort.collect(&:to_s)
sql << '(' + sql_for_field("assigned_to_id", operator, members_of_groups, Issue.table_name, "assigned_to_id", false) + ')' sql << '(' + sql_for_field("assigned_to_id", operator, members_of_groups, Issue.table_name, "assigned_to_id", false) + ')'
elsif field == "assigned_to_role" # named field elsif field == "assigned_to_role" # named field
@@ -474,14 +494,14 @@ class Query < ActiveRecord::Base
roles = Role.givable.find_all_by_id(v) roles = Role.givable.find_all_by_id(v)
end end
roles ||= [] roles ||= []
members_of_roles = roles.inject([]) {|user_ids, role| members_of_roles = roles.inject([]) {|user_ids, role|
if role && role.members if role && role.members
user_ids << role.members.collect(&:user_id) user_ids << role.members.collect(&:user_id)
end end
user_ids.flatten.uniq.compact user_ids.flatten.uniq.compact
}.sort.collect(&:to_s) }.sort.collect(&:to_s)
sql << '(' + sql_for_field("assigned_to_id", operator, members_of_roles, Issue.table_name, "assigned_to_id", false) + ')' sql << '(' + sql_for_field("assigned_to_id", operator, members_of_roles, Issue.table_name, "assigned_to_id", false) + ')'
else else
# regular field # regular field
@@ -490,26 +510,29 @@ class Query < ActiveRecord::Base
sql << '(' + sql_for_field(field, operator, v, db_table, db_field) + ')' sql << '(' + sql_for_field(field, operator, v, db_table, db_field) + ')'
end end
filters_clauses << sql filters_clauses << sql
end if filters and valid? end if filters and valid?
(filters_clauses << project_statement).join(' AND ') filters_clauses << project_statement
filters_clauses.reject!(&:blank?)
filters_clauses.any? ? filters_clauses.join(' AND ') : nil
end end
# Returns the issue count # Returns the issue count
def issue_count def issue_count
Issue.count(:include => [:status, :project], :conditions => statement) Issue.visible.count(:include => [:status, :project], :conditions => statement)
rescue ::ActiveRecord::StatementInvalid => e rescue ::ActiveRecord::StatementInvalid => e
raise StatementInvalid.new(e.message) raise StatementInvalid.new(e.message)
end end
# Returns the issue count by group or nil if query is not grouped # Returns the issue count by group or nil if query is not grouped
def issue_count_by_group def issue_count_by_group
r = nil r = nil
if grouped? if grouped?
begin begin
# Rails will raise an (unexpected) RecordNotFound if there's only a nil group value # Rails will raise an (unexpected) RecordNotFound if there's only a nil group value
r = Issue.count(:group => group_by_statement, :include => [:status, :project], :conditions => statement) r = Issue.visible.count(:group => group_by_statement, :include => [:status, :project], :conditions => statement)
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
r = {nil => issue_count} r = {nil => issue_count}
end end
@@ -522,14 +545,14 @@ class Query < ActiveRecord::Base
rescue ::ActiveRecord::StatementInvalid => e rescue ::ActiveRecord::StatementInvalid => e
raise StatementInvalid.new(e.message) raise StatementInvalid.new(e.message)
end end
# Returns the issues # Returns the issues
# Valid options are :order, :offset, :limit, :include, :conditions # Valid options are :order, :offset, :limit, :include, :conditions
def issues(options={}) def issues(options={})
order_option = [group_by_sort_order, options[:order]].reject {|s| s.blank?}.join(',') order_option = [group_by_sort_order, options[:order]].reject {|s| s.blank?}.join(',')
order_option = nil if order_option.blank? order_option = nil if order_option.blank?
Issue.find :all, :include => ([:status, :project] + (options[:include] || [])).uniq, Issue.visible.find :all, :include => ([:status, :project] + (options[:include] || [])).uniq,
:conditions => Query.merge_conditions(statement, options[:conditions]), :conditions => Query.merge_conditions(statement, options[:conditions]),
:order => order_option, :order => order_option,
:limit => options[:limit], :limit => options[:limit],
@@ -541,7 +564,7 @@ class Query < ActiveRecord::Base
# Returns the journals # Returns the journals
# Valid options are :order, :offset, :limit # Valid options are :order, :offset, :limit
def journals(options={}) def journals(options={})
Journal.find :all, :include => [:details, :user, {:issue => [:project, :author, :tracker, :status]}], Journal.visible.find :all, :include => [:details, :user, {:issue => [:project, :author, :tracker, :status]}],
:conditions => statement, :conditions => statement,
:order => options[:order], :order => options[:order],
:limit => options[:limit], :limit => options[:limit],
@@ -549,26 +572,36 @@ class Query < ActiveRecord::Base
rescue ::ActiveRecord::StatementInvalid => e rescue ::ActiveRecord::StatementInvalid => e
raise StatementInvalid.new(e.message) raise StatementInvalid.new(e.message)
end end
# Returns the versions # Returns the versions
# Valid options are :conditions # Valid options are :conditions
def versions(options={}) def versions(options={})
Version.find :all, :include => :project, Version.visible.find :all, :include => :project,
:conditions => Query.merge_conditions(project_statement, options[:conditions]) :conditions => Query.merge_conditions(project_statement, options[:conditions])
rescue ::ActiveRecord::StatementInvalid => e rescue ::ActiveRecord::StatementInvalid => e
raise StatementInvalid.new(e.message) raise StatementInvalid.new(e.message)
end end
private private
# Helper method to generate the WHERE sql for a +field+, +operator+ and a +value+ # 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) def sql_for_field(field, operator, value, db_table, db_field, is_custom_filter=false)
sql = '' sql = ''
case operator case operator
when "=" when "="
sql = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")" if value.any?
sql = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
else
# IN an empty set
sql = "1=0"
end
when "!" when "!"
sql = "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))" 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 "!*" when "!*"
sql = "#{db_table}.#{db_field} IS NULL" sql = "#{db_table}.#{db_field} IS NULL"
sql << " OR #{db_table}.#{db_field} = ''" if is_custom_filter sql << " OR #{db_table}.#{db_field} = ''" if is_custom_filter
@@ -598,24 +631,22 @@ class Query < ActiveRecord::Base
when "t" when "t"
sql = date_range_clause(db_table, db_field, 0, 0) sql = date_range_clause(db_table, db_field, 0, 0)
when "w" when "w"
from = l(:general_first_day_of_week) == '7' ? first_day_of_week = l(:general_first_day_of_week).to_i
# week starts on sunday day_of_week = Date.today.cwday
((Date.today.cwday == 7) ? Time.now.at_beginning_of_day : Time.now.at_beginning_of_week - 1.day) : days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
# week starts on monday (Rails default) sql = date_range_clause(db_table, db_field, - days_ago, - days_ago + 6)
Time.now.at_beginning_of_week
sql = "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(from), connection.quoted_date(from + 7.days)]
when "~" when "~"
sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'" sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
when "!~" when "!~"
sql = "LOWER(#{db_table}.#{db_field}) NOT LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'" sql = "LOWER(#{db_table}.#{db_field}) NOT LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
end end
return sql return sql
end end
def add_custom_fields_filters(custom_fields) def add_custom_fields_filters(custom_fields)
@available_filters ||= {} @available_filters ||= {}
custom_fields.select(&:is_filter?).each do |field| custom_fields.select(&:is_filter?).each do |field|
case field.field_format case field.field_format
when "text" when "text"
@@ -626,13 +657,16 @@ class Query < ActiveRecord::Base
options = { :type => :date, :order => 20 } options = { :type => :date, :order => 20 }
when "bool" when "bool"
options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]], :order => 20 } options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]], :order => 20 }
when "user", "version"
next unless project
options = { :type => :list_optional, :values => field.possible_values_options(project), :order => 20}
else else
options = { :type => :string, :order => 20 } options = { :type => :string, :order => 20 }
end end
@available_filters["cf_#{field.id}"] = options.merge({ :name => field.name }) @available_filters["cf_#{field.id}"] = options.merge({ :name => field.name })
end end
end end
# Returns a SQL clause for a date or datetime field. # Returns a SQL clause for a date or datetime field.
def date_range_clause(table, field, from, to) def date_range_clause(table, field, from, to)
s = [] s = []
+148 -43
View File
@@ -1,52 +1,89 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Repository < ActiveRecord::Base class Repository < ActiveRecord::Base
include Redmine::Ciphering
belongs_to :project belongs_to :project
has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC" has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
has_many :changes, :through => :changesets has_many :changes, :through => :changesets
serialize :extra_info
# Raw SQL to delete changesets and changes in the database # Raw SQL to delete changesets and changes in the database
# has_many :changesets, :dependent => :destroy is too slow for big repositories # has_many :changesets, :dependent => :destroy is too slow for big repositories
before_destroy :clear_changesets before_destroy :clear_changesets
validates_length_of :password, :maximum => 255, :allow_nil => true
# Checks if the SCM is enabled when creating a repository # Checks if the SCM is enabled when creating a repository
validate_on_create { |r| r.errors.add(:type, :invalid) unless Setting.enabled_scm.include?(r.class.name.demodulize) } validate_on_create { |r| r.errors.add(:type, :invalid) unless Setting.enabled_scm.include?(r.class.name.demodulize) }
def self.human_attribute_name(attribute_key_name)
attr_name = attribute_key_name
if attr_name == "log_encoding"
attr_name = "commit_logs_encoding"
end
super(attr_name)
end
# Removes leading and trailing whitespace # Removes leading and trailing whitespace
def url=(arg) def url=(arg)
write_attribute(:url, arg ? arg.to_s.strip : nil) write_attribute(:url, arg ? arg.to_s.strip : nil)
end end
# Removes leading and trailing whitespace # Removes leading and trailing whitespace
def root_url=(arg) def root_url=(arg)
write_attribute(:root_url, arg ? arg.to_s.strip : nil) write_attribute(:root_url, arg ? arg.to_s.strip : nil)
end 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 def scm
@scm ||= self.scm_adapter.new url, root_url, login, password @scm ||= self.scm_adapter.new(url, root_url,
login, password, path_encoding)
update_attribute(:root_url, @scm.root_url) if root_url.blank? update_attribute(:root_url, @scm.root_url) if root_url.blank?
@scm @scm
end end
def scm_name def scm_name
self.class.scm_name self.class.scm_name
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? def supports_cat?
scm.supports_cat? scm.supports_cat?
end end
@@ -54,11 +91,19 @@ class Repository < ActiveRecord::Base
def supports_annotate? def supports_annotate?
scm.supports_annotate? scm.supports_annotate?
end end
def supports_all_revisions?
true
end
def supports_directory_revisions?
false
end
def entry(path=nil, identifier=nil) def entry(path=nil, identifier=nil)
scm.entry(path, identifier) scm.entry(path, identifier)
end end
def entries(path=nil, identifier=nil) def entries(path=nil, identifier=nil)
scm.entries(path, identifier) scm.entries(path, identifier)
end end
@@ -72,31 +117,40 @@ class Repository < ActiveRecord::Base
end end
def default_branch def default_branch
scm.default_branch nil
end end
def properties(path, identifier=nil) def properties(path, identifier=nil)
scm.properties(path, identifier) scm.properties(path, identifier)
end end
def cat(path, identifier=nil) def cat(path, identifier=nil)
scm.cat(path, identifier) scm.cat(path, identifier)
end end
def diff(path, rev, rev_to) def diff(path, rev, rev_to)
scm.diff(path, rev, rev_to) scm.diff(path, rev, rev_to)
end 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 # Returns a path relative to the url of the repository
def relative_path(path) def relative_path(path)
path path
end end
# Finds and returns a revision with a number or the beginning of a hash # Finds and returns a revision with a number or the beginning of a hash
def find_changeset_by_name(name) def find_changeset_by_name(name)
changesets.find(:first, :conditions => (name.match(/^\d*$/) ? ["revision = ?", name.to_s] : ["revision LIKE ?", name + '%'])) return nil if name.blank?
changesets.find(:first, :conditions => (name.match(/^\d*$/) ?
["revision = ?", name.to_s] : ["revision LIKE ?", name + '%']))
end end
def latest_changeset def latest_changeset
@latest_changeset ||= changesets.find(:first) @latest_changeset ||= changesets.find(:first)
end end
@@ -105,26 +159,32 @@ class Repository < ActiveRecord::Base
# Default behaviour is to search in cached changesets # Default behaviour is to search in cached changesets
def latest_changesets(path, rev, limit=10) def latest_changesets(path, rev, limit=10)
if path.blank? if path.blank?
changesets.find(:all, :include => :user, changesets.find(
:order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC", :all,
:limit => limit) :include => :user,
:order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
:limit => limit)
else else
changes.find(:all, :include => {:changeset => :user}, changes.find(
:conditions => ["path = ?", path.with_leading_slash], :all,
:order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC", :include => {:changeset => :user},
:limit => limit).collect(&:changeset) :conditions => ["path = ?", path.with_leading_slash],
:order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
:limit => limit
).collect(&:changeset)
end end
end end
def scan_changesets_for_issue_ids def scan_changesets_for_issue_ids
self.changesets.each(&:scan_comment_for_issue_ids) self.changesets.each(&:scan_comment_for_issue_ids)
end end
# Returns an array of committers usernames and associated user_id # Returns an array of committers usernames and associated user_id
def committers def committers
@committers ||= Changeset.connection.select_rows("SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}") @committers ||= Changeset.connection.select_rows(
"SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
end end
# Maps committers username to a user ids # Maps committers username to a user ids
def committer_ids=(h) def committer_ids=(h)
if h.is_a?(Hash) if h.is_a?(Hash)
@@ -132,17 +192,19 @@ class Repository < ActiveRecord::Base
new_user_id = h[committer] new_user_id = h[committer]
if new_user_id && (new_user_id.to_i != user_id.to_i) 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) 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]) Changeset.update_all(
"user_id = #{ new_user_id.nil? ? 'NULL' : new_user_id }",
["repository_id = ? AND committer = ?", id, committer])
end end
end end
@committers = nil @committers = nil
@found_committer_users = nil @found_committer_users = nil
true true
else else
false false
end end
end end
# Returns the Redmine User corresponding to the given +committer+ # Returns the Redmine User corresponding to the given +committer+
# It will return nil if the committer is not yet mapped and if no User # It will return nil if the committer is not yet mapped and if no User
# with the same username or email was found # with the same username or email was found
@@ -150,7 +212,7 @@ class Repository < ActiveRecord::Base
unless committer.blank? unless committer.blank?
@found_committer_users ||= {} @found_committer_users ||= {}
return @found_committer_users[committer] if @found_committer_users.has_key?(committer) return @found_committer_users[committer] if @found_committer_users.has_key?(committer)
user = nil user = nil
c = changesets.find(:first, :conditions => {:committer => committer}, :include => :user) c = changesets.find(:first, :conditions => {:committer => committer}, :include => :user)
if c && c.user if c && c.user
@@ -165,18 +227,27 @@ class Repository < ActiveRecord::Base
user user
end end
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 # Fetches new changesets for all repositories of active projects
# Can be called periodically by an external script # Can be called periodically by an external script
# eg. ruby script/runner "Repository.fetch_changesets" # eg. ruby script/runner "Repository.fetch_changesets"
def self.fetch_changesets def self.fetch_changesets
Project.active.has_module(:repository).find(:all, :include => :repository).each do |project| Project.active.has_module(:repository).find(:all, :include => :repository).each do |project|
if project.repository if project.repository
project.repository.fetch_changesets begin
project.repository.fetch_changesets
rescue Redmine::Scm::Adapters::CommandFailed => e
logger.error "scm: error during fetching changesets: #{e.message}"
end
end end
end end
end end
# scan changeset comments to find related and fixed issues for all repositories # scan changeset comments to find related and fixed issues for all repositories
def self.scan_changesets_for_issue_ids def self.scan_changesets_for_issue_ids
find(:all).each(&:scan_changesets_for_issue_ids) find(:all).each(&:scan_changesets_for_issue_ids)
@@ -185,27 +256,61 @@ class Repository < ActiveRecord::Base
def self.scm_name def self.scm_name
'Abstract' 'Abstract'
end end
def self.available_scm def self.available_scm
subclasses.collect {|klass| [klass.scm_name, klass.name]} subclasses.collect {|klass| [klass.scm_name, klass.name]}
end end
def self.factory(klass_name, *args) def self.factory(klass_name, *args)
klass = "Repository::#{klass_name}".constantize klass = "Repository::#{klass_name}".constantize
klass.new(*args) klass.new(*args)
rescue rescue
nil nil
end 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
private private
def before_save def before_save
# Strips url and root_url # Strips url and root_url
url.strip! url.strip!
root_url.strip! root_url.strip!
true true
end end
def clear_changesets def clear_changesets
cs, ch, ci = Changeset.table_name, Change.table_name, "#{table_name_prefix}changesets_issues#{table_name_suffix}" cs, ch, ci = Changeset.table_name, Change.table_name, "#{table_name_prefix}changesets_issues#{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 #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
+37 -24
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -19,16 +19,24 @@ require 'redmine/scm/adapters/bazaar_adapter'
class Repository::Bazaar < Repository class Repository::Bazaar < Repository
attr_protected :root_url attr_protected :root_url
validates_presence_of :url validates_presence_of :url, :log_encoding
def scm_adapter def self.human_attribute_name(attribute_key_name)
attr_name = attribute_key_name
if attr_name == "url"
attr_name = "path_to_repository"
end
super(attr_name)
end
def self.scm_adapter_class
Redmine::Scm::Adapters::BazaarAdapter Redmine::Scm::Adapters::BazaarAdapter
end end
def self.scm_name def self.scm_name
'Bazaar' 'Bazaar'
end end
def entries(path=nil, identifier=nil) def entries(path=nil, identifier=nil)
entries = scm.entries(path, identifier) entries = scm.entries(path, identifier)
if entries if entries
@@ -39,19 +47,24 @@ class Repository::Bazaar < Repository
full_path = File.join(root_url, e.path) full_path = File.join(root_url, e.path)
e.size = File.stat(full_path).size if File.file?(full_path) e.size = File.stat(full_path).size if File.file?(full_path)
end end
c = Change.find(:first, c = Change.find(
:include => :changeset, :first,
:conditions => ["#{Change.table_name}.revision = ? and #{Changeset.table_name}.repository_id = ?", e.lastrev.revision, id], :include => :changeset,
:order => "#{Changeset.table_name}.revision DESC") :conditions => [
"#{Change.table_name}.revision = ? and #{Changeset.table_name}.repository_id = ?",
e.lastrev.revision,
id
],
:order => "#{Changeset.table_name}.revision DESC")
if c if c
e.lastrev.identifier = c.changeset.revision e.lastrev.identifier = c.changeset.revision
e.lastrev.name = c.changeset.revision e.lastrev.name = c.changeset.revision
e.lastrev.author = c.changeset.committer e.lastrev.author = c.changeset.committer
end end
end end
end end
end end
def fetch_changesets def fetch_changesets
scm_info = scm.info scm_info = scm.info
if scm_info if scm_info
@@ -68,18 +81,18 @@ class Repository::Bazaar < Repository
revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true) revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
transaction do transaction do
revisions.reverse_each do |revision| revisions.reverse_each do |revision|
changeset = Changeset.create(:repository => self, changeset = Changeset.create(:repository => self,
:revision => revision.identifier, :revision => revision.identifier,
:committer => revision.author, :committer => revision.author,
:committed_on => revision.time, :committed_on => revision.time,
:scmid => revision.scmid, :scmid => revision.scmid,
:comments => revision.message) :comments => revision.message)
revision.paths.each do |change| revision.paths.each do |change|
Change.create(:changeset => changeset, Change.create(:changeset => changeset,
:action => change[:action], :action => change[:action],
:path => change[:path], :path => change[:path],
:revision => change[:revision]) :revision => change[:revision])
end end
end end
end unless revisions.nil? end unless revisions.nil?
+118 -74
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -19,67 +19,95 @@ require 'redmine/scm/adapters/cvs_adapter'
require 'digest/sha1' require 'digest/sha1'
class Repository::Cvs < Repository class Repository::Cvs < Repository
validates_presence_of :url, :root_url validates_presence_of :url, :root_url, :log_encoding
def scm_adapter def self.human_attribute_name(attribute_key_name)
attr_name = attribute_key_name
if attr_name == "root_url"
attr_name = "cvsroot"
elsif attr_name == "url"
attr_name = "cvs_module"
end
super(attr_name)
end
def self.scm_adapter_class
Redmine::Scm::Adapters::CvsAdapter Redmine::Scm::Adapters::CvsAdapter
end end
def self.scm_name def self.scm_name
'CVS' 'CVS'
end end
def entry(path=nil, identifier=nil) def entry(path=nil, identifier=nil)
rev = identifier.nil? ? nil : changesets.find_by_revision(identifier) rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
scm.entry(path, rev.nil? ? nil : rev.committed_on) scm.entry(path, rev.nil? ? nil : rev.committed_on)
end end
def entries(path=nil, identifier=nil) def entries(path=nil, identifier=nil)
rev = identifier.nil? ? nil : changesets.find_by_revision(identifier) 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) entries = scm.entries(path, rev.nil? ? nil : rev.committed_on)
if entries if entries
entries.each() do |entry| entries.each() do |entry|
unless entry.lastrev.nil? || entry.lastrev.identifier if ( ! entry.lastrev.nil? ) && ( ! entry.lastrev.revision.nil? )
change=changes.find_by_revision_and_path( entry.lastrev.revision, scm.with_leading_slash(entry.path) ) change=changes.find_by_revision_and_path(
entry.lastrev.revision,
scm.with_leading_slash(entry.path) )
if change if change
entry.lastrev.identifier=change.changeset.revision entry.lastrev.identifier = change.changeset.revision
entry.lastrev.author=change.changeset.committer entry.lastrev.revision = change.changeset.revision
entry.lastrev.revision=change.revision entry.lastrev.author = change.changeset.committer
entry.lastrev.branch=change.branch # entry.lastrev.branch = change.branch
end end
end end
end end
end end
entries entries
end end
def cat(path, identifier=nil) def cat(path, identifier=nil)
rev = identifier.nil? ? nil : changesets.find_by_revision(identifier) 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) scm.cat(path, rev.nil? ? nil : rev.committed_on)
end 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) def diff(path, rev, rev_to)
#convert rev to revision. CVS can't handle changesets here # convert rev to revision. CVS can't handle changesets here
diff=[] diff=[]
changeset_from=changesets.find_by_revision(rev) changeset_from = changesets.find_by_revision(rev)
if rev_to.to_i > 0 if rev_to.to_i > 0
changeset_to=changesets.find_by_revision(rev_to) changeset_to = changesets.find_by_revision(rev_to)
end end
changeset_from.changes.each() do |change_from| changeset_from.changes.each() do |change_from|
revision_from = nil
revision_from=nil revision_to = nil
revision_to=nil if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
revision_from = change_from.revision
revision_from=change_from.revision if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path)) end
if revision_from if revision_from
if changeset_to if changeset_to
changeset_to.changes.each() do |change_to| changeset_to.changes.each() do |change_to|
revision_to=change_to.revision if change_to.path==change_from.path revision_to = change_to.revision if change_to.path == change_from.path
end end
end end
unless revision_to unless revision_to
revision_to=scm.get_previous_revision(revision_from) revision_to = scm.get_previous_revision(revision_from)
end end
file_diff = scm.diff(change_from.path, revision_from, revision_to) file_diff = scm.diff(change_from.path, revision_from, revision_to)
diff = diff + file_diff unless file_diff.nil? diff = diff + file_diff unless file_diff.nil?
@@ -87,75 +115,91 @@ class Repository::Cvs < Repository
end end
return diff return diff
end end
def fetch_changesets def fetch_changesets
# some nifty bits to introduce a commit-id with cvs # 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. # 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. # 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 # 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 # 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 # we use a small delta here, to merge all changes belonging to _one_ changeset
time_delta=10.seconds time_delta = 10.seconds
fetch_since = latest_changeset ? latest_changeset.committed_on : nil fetch_since = latest_changeset ? latest_changeset.committed_on : nil
transaction do transaction do
tmp_rev_num = 1 tmp_rev_num = 1
scm.revisions('', fetch_since, nil, :with_paths => true) do |revision| 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 # only add the change to the database, if it doen't exists. the cvs log
# is not exclusive at all. # is not exclusive at all.
unless changes.find_by_path_and_revision(scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision]) tmp_time = revision.time.clone
revision unless changes.find_by_path_and_revision(
cs = changesets.find(:first, :conditions=>{ scm.with_leading_slash(revision.paths[0][:path]),
:committed_on=>revision.time-time_delta..revision.time+time_delta, revision.paths[0][:revision]
:committer=>revision.author, )
:comments=>Changeset.normalize_comments(revision.message) cmt = Changeset.normalize_comments(revision.message, repo_log_encoding)
}) author_utf8 = Changeset.to_utf8(revision.author, repo_log_encoding)
cs = changesets.find(
# create a new changeset.... :first,
:conditions => {
:committed_on => tmp_time - time_delta .. tmp_time + time_delta,
:committer => author_utf8,
:comments => cmt
}
)
# create a new changeset....
unless cs unless cs
# we use a temporaray revision number here (just for inserting) # we use a temporaray revision number here (just for inserting)
# later on, we calculate a continous positive number # later on, we calculate a continous positive number
latest = changesets.find(:first, :order => 'id DESC') tmp_time2 = tmp_time.clone.gmtime
cs = Changeset.create(:repository => self, branch = revision.paths[0][:branch]
:revision => "_#{tmp_rev_num}", scmid = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
:committer => revision.author, cs = Changeset.create(:repository => self,
:committed_on => revision.time, :revision => "tmp#{tmp_rev_num}",
:comments => revision.message) :scmid => scmid,
:committer => revision.author,
:committed_on => tmp_time,
:comments => revision.message)
tmp_rev_num += 1 tmp_rev_num += 1
end end
# convert CVS-File-States to internal Action-abbrevations
#convert CVS-File-States to internal Action-abbrevations # default action is (M)odified
#default action is (M)odified action = "M"
action="M" if revision.paths[0][:action] == "Exp" && revision.paths[0][:revision] == "1.1"
if revision.paths[0][:action]=="Exp" && revision.paths[0][:revision]=="1.1" action = "A" # add-action always at first revision (= 1.1)
action="A" #add-action always at first revision (= 1.1) elsif revision.paths[0][:action] == "dead"
elsif revision.paths[0][:action]=="dead" action = "D" # dead-state is similar to Delete
action="D" #dead-state is similar to Delete
end end
Change.create(
Change.create(:changeset => cs, :changeset => cs,
:action => action, :action => action,
:path => scm.with_leading_slash(revision.paths[0][:path]), :path => scm.with_leading_slash(revision.paths[0][:path]),
:revision => revision.paths[0][:revision], :revision => revision.paths[0][:revision],
:branch => revision.paths[0][:branch] :branch => revision.paths[0][:branch]
) )
end end
end end
# Renumber new changesets in chronological order # Renumber new changesets in chronological order
changesets.find(:all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE '_%'").each do |changeset| changesets.find(
:all,
:order => 'committed_on ASC, id ASC',
:conditions => "revision LIKE 'tmp%'"
).each do |changeset|
changeset.update_attribute :revision, next_revision_number changeset.update_attribute :revision, next_revision_number
end end
end # transaction end # transaction
@current_revision_number = nil
end end
private private
# Returns the next revision number to assign to a CVS changeset # Returns the next revision number to assign to a CVS changeset
def next_revision_number def next_revision_number
# Need to retrieve existing revision numbers to sort them as integers # Need to retrieve existing revision numbers to sort them as integers
@current_revision_number ||= (connection.select_values("SELECT revision FROM #{Changeset.table_name} WHERE repository_id = #{id} AND revision NOT LIKE '_%'").collect(&:to_i).max || 0) 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 @current_revision_number += 1
end end
end end
+42 -25
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -18,44 +18,62 @@
require 'redmine/scm/adapters/darcs_adapter' require 'redmine/scm/adapters/darcs_adapter'
class Repository::Darcs < Repository class Repository::Darcs < Repository
validates_presence_of :url validates_presence_of :url, :log_encoding
def scm_adapter def self.human_attribute_name(attribute_key_name)
attr_name = attribute_key_name
if attr_name == "url"
attr_name = "path_to_repository"
end
super(attr_name)
end
def self.scm_adapter_class
Redmine::Scm::Adapters::DarcsAdapter Redmine::Scm::Adapters::DarcsAdapter
end end
def self.scm_name def self.scm_name
'Darcs' 'Darcs'
end end
def supports_directory_revisions?
true
end
def entry(path=nil, identifier=nil) def entry(path=nil, identifier=nil)
patch = identifier.nil? ? nil : changesets.find_by_revision(identifier) patch = identifier.nil? ? nil : changesets.find_by_revision(identifier)
scm.entry(path, patch.nil? ? nil : patch.scmid) scm.entry(path, patch.nil? ? nil : patch.scmid)
end end
def entries(path=nil, identifier=nil) def entries(path=nil, identifier=nil)
patch = identifier.nil? ? nil : changesets.find_by_revision(identifier) 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) entries = scm.entries(path, patch.nil? ? nil : patch.scmid)
if entries if entries
entries.each do |entry| entries.each do |entry|
# Search the DB for the entry's last change # Search the DB for the entry's last change
changeset = changesets.find_by_scmid(entry.lastrev.scmid) if entry.lastrev && !entry.lastrev.scmid.blank? if entry.lastrev && !entry.lastrev.scmid.blank?
changeset = changesets.find_by_scmid(entry.lastrev.scmid)
end
if changeset if changeset
entry.lastrev.identifier = changeset.revision entry.lastrev.identifier = changeset.revision
entry.lastrev.name = changeset.revision entry.lastrev.name = changeset.revision
entry.lastrev.time = changeset.committed_on entry.lastrev.time = changeset.committed_on
entry.lastrev.author = changeset.committer entry.lastrev.author = changeset.committer
end end
end end
end end
entries entries
end end
def cat(path, identifier=nil) def cat(path, identifier=nil)
patch = identifier.nil? ? nil : changesets.find_by_revision(identifier.to_s) patch = identifier.nil? ? nil : changesets.find_by_revision(identifier.to_s)
scm.cat(path, patch.nil? ? nil : patch.scmid) scm.cat(path, patch.nil? ? nil : patch.scmid)
end end
def diff(path, rev, rev_to) def diff(path, rev, rev_to)
patch_from = changesets.find_by_revision(rev) patch_from = changesets.find_by_revision(rev)
return nil if patch_from.nil? return nil if patch_from.nil?
@@ -65,25 +83,24 @@ class Repository::Darcs < Repository
end end
patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil) : nil patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil) : nil
end end
def fetch_changesets def fetch_changesets
scm_info = scm.info scm_info = scm.info
if scm_info if scm_info
db_last_id = latest_changeset ? latest_changeset.scmid : nil db_last_id = latest_changeset ? latest_changeset.scmid : nil
next_rev = latest_changeset ? latest_changeset.revision.to_i + 1 : 1 next_rev = latest_changeset ? latest_changeset.revision.to_i + 1 : 1
# latest revision in the repository # latest revision in the repository
scm_revision = scm_info.lastrev.scmid scm_revision = scm_info.lastrev.scmid
unless changesets.find_by_scmid(scm_revision) unless changesets.find_by_scmid(scm_revision)
revisions = scm.revisions('', db_last_id, nil, :with_path => true) revisions = scm.revisions('', db_last_id, nil, :with_path => true)
transaction do transaction do
revisions.reverse_each do |revision| revisions.reverse_each do |revision|
changeset = Changeset.create(:repository => self, changeset = Changeset.create(:repository => self,
:revision => next_rev, :revision => next_rev,
:scmid => revision.scmid, :scmid => revision.scmid,
:committer => revision.author, :committer => revision.author,
:committed_on => revision.time, :committed_on => revision.time,
:comments => revision.message) :comments => revision.message)
revision.paths.each do |change| revision.paths.each do |change|
changeset.create_change(change) changeset.create_change(change)
end end
+19 -8
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# FileSystem adapter # FileSystem adapter
# File written by Paul Rivier, at Demotera. # File written by Paul Rivier, at Demotera.
@@ -8,12 +8,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -24,14 +24,26 @@ class Repository::Filesystem < Repository
attr_protected :root_url attr_protected :root_url
validates_presence_of :url validates_presence_of :url
def scm_adapter def self.human_attribute_name(attribute_key_name)
attr_name = attribute_key_name
if attr_name == "url"
attr_name = "root_directory"
end
super(attr_name)
end
def self.scm_adapter_class
Redmine::Scm::Adapters::FilesystemAdapter Redmine::Scm::Adapters::FilesystemAdapter
end end
def self.scm_name def self.scm_name
'Filesystem' 'Filesystem'
end end
def supports_all_revisions?
false
end
def entries(path=nil, identifier=nil) def entries(path=nil, identifier=nil)
scm.entries(path, identifier) scm.entries(path, identifier)
end end
@@ -39,5 +51,4 @@ class Repository::Filesystem < Repository
def fetch_changesets def fetch_changesets
nil nil
end end
end end
+141 -31
View File
@@ -1,16 +1,17 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# Copyright (C) 2007 Patrick Aljord patcito@ŋmail.com # Copyright (C) 2007 Patrick Aljord patcito@ŋmail.com
#
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -21,14 +22,51 @@ class Repository::Git < Repository
attr_protected :root_url attr_protected :root_url
validates_presence_of :url validates_presence_of :url
def scm_adapter def self.human_attribute_name(attribute_key_name)
attr_name = attribute_key_name
if attr_name == "url"
attr_name = "path_to_repository"
end
super(attr_name)
end
def self.scm_adapter_class
Redmine::Scm::Adapters::GitAdapter Redmine::Scm::Adapters::GitAdapter
end end
def self.scm_name def self.scm_name
'Git' 'Git'
end 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 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 def branches
scm.branches scm.branches
end end
@@ -37,42 +75,114 @@ class Repository::Git < Repository
scm.tags scm.tags
end end
# With SCM's that have a sequential commit numbering, redmine is able to be def default_branch
# clever and only fetch changesets going forward from the most recent one scm.default_branch
# it knows about. However, with git, you never know if people have merged end
# commits into the middle of the repository history, so we should parse
# the entire log. Since it's way too slow for large repositories, we only def find_changeset_by_name(name)
# parse 1 week before the last known commit. return nil if name.nil? || name.empty?
e = changesets.find(:first, :conditions => ['revision = ?', name.to_s])
return e if e
changesets.find(:first, :conditions => ['scmid LIKE ?', "#{name}%"])
end
def entries(path=nil, identifier=nil)
scm.entries(path,
identifier,
options = {:report_last_commit => extra_report_last_commit})
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 parse revisions per branch.
# Branch "last_scmid" is for this requirement.
#
# 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 # The repository can still be fully reloaded by calling #clear_changesets
# before fetching changesets (eg. for offline resync) # before fetching changesets (eg. for offline resync)
def fetch_changesets def fetch_changesets
c = changesets.find(:first, :order => 'committed_on DESC') scm_brs = branches
since = (c ? c.committed_on - 7.days : nil) return if scm_brs.nil? || scm_brs.empty?
h1 = extra_info || {}
revisions = scm.revisions('', nil, nil, :all => true, :since => since) h = h1.dup
return if revisions.nil? || revisions.empty? h["branches"] ||= {}
h["db_consistent"] ||= {}
recent_changesets = changesets.find(:all, :conditions => ['committed_on >= ?', since]) if changesets.count == 0
h["db_consistent"]["ordering"] = 1
# Clean out revisions that are no longer in git merge_extra_info(h)
recent_changesets.each {|c| c.destroy unless revisions.detect {|r| r.scmid.to_s == c.scmid.to_s }} self.save
elsif ! h["db_consistent"].has_key?("ordering")
# Subtract revisions that redmine already knows about h["db_consistent"]["ordering"] = 0
recent_revisions = recent_changesets.map{|c| c.scmid} merge_extra_info(h)
revisions.reject!{|r| recent_revisions.include?(r.scmid)} self.save
end
# Save the remaining ones to the database scm_brs.each do |br|
revisions.each{|r| r.save(self)} unless revisions.nil? from_scmid = nil
from_scmid = h["branches"][br]["last_scmid"] if h["branches"][br]
h["branches"][br] ||= {}
scm.revisions('', from_scmid, br, {:reverse => true}) do |rev|
db_rev = find_changeset_by_name(rev.revision)
transaction do
if db_rev.nil?
save_revision(rev)
end
h["branches"][br]["last_scmid"] = rev.scmid
merge_extra_info(h)
self.save
end
end
end
end end
def save_revision(rev)
changeset = Changeset.new(
:repository => self,
:revision => rev.identifier,
:scmid => rev.scmid,
:committer => rev.author,
:committed_on => rev.time,
:comments => rev.message
)
if changeset.save
rev.paths.each do |file|
Change.create(
:changeset => changeset,
:action => file[:action],
:path => file[:path])
end
end
end
private :save_revision
def latest_changesets(path,rev,limit=10) def latest_changesets(path,rev,limit=10)
revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false) revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false)
return [] if revisions.nil? || revisions.empty? return [] if revisions.nil? || revisions.empty?
changesets.find( changesets.find(
:all, :all,
:conditions => [ :conditions => [
"scmid IN (?)", "scmid IN (?)",
revisions.map!{|c| c.scmid} revisions.map!{|c| c.scmid}
], ],
:order => 'committed_on DESC' :order => 'committed_on DESC'
+115 -58
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -18,73 +18,130 @@
require 'redmine/scm/adapters/mercurial_adapter' require 'redmine/scm/adapters/mercurial_adapter'
class Repository::Mercurial < Repository 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 attr_protected :root_url
validates_presence_of :url validates_presence_of :url
def scm_adapter FETCH_AT_ONCE = 100 # number of changesets to fetch at once
def self.human_attribute_name(attribute_key_name)
attr_name = attribute_key_name
if attr_name == "url"
attr_name = "path_to_repository"
end
super(attr_name)
end
def self.scm_adapter_class
Redmine::Scm::Adapters::MercurialAdapter Redmine::Scm::Adapters::MercurialAdapter
end end
def self.scm_name def self.scm_name
'Mercurial' 'Mercurial'
end end
def entries(path=nil, identifier=nil) def supports_directory_revisions?
entries=scm.entries(path, identifier) true
if entries
entries.each do |entry|
next unless entry.is_file?
# Set the filesize unless browsing a specific revision
if identifier.nil?
full_path = File.join(root_url, entry.path)
entry.size = File.stat(full_path).size if File.file?(full_path)
end
# Search the DB for the entry's last change
change = changes.find(:first, :conditions => ["path = ?", scm.with_leading_slash(entry.path)], :order => "#{Changeset.table_name}.committed_on DESC")
if change
entry.lastrev.identifier = change.changeset.revision
entry.lastrev.name = change.changeset.revision
entry.lastrev.author = change.changeset.committer
entry.lastrev.revision = change.revision
end
end
end
entries
end 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.nil? || name.empty?
if /[^\d]/ =~ name or name.to_s.size > 8
e = changesets.find(:first, :conditions => ['scmid = ?', name.to_s])
else
e = changesets.find(:first, :conditions => ['revision = ?', name.to_s])
end
return e if e
changesets.find(:first, :conditions => ['scmid LIKE ?', "#{name}%"]) # last ditch
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.find(:all, :include => :user,
:conditions => latest_changesets_cond(path, rev, limit),
:limit => limit, :order => "#{Changeset.table_name}.id DESC")
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(/[%_\\]/) { |s| "\\#{s}" }}/%" << '\\'
end
[cond.join(' AND '), *args] unless cond.empty?
end
private :latest_changesets_cond
def fetch_changesets def fetch_changesets
scm_info = scm.info return if scm.info.nil?
if scm_info scm_rev = scm.info.lastrev.revision.to_i
# latest revision found in database db_rev = latest_changeset ? latest_changeset.revision.to_i : -1
db_revision = latest_changeset ? latest_changeset.revision.to_i : -1 return unless db_rev < scm_rev # already up-to-date
# latest revision in the repository
latest_revision = scm_info.lastrev logger.debug "Fetching changesets for repository #{url}" if logger
return if latest_revision.nil? (db_rev + 1).step(scm_rev, FETCH_AT_ONCE) do |i|
scm_revision = latest_revision.identifier.to_i transaction do
if db_revision < scm_revision scm.each_revision('', i, [i + FETCH_AT_ONCE - 1, scm_rev].min) do |re|
logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug? cs = Changeset.create(:repository => self,
identifier_from = db_revision + 1 :revision => re.revision,
while (identifier_from <= scm_revision) :scmid => re.scmid,
# loads changesets by batches of 100 :committer => re.author,
identifier_to = [identifier_from + 99, scm_revision].min :committed_on => re.time,
revisions = scm.revisions('', identifier_from, identifier_to, :with_paths => true) :comments => re.message)
transaction do re.paths.each { |e| cs.create_change(e) }
revisions.each do |revision|
changeset = Changeset.create(:repository => self,
:revision => revision.identifier,
:scmid => revision.scmid,
:committer => revision.author,
:committed_on => revision.time,
:comments => revision.message)
revision.paths.each do |change|
changeset.create_change(change)
end
end
end unless revisions.nil?
identifier_from = identifier_to + 1
end end
end end
end end
self
end end
end end
+23 -15
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -22,24 +22,32 @@ class Repository::Subversion < Repository
validates_presence_of :url validates_presence_of :url
validates_format_of :url, :with => /^(http|https|svn(\+[^\s:\/\\]+)?|file):\/\/.+/i validates_format_of :url, :with => /^(http|https|svn(\+[^\s:\/\\]+)?|file):\/\/.+/i
def scm_adapter def self.scm_adapter_class
Redmine::Scm::Adapters::SubversionAdapter Redmine::Scm::Adapters::SubversionAdapter
end end
def self.scm_name def self.scm_name
'Subversion' 'Subversion'
end end
def supports_directory_revisions?
true
end
def repo_log_encoding
'UTF-8'
end
def latest_changesets(path, rev, limit=10) def latest_changesets(path, rev, limit=10)
revisions = scm.revisions(path, rev, nil, :limit => limit) revisions = scm.revisions(path, rev, nil, :limit => limit)
revisions ? changesets.find_all_by_revision(revisions.collect(&:identifier), :order => "committed_on DESC", :include => :user) : [] revisions ? changesets.find_all_by_revision(revisions.collect(&:identifier), :order => "committed_on DESC", :include => :user) : []
end end
# Returns a path relative to the url of the repository # Returns a path relative to the url of the repository
def relative_path(path) def relative_path(path)
path.gsub(Regexp.new("^\/?#{Regexp.escape(relative_url)}"), '') path.gsub(Regexp.new("^\/?#{Regexp.escape(relative_url)}"), '')
end end
def fetch_changesets def fetch_changesets
scm_info = scm.info scm_info = scm.info
if scm_info if scm_info
@@ -56,12 +64,12 @@ class Repository::Subversion < Repository
revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true) revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
revisions.reverse_each do |revision| revisions.reverse_each do |revision|
transaction do transaction do
changeset = Changeset.create(:repository => self, changeset = Changeset.create(:repository => self,
:revision => revision.identifier, :revision => revision.identifier,
:committer => revision.author, :committer => revision.author,
:committed_on => revision.time, :committed_on => revision.time,
:comments => revision.message) :comments => revision.message)
revision.paths.each do |change| revision.paths.each do |change|
changeset.create_change(change) changeset.create_change(change)
end unless changeset.new_record? end unless changeset.new_record?
@@ -72,9 +80,9 @@ class Repository::Subversion < Repository
end end
end end
end end
private private
# Returns the relative url of the repository # Returns the relative url of the repository
# Eg: root_url = file:///var/svn/foo # Eg: root_url = file:///var/svn/foo
# url = file:///var/svn/foo/bar # url = file:///var/svn/foo/bar
+20 -4
View File
@@ -1,5 +1,5 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -19,6 +19,12 @@ class Role < ActiveRecord::Base
# Built-in roles # Built-in roles
BUILTIN_NON_MEMBER = 1 BUILTIN_NON_MEMBER = 1
BUILTIN_ANONYMOUS = 2 BUILTIN_ANONYMOUS = 2
ISSUES_VISIBILITY_OPTIONS = [
['all', :label_issues_visibility_all],
['default', :label_issues_visibility_public],
['own', :label_issues_visibility_own]
]
named_scope :givable, { :conditions => "builtin = 0", :order => 'position' } named_scope :givable, { :conditions => "builtin = 0", :order => 'position' }
named_scope :builtin, lambda { |*args| named_scope :builtin, lambda { |*args|
@@ -43,8 +49,10 @@ class Role < ActiveRecord::Base
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name validates_uniqueness_of :name
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
validates_format_of :name, :with => /^[\w\s\'\-]*$/i validates_inclusion_of :issues_visibility,
:in => ISSUES_VISIBILITY_OPTIONS.collect(&:first),
:if => lambda {|role| role.respond_to?(:issues_visibility)}
def permissions def permissions
read_attribute(:permissions) || [] read_attribute(:permissions) || []
end end
@@ -85,6 +93,14 @@ class Role < ActiveRecord::Base
name name
end 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 # Return true if the role is a builtin role
def builtin? def builtin?
self.builtin != 0 self.builtin != 0
+21 -20
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -28,12 +28,12 @@ class Setting < ActiveRecord::Base
'%b %d, %Y', '%b %d, %Y',
'%B %d, %Y' '%B %d, %Y'
] ]
TIME_FORMATS = [ TIME_FORMATS = [
'%H:%M', '%H:%M',
'%I:%M %p' '%I:%M %p'
] ]
ENCODINGS = %w(US-ASCII ENCODINGS = %w(US-ASCII
windows-1250 windows-1250
windows-1251 windows-1251
@@ -65,6 +65,7 @@ class Setting < ActiveRecord::Base
UTF-16LE UTF-16LE
EUC-JP EUC-JP
Shift_JIS Shift_JIS
CP932
GB18030 GB18030
GBK GBK
ISCII91 ISCII91
@@ -72,22 +73,22 @@ class Setting < ActiveRecord::Base
Big5 Big5
Big5-HKSCS Big5-HKSCS
TIS-620) TIS-620)
cattr_accessor :available_settings cattr_accessor :available_settings
@@available_settings = YAML::load(File.open("#{RAILS_ROOT}/config/settings.yml")) @@available_settings = YAML::load(File.open("#{RAILS_ROOT}/config/settings.yml"))
Redmine::Plugin.all.each do |plugin| Redmine::Plugin.all.each do |plugin|
next unless plugin.settings next unless plugin.settings
@@available_settings["plugin_#{plugin.id}"] = {'default' => plugin.settings[:default], 'serialized' => true} @@available_settings["plugin_#{plugin.id}"] = {'default' => plugin.settings[:default], 'serialized' => true}
end end
validates_uniqueness_of :name validates_uniqueness_of :name
validates_inclusion_of :name, :in => @@available_settings.keys 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' } validates_numericality_of :value, :only_integer => true, :if => Proc.new { |setting| @@available_settings[setting.name]['format'] == 'int' }
# Hash used to cache setting values # Hash used to cache setting values
@cached_settings = {} @cached_settings = {}
@cached_cleared_on = Time.now @cached_cleared_on = Time.now
def value def value
v = read_attribute(:value) v = read_attribute(:value)
# Unserialize serialized settings # Unserialize serialized settings
@@ -95,18 +96,18 @@ class Setting < ActiveRecord::Base
v = v.to_sym if @@available_settings[name]['format'] == 'symbol' && !v.blank? v = v.to_sym if @@available_settings[name]['format'] == 'symbol' && !v.blank?
v v
end end
def value=(v) def value=(v)
v = v.to_yaml if v && @@available_settings[name] && @@available_settings[name]['serialized'] v = v.to_yaml if v && @@available_settings[name] && @@available_settings[name]['serialized']
write_attribute(:value, v.to_s) write_attribute(:value, v.to_s)
end end
# Returns the value of the setting named name # Returns the value of the setting named name
def self.[](name) def self.[](name)
v = @cached_settings[name] v = @cached_settings[name]
v ? v : (@cached_settings[name] = find_or_default(name).value) v ? v : (@cached_settings[name] = find_or_default(name).value)
end end
def self.[]=(name, v) def self.[]=(name, v)
setting = find_or_default(name) setting = find_or_default(name)
setting.value = (v ? v : "") setting.value = (v ? v : "")
@@ -114,7 +115,7 @@ class Setting < ActiveRecord::Base
setting.save setting.save
setting.value setting.value
end end
# Defines getter and setter for each setting # Defines getter and setter for each setting
# Then setting values can be read using: Setting.some_setting_name # Then setting values can be read using: Setting.some_setting_name
# or set using Setting.some_setting_name = "some value" # or set using Setting.some_setting_name = "some value"
@@ -134,16 +135,16 @@ class Setting < ActiveRecord::Base
END_SRC END_SRC
class_eval src, __FILE__, __LINE__ class_eval src, __FILE__, __LINE__
end end
# Helper that returns an array based on per_page_options setting # Helper that returns an array based on per_page_options setting
def self.per_page_options_array def self.per_page_options_array
per_page_options.split(%r{[\s,]}).collect(&:to_i).select {|n| n > 0}.sort per_page_options.split(%r{[\s,]}).collect(&:to_i).select {|n| n > 0}.sort
end end
def self.openid? def self.openid?
Object.const_defined?(:OpenID) && self[:openid].to_i > 0 Object.const_defined?(:OpenID) && self[:openid].to_i > 0
end end
# Checks if settings have changed since the values were read # Checks if settings have changed since the values were read
# and clears the cache hash if it's the case # and clears the cache hash if it's the case
# Called once per request # Called once per request
@@ -155,13 +156,13 @@ class Setting < ActiveRecord::Base
logger.info "Settings cache cleared." if logger logger.info "Settings cache cleared." if logger
end end
end end
private private
# Returns the Setting instance for the setting named name # Returns the Setting instance for the setting named name
# (record found in database or new record with default value) # (record found in database or new record with default value)
def self.find_or_default(name) def self.find_or_default(name)
name = name.to_s name = name.to_s
raise "There's no setting named #{name}" unless @@available_settings.has_key?(name) raise "There's no setting named #{name}" unless @@available_settings.has_key?(name)
setting = find_by_name(name) setting = find_by_name(name)
setting ||= new(:name => name, :value => @@available_settings[name]['default']) if @@available_settings.has_key? name setting ||= new(:name => name, :value => @@available_settings[name]['default']) if @@available_settings.has_key? name
end end
+22 -12
View File
@@ -1,16 +1,16 @@
# redMine - project management software # Redmine - project management software
# Copyright (C) 2006-2008 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -22,7 +22,7 @@ class TimeEntry < ActiveRecord::Base
belongs_to :issue belongs_to :issue
belongs_to :user belongs_to :user
belongs_to :activity, :class_name => 'TimeEntryActivity', :foreign_key => 'activity_id' belongs_to :activity, :class_name => 'TimeEntryActivity', :foreign_key => 'activity_id'
attr_protected :project_id, :user_id, :tyear, :tmonth, :tweek attr_protected :project_id, :user_id, :tyear, :tmonth, :tweek
acts_as_customizable acts_as_customizable
@@ -33,12 +33,17 @@ class TimeEntry < ActiveRecord::Base
acts_as_activity_provider :timestamp => "#{table_name}.created_on", acts_as_activity_provider :timestamp => "#{table_name}.created_on",
:author_key => :user_id, :author_key => :user_id,
:find_options => {:include => :project} :find_options => {:include => :project}
validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on
validates_numericality_of :hours, :allow_nil => true, :message => :invalid validates_numericality_of :hours, :allow_nil => true, :message => :invalid
validates_length_of :comments, :maximum => 255, :allow_nil => true validates_length_of :comments, :maximum => 255, :allow_nil => true
named_scope :visible, lambda {|*args| {
:include => :project,
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_time_entries, *args)
}}
def after_initialize def after_initialize
if new_record? && self.activity.nil? if new_record? && self.activity.nil?
if default_activity = TimeEntryActivity.default if default_activity = TimeEntryActivity.default
@@ -47,36 +52,41 @@ class TimeEntry < ActiveRecord::Base
self.hours = nil if hours == 0 self.hours = nil if hours == 0
end end
end end
def before_validation def before_validation
self.project = issue.project if issue && project.nil? self.project = issue.project if issue && project.nil?
end end
def validate def validate
errors.add :hours, :invalid if hours && (hours < 0 || hours >= 1000) errors.add :hours, :invalid if hours && (hours < 0 || hours >= 1000)
errors.add :project_id, :invalid if project.nil? errors.add :project_id, :invalid if project.nil?
errors.add :issue_id, :invalid if (issue_id && !issue) || (issue && project!=issue.project) errors.add :issue_id, :invalid if (issue_id && !issue) || (issue && project!=issue.project)
end end
def hours=(h) def hours=(h)
write_attribute :hours, (h.is_a?(String) ? (h.to_hours || h) : h) write_attribute :hours, (h.is_a?(String) ? (h.to_hours || h) : h)
end end
# tyear, tmonth, tweek assigned where setting spent_on attributes # tyear, tmonth, tweek assigned where setting spent_on attributes
# these attributes make time aggregations easier # these attributes make time aggregations easier
def spent_on=(date) def spent_on=(date)
super super
if spent_on.is_a?(Time)
self.spent_on = spent_on.to_date
end
self.tyear = spent_on ? spent_on.year : nil self.tyear = spent_on ? spent_on.year : nil
self.tmonth = spent_on ? spent_on.month : 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 self.tweek = spent_on ? Date.civil(spent_on.year, spent_on.month, spent_on.day).cweek : nil
end end
# Returns true if the time entry can be edited by usr, otherwise false # Returns true if the time entry can be edited by usr, otherwise false
def editable_by?(usr) def editable_by?(usr)
(usr == user && usr.allowed_to?(:edit_own_time_entries, project)) || usr.allowed_to?(:edit_time_entries, project) (usr == user && usr.allowed_to?(:edit_own_time_entries, project)) || usr.allowed_to?(:edit_time_entries, project)
end end
# TODO: remove this method in 1.3.0
def self.visible_by(usr) def self.visible_by(usr)
ActiveSupport::Deprecation.warn "TimeEntry.visible_by is deprecated and will be removed in Redmine 1.3.0. Use the visible scope instead."
with_scope(:find => { :conditions => Project.allowed_to_condition(usr, :view_time_entries) }) do with_scope(:find => { :conditions => Project.allowed_to_condition(usr, :view_time_entries) }) do
yield yield
end end
+2 -1
View File
@@ -31,8 +31,9 @@ class Tracker < ActiveRecord::Base
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name validates_uniqueness_of :name
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
def to_s; name end def to_s; name end
def <=>(tracker) def <=>(tracker)
+123 -19
View File
@@ -1,5 +1,5 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2009 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -48,8 +48,8 @@ class User < Principal
has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify
has_many :changesets, :dependent => :nullify has_many :changesets, :dependent => :nullify
has_one :preference, :dependent => :destroy, :class_name => 'UserPreference' has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
has_one :rss_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'" has_one :rss_token, :class_name => 'Token', :conditions => "action='feeds'"
has_one :api_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='api'" has_one :api_token, :class_name => 'Token', :conditions => "action='api'"
belongs_to :auth_source belongs_to :auth_source
# Active non-anonymous users scope # Active non-anonymous users scope
@@ -68,13 +68,23 @@ class User < Principal
# Login must contain lettres, numbers, underscores only # Login must contain lettres, numbers, underscores only
validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i
validates_length_of :login, :maximum => 30 validates_length_of :login, :maximum => 30
validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-\.]*$/i
validates_length_of :firstname, :lastname, :maximum => 30 validates_length_of :firstname, :lastname, :maximum => 30
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :allow_nil => true validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :allow_nil => true
validates_length_of :mail, :maximum => 60, :allow_nil => true validates_length_of :mail, :maximum => 60, :allow_nil => true
validates_confirmation_of :password, :allow_nil => true validates_confirmation_of :password, :allow_nil => true
validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true
before_destroy :remove_references_before_destroy
named_scope :in_group, lambda {|group|
group_id = group.is_a?(Group) ? group.id : group.to_i
{ :conditions => ["#{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] }
}
named_scope :not_in_group, lambda {|group|
group_id = group.is_a?(Group) ? group.id : group.to_i
{ :conditions => ["#{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] }
}
def before_create def before_create
self.mail_notification = Setting.default_notification_option if self.mail_notification.blank? self.mail_notification = Setting.default_notification_option if self.mail_notification.blank?
true true
@@ -82,11 +92,14 @@ class User < Principal
def before_save def before_save
# update hashed_password if password was set # update hashed_password if password was set
self.hashed_password = User.hash_password(self.password) if self.password && self.auth_source_id.blank? if self.password && self.auth_source_id.blank?
salt_password(password)
end
end end
def reload(*args) def reload(*args)
@name = nil @name = nil
@projects_by_role = nil
super super
end end
@@ -120,7 +133,7 @@ class User < Principal
return nil unless user.auth_source.authenticate(login, password) return nil unless user.auth_source.authenticate(login, password)
else else
# authentication with local password # authentication with local password
return nil unless User.hash_password(password) == user.hashed_password return nil unless user.check_password?(password)
end end
else else
# user is not yet registered, try to authenticate with available sources # user is not yet registered, try to authenticate with available sources
@@ -199,13 +212,21 @@ class User < Principal
update_attribute(:status, STATUS_LOCKED) update_attribute(:status, STATUS_LOCKED)
end end
# Returns true if +clear_password+ is the correct user's password, otherwise false
def check_password?(clear_password) def check_password?(clear_password)
if auth_source_id.present? if auth_source_id.present?
auth_source.authenticate(self.login, clear_password) auth_source.authenticate(self.login, clear_password)
else else
User.hash_password(clear_password) == self.hashed_password User.hash_password("#{salt}#{User.hash_password clear_password}") == hashed_password
end end
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? # Does the backend storage allow this user to change their password?
def change_password_allowed? def change_password_allowed?
@@ -261,12 +282,16 @@ class User < Principal
notified_projects_ids notified_projects_ids
end end
# Only users that belong to more than 1 project can select projects for which they are notified
def valid_notification_options 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 # Note that @user.membership.size would fail since AR ignores
# :include association option when doing a count # :include association option when doing a count
if memberships.length < 1 if user.nil? || user.memberships.length < 1
MAIL_NOTIFICATION_OPTIONS.delete_if {|option| option.first == 'selected'} MAIL_NOTIFICATION_OPTIONS.reject {|option| option.first == 'selected'}
else else
MAIL_NOTIFICATION_OPTIONS MAIL_NOTIFICATION_OPTIONS
end end
@@ -346,16 +371,33 @@ class User < Principal
!roles_for_project(project).detect {|role| role.member?}.nil? !roles_for_project(project).detect {|role| role.member?}.nil?
end 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 {|h,k| h[k]=[]}
memberships.each do |membership|
membership.roles.each do |role|
@projects_by_role[role] << membership.project if membership.project
end
end
@projects_by_role.each do |role, projects|
projects.uniq!
end
@projects_by_role
end
# Return true if the user is allowed to do the specified action on a specific context # Return true if the user is allowed to do the specified action on a specific context
# Action can be: # Action can be:
# * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit') # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
# * a permission Symbol (eg. :edit_project) # * a permission Symbol (eg. :edit_project)
# Context can be: # Context can be:
# * a project : returns true if user is allowed to do the specified action on this project # * a project : returns true if user is allowed to do the specified action on this project
# * a group of projects : returns true if user is allowed on every 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, # * 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 # or falls back to Non Member / Anonymous permissions depending if the user is logged
def allowed_to?(action, context, options={}) def allowed_to?(action, context, options={}, &block)
if context && context.is_a?(Project) if context && context.is_a?(Project)
# No action allowed on archived projects # No action allowed on archived projects
return false unless context.active? return false unless context.active?
@@ -366,12 +408,15 @@ class User < Principal
roles = roles_for_project(context) roles = roles_for_project(context)
return false unless roles return false unless roles
roles.detect {|role| (context.is_public? || role.member?) && role.allowed_to?(action)} roles.detect {|role|
(context.is_public? || role.member?) &&
role.allowed_to?(action) &&
(block_given? ? yield(role, self) : true)
}
elsif context && context.is_a?(Array) elsif context && context.is_a?(Array)
# Authorize if user is authorized on every element of the array # Authorize if user is authorized on every element of the array
context.map do |project| context.map do |project|
allowed_to?(action,project,options) allowed_to?(action, project, options, &block)
end.inject do |memo,allowed| end.inject do |memo,allowed|
memo && allowed memo && allowed
end end
@@ -381,7 +426,11 @@ class User < Principal
# authorize if user has at least one role that has this permission # authorize if user has at least one role that has this permission
roles = memberships.collect {|m| m.roles}.flatten.uniq roles = memberships.collect {|m| m.roles}.flatten.uniq
roles.detect {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action)) roles << (self.logged? ? Role.non_member : Role.anonymous)
roles.detect {|role|
role.allowed_to?(action) &&
(block_given? ? yield(role, self) : true)
}
else else
false false
end end
@@ -389,8 +438,8 @@ class User < Principal
# Is the user allowed to do the specified action on any project? # Is the user allowed to do the specified action on any project?
# See allowed_to? for the actions and valid options. # See allowed_to? for the actions and valid options.
def allowed_to_globally?(action, options) def allowed_to_globally?(action, options, &block)
allowed_to?(action, nil, options.reverse_merge(:global => true)) allowed_to?(action, nil, options.reverse_merge(:global => true), &block)
end end
safe_attributes 'login', safe_attributes 'login',
@@ -419,7 +468,12 @@ class User < Principal
when 'all' when 'all'
true true
when 'selected' when 'selected'
# Handled by the Project # user receives notifications for created/assigned issues on unselected projects
if object.is_a?(Issue) && (object.author == self || object.assigned_to == self)
true
else
false
end
when 'none' when 'none'
false false
when 'only_my_events' when 'only_my_events'
@@ -463,6 +517,20 @@ class User < Principal
end end
anonymous_user anonymous_user
end 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.find_each(:conditions => "salt IS NULL OR salt = ''") do |user|
next if user.hashed_password.blank?
salt = User.generate_salt
hashed_password = User.hash_password("#{salt}#{user.hashed_password}")
User.update_all("salt = '#{salt}', hashed_password = '#{hashed_password}'", ["id = ?", user.id] )
end
end
end
protected protected
@@ -474,11 +542,42 @@ class User < Principal
end end
private private
# 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 is_public = ?', id, false]
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 # Return password digest
def self.hash_password(clear_password) def self.hash_password(clear_password)
Digest::SHA1.hexdigest(clear_password || "") Digest::SHA1.hexdigest(clear_password || "")
end end
# Returns a 128bits random salt as a hex string (32 chars long)
def self.generate_salt
ActiveSupport::SecureRandom.hex(16)
end
end end
class AnonymousUser < User class AnonymousUser < User
@@ -499,4 +598,9 @@ class AnonymousUser < User
def mail; nil end def mail; nil end
def time_zone; nil end def time_zone; nil end
def rss_key; nil end def rss_key; nil end
# Anonymous user can not be destroyed
def destroy
false
end
end end
+3
View File
@@ -51,4 +51,7 @@ class UserPreference < ActiveRecord::Base
def comments_sorting; self[:comments_sorting] end def comments_sorting; self[:comments_sorting] end
def comments_sorting=(order); self[:comments_sorting]=order 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
end end
+6
View File
@@ -33,6 +33,7 @@ class Version < ActiveRecord::Base
validates_inclusion_of :status, :in => VERSION_STATUSES validates_inclusion_of :status, :in => VERSION_STATUSES
validates_inclusion_of :sharing, :in => VERSION_SHARINGS validates_inclusion_of :sharing, :in => VERSION_SHARINGS
named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
named_scope :open, :conditions => {:status => 'open'} named_scope :open, :conditions => {:status => 'open'}
named_scope :visible, lambda {|*args| { :include => :project, named_scope :visible, lambda {|*args| { :include => :project,
:conditions => Project.allowed_to_condition(args.first || User.current, :view_issues) } } :conditions => Project.allowed_to_condition(args.first || User.current, :view_issues) } }
@@ -42,6 +43,11 @@ class Version < ActiveRecord::Base
user.allowed_to?(:view_issues, self.project) user.allowed_to?(:view_issues, self.project)
end end
# Version files have same visibility as project files
def attachments_visible?(*args)
project.present? && project.attachments_visible?(*args)
end
def start_date def start_date
@start_date ||= fixed_issues.minimum('start_date') @start_date ||= fixed_issues.minimum('start_date')
end end
+13 -4
View File
@@ -44,17 +44,26 @@ class Wiki < ActiveRecord::Base
# find the page with the given title # find the page with the given title
def find_page(title, options = {}) def find_page(title, options = {})
@page_found_with_redirect = false
title = start_page if title.blank? title = start_page if title.blank?
title = Wiki.titleize(title).downcase title = Wiki.titleize(title)
page = pages.first(:conditions => ["LOWER(title) LIKE ?", title]) page = pages.first(:conditions => ["LOWER(title) = LOWER(?)", title])
if !page && !(options[:with_redirect] == false) if !page && !(options[:with_redirect] == false)
# search for a redirect # search for a redirect
redirect = redirects.first(:conditions => ["LOWER(title) LIKE ?", title]) redirect = redirects.first(:conditions => ["LOWER(title) = LOWER(?)", title])
page = find_page(redirect.redirects_to, :with_redirect => false) if redirect if redirect
page = find_page(redirect.redirects_to, :with_redirect => false)
@page_found_with_redirect = true
end
end end
page page
end 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 # Finds a page by title
# The given string can be of one of the forms: "title" or "project:title" # The given string can be of one of the forms: "title" or "project:title"
# Examples: # Examples:
+15 -15
View File
@@ -1,16 +1,16 @@
# redMine - project management software # RedMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -23,28 +23,28 @@ class WikiContent < ActiveRecord::Base
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
validates_presence_of :text validates_presence_of :text
validates_length_of :comments, :maximum => 255, :allow_nil => true validates_length_of :comments, :maximum => 255, :allow_nil => true
acts_as_versioned acts_as_versioned
def visible?(user=User.current) def visible?(user=User.current)
page.visible?(user) page.visible?(user)
end end
def project def project
page.project page.project
end end
def attachments def attachments
page.nil? ? [] : page.attachments page.nil? ? [] : page.attachments
end end
# Returns the mail adresses of users that should be notified # Returns the mail adresses of users that should be notified
def recipients def recipients
notified = project.notified_users notified = project.notified_users
notified.reject! {|user| !visible?(user)} notified.reject! {|user| !visible?(user)}
notified.collect(&:mail) notified.collect(&:mail)
end end
class Version class Version
belongs_to :page, :class_name => '::WikiPage', :foreign_key => 'page_id' belongs_to :page, :class_name => '::WikiPage', :foreign_key => 'page_id'
belongs_to :author, :class_name => '::User', :foreign_key => 'author_id' belongs_to :author, :class_name => '::User', :foreign_key => 'author_id'
@@ -84,7 +84,7 @@ class WikiContent < ActiveRecord::Base
end end
plain plain
end end
def text def text
@text ||= case compression @text ||= case compression
when 'gzip' when 'gzip'
@@ -92,16 +92,16 @@ class WikiContent < ActiveRecord::Base
else else
# uncompressed data # uncompressed data
data data
end end
end end
def project def project
page.project page.project
end end
# Returns the previous version or nil # Returns the previous version or nil
def previous def previous
@previous ||= WikiContent::Version.find(:first, @previous ||= WikiContent::Version.find(:first,
:order => 'version DESC', :order => 'version DESC',
:include => :author, :include => :author,
:conditions => ["wiki_content_id = ? AND version < ?", wiki_content_id, version]) :conditions => ["wiki_content_id = ? AND version < ?", wiki_content_id, version])
+29 -10
View File
@@ -1,5 +1,5 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2009 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -30,8 +30,9 @@ class WikiPage < ActiveRecord::Base
:datetime => :created_on, :datetime => :created_on,
:url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}} :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}}
acts_as_searchable :columns => ['title', 'text'], acts_as_searchable :columns => ['title', "#{WikiContent.table_name}.text"],
:include => [{:wiki => :project}, :content], :include => [{:wiki => :project}, :content],
:permission => :view_wiki_pages,
:project_key => "#{Wiki.table_name}.project_id" :project_key => "#{Wiki.table_name}.project_id"
attr_accessor :redirect_existing_links attr_accessor :redirect_existing_links
@@ -41,6 +42,12 @@ class WikiPage < ActiveRecord::Base
validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false
validates_associated :content validates_associated :content
# eager load information about last updates, without loading text
named_scope :with_updated_on, {
:select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
:joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id"
}
# Wiki pages that are protected by default # Wiki pages that are protected by default
DEFAULT_PROTECTED_PAGES = %w(sidebar) DEFAULT_PROTECTED_PAGES = %w(sidebar)
@@ -121,6 +128,18 @@ class WikiPage < ActiveRecord::Base
content.text if content content.text if content
end end
def updated_on
unless @updated_on
if time = read_attribute(:updated_on)
# content updated_on was eager loaded with the page
@updated_on = Time.parse(time) rescue nil
else
@updated_on = content && content.updated_on
end
end
@updated_on
end
# Returns true if usr is allowed to edit the page, otherwise false # Returns true if usr is allowed to edit the page, otherwise false
def editable_by?(usr) def editable_by?(usr)
!protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project) !protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project)
@@ -149,17 +168,13 @@ class WikiPage < ActiveRecord::Base
end end
end end
class WikiDiff class WikiDiff < Redmine::Helpers::Diff
attr_reader :diff, :words, :content_to, :content_from attr_reader :content_to, :content_from
def initialize(content_to, content_from) def initialize(content_to, content_from)
@content_to = content_to @content_to = content_to
@content_from = content_from @content_from = content_from
@words = content_to.text.split(/(\s+)/) super(content_to.text, content_from.text)
@words = @words.select {|word| word != ' '}
words_from = content_from.text.split(/(\s+)/)
words_from = words_from.select {|word| word != ' '}
@diff = words_from.diff @words
end end
end end
@@ -197,6 +212,10 @@ class WikiAnnotate
break unless @lines.detect { |line| line[0].nil? } break unless @lines.detect { |line| line[0].nil? }
current = current.previous current = current.previous
end end
@lines.each { |line| line[0] ||= current.version } @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
end end
+2 -2
View File
@@ -89,8 +89,8 @@ class Workflow < ActiveRecord::Base
else else
transaction do transaction do
delete_all :tracker_id => target_tracker.id, :role_id => target_role.id delete_all :tracker_id => target_tracker.id, :role_id => target_role.id
connection.insert "INSERT INTO #{Workflow.table_name} (tracker_id, role_id, old_status_id, new_status_id)" + connection.insert "INSERT INTO #{Workflow.table_name} (tracker_id, role_id, old_status_id, new_status_id, author, assignee)" +
" SELECT #{target_tracker.id}, #{target_role.id}, old_status_id, new_status_id" + " SELECT #{target_tracker.id}, #{target_role.id}, old_status_id, new_status_id, author, assignee" +
" FROM #{Workflow.table_name}" + " FROM #{Workflow.table_name}" +
" WHERE tracker_id = #{source_tracker.id} AND role_id = #{source_role.id}" " WHERE tracker_id = #{source_tracker.id} AND role_id = #{source_role.id}"
end end
+6 -8
View File
@@ -21,16 +21,14 @@
<%= content_tag('p', l(:label_no_data), :class => 'nodata') if @events_by_day.empty? %> <%= content_tag('p', l(:label_no_data), :class => 'nodata') if @events_by_day.empty? %>
<div style="float:left;"> <div style="float:left;">
<%= link_to_remote(('&#171; ' + l(:label_previous)), <%= link_to_content_update('&#171; ' + l(:label_previous),
{:update => "content", :url => params.merge(:from => @date_to - @days - 1), :method => :get, :complete => 'window.scrollTo(0,0)'}, params.merge(:from => @date_to - @days - 1),
{:href => url_for(params.merge(:from => @date_to - @days - 1)), :title => l(:label_date_from_to, :start => format_date(@date_to - 2*@days), :end => format_date(@date_to - @days - 1))) %>
:title => l(:label_date_from_to, :start => format_date(@date_to - 2*@days), :end => format_date(@date_to - @days - 1))}) %>
</div> </div>
<div style="float:right;"> <div style="float:right;">
<%= link_to_remote((l(:label_next) + ' &#187;'), <%= link_to_content_update(l(:label_next) + ' &#187;',
{:update => "content", :url => params.merge(:from => @date_to + @days - 1), :method => :get, :complete => 'window.scrollTo(0,0)'}, params.merge(:from => @date_to + @days - 1),
{:href => url_for(params.merge(:from => @date_to + @days - 1)), :title => l(:label_date_from_to, :start => format_date(@date_to), :end => format_date(@date_to + @days - 1))) unless @date_to >= Date.today %>
:title => l(:label_date_from_to, :start => format_date(@date_to), :end => format_date(@date_to + @days - 1))}) unless @date_to >= Date.today %>
</div> </div>
&nbsp; &nbsp;
<% other_formats_links do |f| %> <% other_formats_links do |f| %>

Some files were not shown because too many files have changed in this diff Show More