Compare commits

...

174 Commits

Author SHA1 Message Date
Dmitriy Zaporozhets 7af16bbb0f Merge branch 'advanced-notes' of /home/git/repositories/gitlab/gitlabhq 2013-04-02 11:35:46 +00:00
Dmitriy Zaporozhets b641cdd183 fix test 2013-04-02 14:30:32 +03:00
Dmitriy Zaporozhets af657b0509 reset st_commits before setting new value to prevent error when old st_commits is broken 2013-04-02 11:32:41 +03:00
Dmitriy Zaporozhets d3559e2556 fix tabs features 2013-04-02 11:23:06 +03:00
Sytse Sijbrandij 08c6f5f604 Adding special cases to the advanced setup notes. 2013-04-02 07:52:47 +02:00
Dmitriy Zaporozhets 8465238899 fix long names on wall 2013-04-01 22:53:07 +03:00
Dmitriy Zaporozhets 8cadeb6750 nav views refactoring 2013-04-01 22:30:48 +03:00
Dmitriy Zaporozhets 19ab03f461 minor design improvements 2013-04-01 21:37:39 +03:00
Dmitriy Zaporozhets 0e9080e3dd Fixed bug with non-displayed download button 2013-04-01 21:25:50 +03:00
Dmitriy Zaporozhets 65d9f8c16c Fix notification issue 2013-04-01 21:16:52 +03:00
Dmitriy Zaporozhets 76a4cbe464 Merge branch 'refactor/gitlab_git' 2013-04-01 20:53:00 +03:00
Dmitriy Zaporozhets 8a6bf09ad0 Pass project into factory for teams tests 2013-04-01 20:35:41 +03:00
Dmitriy Zaporozhets f536c13355 fixed test using repo with commits but old factory 2013-04-01 19:06:47 +03:00
Dmitriy Zaporozhets 3b88636d3c fix tests 2013-04-01 18:35:29 +03:00
Dmitriy Zaporozhets adccf3b499 fix facotries 2013-04-01 18:24:05 +03:00
Dmitriy Zaporozhets f5dec306fd Use project_with_code factory where necessary 2013-04-01 18:16:08 +03:00
Dmitriy Zaporozhets 9a26e9a0d6 Dont init repo on every create(:repo) 2013-04-01 17:27:44 +03:00
Dmitriy Zaporozhets 273741fbde Merge pull request #3462 from tsl0922/fix-reassign-error
fix: wrong number of arguments
2013-04-01 07:26:04 -07:00
Dmitriy Zaporozhets 541d899410 Project.repository should never be nil so you can call repository.exists? or repository.empty?
Also specify separate project factory for project with filled repo
2013-04-01 16:56:25 +03:00
Dmitriy Zaporozhets 49b024f5f5 Use Gitlab::Git:: for git features across application 2013-04-01 16:04:35 +03:00
Dmitriy Zaporozhets bb06e905ef added Gitlab::Git::Compare for git compare feature 2013-04-01 16:03:11 +03:00
Dmitriy Zaporozhets 51c167554c added Gitlab::Git::Blame for git blame feature 2013-04-01 16:02:54 +03:00
Dmitriy Zaporozhets 22817398e6 define TestEnv and keep all global stubs in one place 2013-04-01 14:39:19 +03:00
tsl0922 45c4804c8e fix: wrong argument number 2013-04-01 17:25:31 +08:00
Dmitriy Zaporozhets 7bb71bb088 Fix stubbed repo 2013-04-01 09:21:31 +03:00
Dmitriy Zaporozhets 458631c5ba remove unnecessary Commit.new 2013-03-31 23:58:17 +03:00
Dmitriy Zaporozhets bbfbff3add Extend models functionality with old decorator methods. Use Repository model 2013-03-31 23:48:12 +03:00
Dmitriy Zaporozhets b53557aca6 Remove decorator calls and methods from views. Repalace with helper calls when needed 2013-03-31 23:47:26 +03:00
Dmitriy Zaporozhets da5b0c91dc Move some decorator logic to helpers 2013-03-31 23:46:54 +03:00
Dmitriy Zaporozhets 685681e28a remove Tree/Commit decorator usage from controllers 2013-03-31 23:46:25 +03:00
Dmitriy Zaporozhets 2a6b4f965e rake task to clear redis cache 2013-03-31 23:45:58 +03:00
Dmitriy Zaporozhets a0bca5b71d Add Repository model to proxy request to Gitlab::Git::Repositoty and decorate commits with Commit model 2013-03-31 23:45:38 +03:00
Dmitriy Zaporozhets 1ea385625b Remove Commit & Tree decorators 2013-03-31 23:44:59 +03:00
Dmitriy Zaporozhets 26323046fd Decorate Gitlab::Git::Commit with Commit 2013-03-31 19:00:45 +03:00
Dmitriy Zaporozhets 9dc644635f Fix tests and remove app/models/repository.rb 2013-03-31 18:50:17 +03:00
Dmitriy Zaporozhets 154e54b46e Remove grit logic from app/ 2013-03-31 18:49:58 +03:00
Dmitriy Zaporozhets d444a23ad6 specs for Gitlab::Git::Repository and Gitlab::Git::Commit 2013-03-31 18:49:31 +03:00
Dmitriy Zaporozhets 676bce2ab9 Move Commit and Repository logic to lib/gitlab/git 2013-03-31 18:49:06 +03:00
Dmitriy Zaporozhets 71b0f8ea0b Use existing methods for branch names: Ex use @repository.branch_names instead of @repository.heads.map(&:name) 2013-03-31 17:08:10 +03:00
Dmitriy Zaporozhets 025e41576e Merge branch 'header-in-contributing-guide' of /home/git/repositories/gitlab/gitlabhq 2013-03-31 12:06:48 +00:00
Dmitriy Zaporozhets a1b76c6c0a Merge branch 'notes-in-installation-guide' of /home/git/repositories/gitlab/gitlabhq 2013-03-31 12:06:24 +00:00
Dmitriy Zaporozhets ddaedaef1a Fix therubyracer dependencies 2013-03-31 15:04:08 +03:00
Sytse Sijbrandij 8fcdbaea71 Section for important notes. 2013-03-31 13:54:46 +02:00
Sytse Sijbrandij 15143a3b7b Improve header and wording. 2013-03-31 13:48:49 +02:00
Dmitriy Zaporozhets ea7e163660 Merge pull request #3457 from jrmithdobbs/fix-freebsd-bundle-install
Update deps for therubyracer and libv8 resolve build issues on FreeBSD...
2013-03-31 01:32:33 -07:00
Douglas Huff abc47852a9 Update deps for therubyracer and libv8 to resolve build issues on FreeBSD. Resolves Iussue#3446 . 2013-03-30 18:54:12 -07:00
Dmitriy Zaporozhets 188e6a7a3f Merge pull request #3369 from hiroponz/display-note-count
Display note count on network graph.
2013-03-30 15:10:26 -07:00
Dmitriy Zaporozhets c918000bc2 Merge pull request #3396 from Andrew8xx8/issue-button-fix
New issue button was not follows to external tracker if it is selected. ...
2013-03-30 15:10:08 -07:00
Dmitriy Zaporozhets 6005ec894a Merge pull request #3392 from hiroponz/fix-non-ascii-char-username
Fix RoutingError when changing username to non ascii char.
2013-03-30 15:07:11 -07:00
Dmitriy Zaporozhets 4449ac3ad1 Merge pull request #3430 from logorrhea/master
Changed the word 'authentification' to 'authentication'
2013-03-30 15:05:29 -07:00
Dmitriy Zaporozhets 69e5a4bbeb Merge pull request #3428 from colindean/bug/assigned-team-typo
fix typo: shure -> sure
2013-03-30 15:04:32 -07:00
Dmitriy Zaporozhets 1c5a393c95 Merge pull request #3406 from docwhat/in_projects
Fixed UsersProject.in_projects
2013-03-30 15:03:44 -07:00
Dmitriy Zaporozhets 52ae054447 prevent exception when trying to edit empty project 2013-03-30 16:46:56 +02:00
Dmitriy Zaporozhets 11b89eb381 Merge branch 'master' of github.com:gitlabhq/gitlabhq 2013-03-30 16:36:15 +02:00
Dmitriy Zaporozhets e998257dcf use rollbacked version of grit to make gollum works 2013-03-30 16:35:19 +02:00
Dmitriy Zaporozhets e29c9b7932 slower animation for tree browsing 2013-03-30 16:35:19 +02:00
Dmitriy Zaporozhets 52b0ceb87a Merge branch 'accepting-mr-in-uservoice' of /home/git/repositories/gitlab/gitlabhq 2013-03-30 11:15:55 +00:00
Dmitriy Zaporozhets 214768d3c5 Merge pull request #3440 from evanwon/patch-2
Fixed: gitlab-shell version check error message
2013-03-30 04:06:06 -07:00
Dmitriy Zaporozhets 66a1b88393 Update a grit to newer version 2013-03-30 12:50:44 +02:00
Sytse Sijbrandij d8eefdccfc Removing duplication by putting everything in the readme. Allow us to close issues that deviate from the guidelines. 2013-03-30 11:35:35 +01:00
Dmitriy Zaporozhets 49f14f057d Prevent gollum to overrride gitlab-grit gem. Use grit as instead so gollum uses it too. Fixes things with gpg singatured commits, etc. 2013-03-29 08:47:14 +02:00
Dmitriy Zaporozhets a18ce40943 Revert "First step with rugged"
This reverts commit 4524ba20b8.
2013-03-28 23:01:42 +02:00
Dmitriy Zaporozhets 4524ba20b8 First step with rugged 2013-03-28 21:57:38 +02:00
Evan Wondrasek f1b369b57d Fixed: gitlab-shell version check error message 2013-03-28 11:03:00 -05:00
Dmitriy Zaporozhets 21191318ae refactor wall.js. style wall page a bit 2013-03-28 16:41:29 +02:00
Dmitriy Zaporozhets 583bfac5f5 Fix Note notification for entities without assignee 2013-03-28 16:00:19 +02:00
Dmitriy Zaporozhets 5ad4be295f remove notify checkboxes from note forms 2013-03-28 15:39:18 +02:00
Dmitriy Zaporozhets 70947fedda inslude author & assignee to note notification recipients 2013-03-28 14:51:25 +02:00
Dmitriy Zaporozhets 618249734b rebuild notification on notes logic 2013-03-28 14:39:59 +02:00
Dmitriy Zaporozhets 63e6f055f1 Fix notify specs. Fix merge request close via api 2013-03-28 13:24:01 +02:00
Dmitriy Zaporozhets 2f585840db Fixed new mr/issue emails 2013-03-28 12:52:44 +02:00
Dmitriy Zaporozhets ecf3b2e471 add text templates to new emails 2013-03-28 12:33:54 +02:00
Dmitriy Zaporozhets c04120c1c5 Improve notification service tests 2013-03-28 12:24:04 +02:00
Dmitriy Zaporozhets f49a2ac0df Add close issue/mr methods to Notify. Refactored Notificationservice 2013-03-28 12:14:53 +02:00
Dmitriy Zaporozhets 9e616459e0 add watchers to email recipients list. Add emails for close/merge MR 2013-03-28 11:59:06 +02:00
Tyler Funk 26bd6acadb Changed the word 'authentification' to 'authentication' 2013-03-27 22:03:54 -05:00
Dmitriy Zaporozhets 11d52a1553 Fix NotificationService reassign_email method 2013-03-27 22:33:59 +02:00
Dmitriy Zaporozhets 2b2d43ed2a Update develoment dependencies 2013-03-27 22:21:32 +02:00
Colin Dean 9e24929f16 fix typo: shure -> sure 2013-03-27 15:55:10 -04:00
Dmitriy Zaporozhets ed7a2136dd update sidekiq 2013-03-27 21:51:40 +02:00
Dmitriy Zaporozhets f230fe3dda Fix NotificationService NameError for new issue 2013-03-27 21:42:01 +02:00
Dmitriy Zaporozhets 0a044c7318 NotificationService respects disabled notifications now 2013-03-27 20:28:00 +02:00
Dmitriy Zaporozhets ba59912072 Prepare UI for notification settings 2013-03-27 20:07:52 +02:00
Dmitriy Zaporozhets d55ade1686 notification scaffold 2013-03-27 19:04:29 +02:00
Dmitriy Zaporozhets 5f14a6bcf8 annotated 2013-03-27 18:26:37 +02:00
Sytse Sijbrandij 3392f6c1f0 Link to accepting issues on feedback forum. 2013-03-27 10:15:12 +01:00
Dmitriy Zaporozhets a31fe1a63f Merge pull request #3407 from NARKOZ/patch-1
use convenient method to check for empty project repo
2013-03-26 23:28:07 -07:00
Dmitriy Zaporozhets e3f1164248 stub notification in event model 2013-03-26 19:27:39 +02:00
Andrew8xx8 5e6f45b07f Settings replaced by Gitlab.config 2013-03-26 21:04:00 +04:00
Dmitriy Zaporozhets 3728c4904e refactor observers test since email logic moved to service 2013-03-26 19:00:54 +02:00
Dmitriy Zaporozhets ce0945efcd refactor observers. Added BaseObserver with helper methods 2013-03-26 18:11:38 +02:00
Dmitriy Zaporozhets 6abf58466f Move new_note email logic to NotificationService 2013-03-26 17:51:06 +02:00
Dmitriy Zaporozhets f93c4dc0d8 Use notificationService for MR reassigned 2013-03-26 17:23:28 +02:00
Dmitriy Zaporozhets 38ffb8220c use NotificationService for handle notify logic when MR created 2013-03-26 17:16:06 +02:00
Christian Höltje b8502cbaee Fixed UsersProject.in_projects
I discovered while trying to use UserTeam#remove_member() that
UsersProject.in_projects was broken.  So I wrote test cases to test what
I was trying to do and fixed the underlying problem.
2013-03-26 10:19:55 -04:00
Nihad Abbasov 7ed0dc0185 use convenient method to check for empty project repo 2013-03-26 07:14:57 -07:00
Dmitriy Zaporozhets 58a1ed6dd3 Merge pull request #3398 from Andrew8xx8/spork
Spork support added
2013-03-26 06:44:52 -07:00
Dmitriy Zaporozhets da1cf5b9e7 enable callbacks for specs after notification 2013-03-26 15:16:06 +02:00
Dmitriy Zaporozhets c7bd99b040 refactor issue observer spec 2013-03-26 14:41:57 +02:00
Andrew8xx8 5949e30243 Spork support added 2013-03-26 13:38:42 +04:00
Dmitriy Zaporozhets e3e8b9fcb9 fixed tests 2013-03-26 11:17:49 +02:00
Dmitriy Zaporozhets bfebf10850 reject current_user from close issue emails 2013-03-26 11:06:24 +02:00
Dmitriy Zaporozhets 4b3950456d notification level for user 2013-03-26 10:48:07 +02:00
Dmitriy Zaporozhets cf6d4dc10c NotificationService for resolving email notification logic 2013-03-26 10:48:06 +02:00
Dmitriy Zaporozhets 448152ab94 Use NotificationService for observers pt1 2013-03-26 10:48:06 +02:00
Sytse Sijbrandij f7e630c452 Updating based on Dmitriy his comments. 2013-03-26 10:46:53 +02:00
Sytse Sijbrandij 83d3f7e052 Better header and detail why you need two times the storage. Also moving memory and storage to the bottom, OS is more important. 2013-03-26 10:46:53 +02:00
Sytse Sijbrandij 7e93aaa6e6 Corrected mistake, added hint for windows users. 2013-03-26 10:46:53 +02:00
Sytse Sijbrandij 77c802a4fe Combine it with the memory requirements that where already there. 2013-03-26 10:46:53 +02:00
Sytse Sijbrandij ec1a37875d Added memory requirements based on https://news.ycombinator.com/item?id=5423851 2013-03-26 10:46:53 +02:00
Andrew8xx8 242f6aa218 New issue button was not follows to external tracker if it is selected. fixed #3386 2013-03-26 12:28:26 +04:00
Sato Hiroyuki 33e236c631 Fix RoutingError when changing username to non ascii char. 2013-03-26 14:47:11 +09:00
Sato Hiroyuki b49c1cb161 Display note count on network graph. 2013-03-26 09:51:39 +09:00
Sato Hiroyuki 62ef763a80 Refector: clean up code. 2013-03-26 09:46:10 +09:00
Dmitriy Zaporozhets 90db28d6d0 Merge pull request #3377 from SaitoWu/grit_ext
bump version of grit_ext
2013-03-25 11:55:20 -07:00
Saito 7a4f70d79b bump version of grit_ext 2013-03-26 01:12:29 +08:00
Dmitriy Zaporozhets 8c9123943f Update changelog 2013-03-25 16:12:12 +02:00
Dmitriy Zaporozhets 795bb9cf65 Merge branch 'feature/login_with_username' 2013-03-25 16:10:30 +02:00
Dmitriy Zaporozhets 9d92433a7c login with both email or username 2013-03-25 16:10:14 +02:00
Dmitriy Zaporozhets 1496c01521 try to move wiki if it does not exist 2013-03-25 15:52:54 +02:00
Dmitriy Zaporozhets 6752968bb5 Updated changelog with transfer & security changes 2013-03-25 15:27:09 +02:00
Dmitriy Zaporozhets 6e78a1d7c8 Merge branch 'improve/project_transfer' 2013-03-25 15:20:42 +02:00
Dmitriy Zaporozhets 53e54ddf8a require gitlab-shell v1.2.0 now 2013-03-25 15:19:06 +02:00
Dmitriy Zaporozhets d6ac38133c Admin.projects: remove views and route specs 2013-03-25 14:58:43 +02:00
Dmitriy Zaporozhets 98bea4b1ff Updatev security tests since admin is a superuser now. Has access to any project 2013-03-25 13:40:08 +02:00
Dmitriy Zaporozhets c610347cc1 Removed not relevant tests for admin.projects 2013-03-25 13:36:08 +02:00
Dmitriy Zaporozhets d0df8a6ff8 remove project edit from admin area. Redesigned project page in admin area 2013-03-25 11:07:11 +02:00
Dmitriy Zaporozhets e292d7c17b Make transfer action in project controller 2013-03-25 10:48:30 +02:00
Dmitriy Zaporozhets ff35b37fd2 transfer also wiki repository when transfer a project 2013-03-25 10:47:47 +02:00
Dmitriy Zaporozhets 1fb99264a9 Use TransferContext for project 2013-03-25 10:47:22 +02:00
Dmitriy Zaporozhets 850881a2ef add admin ability to edit project settings from project area 2013-03-25 10:46:57 +02:00
Riyad Preukschas 6e15284844 Merge pull request #3354 from vinodc/install-docs-typo-fix
Fixing a minor typo in the installation docs
2013-03-25 00:49:19 -07:00
Dmitriy Zaporozhets afa9f6045a Merge branch 'more-links-in-readme' of /home/git/repositories/gitlab/gitlabhq 2013-03-25 07:39:23 +00:00
Vinod Chandru df46903dbe Fixing a minor typo in the installation docs 2013-03-24 20:23:02 -07:00
Dmitriy Zaporozhets 5f159d4bc0 Merge pull request #3335 from zzet/patch-4
Update databases.md
2013-03-24 03:44:14 -07:00
Andrew Kumanyaev 4cc27fd9e1 Update database.yml.postgresql 2013-03-24 14:10:32 +04:00
Dmitriy Zaporozhets 38ea3939b2 Merge branch 'hiroponz-fix-404-json-file' 2013-03-24 12:01:56 +02:00
Dmitriy Zaporozhets 29b0ac489b move edit to separate controller. This fixes #3265 2013-03-24 11:57:44 +02:00
Andrew Kumanyaev 159cd0d742 Update databases.md 2013-03-24 13:48:23 +04:00
Dmitriy Zaporozhets b6641d6932 Merge branch 'fix-404-json-file' of https://github.com/hiroponz/gitlabhq into hiroponz-fix-404-json-file 2013-03-24 11:26:57 +02:00
Dmitriy Zaporozhets 979dcdba95 security update of crack gem 2013-03-24 11:24:26 +02:00
Sytse Sijbrandij 0d56b1b07f Updated links to gitlab.com and added the last doc files. 2013-03-23 21:20:09 +01:00
Sytse Sijbrandij c4f8d34b7d spelling error 2013-03-23 21:06:00 +01:00
Sytse Sijbrandij de3b181a69 5.0 should no longer be on the roadmap 2013-03-23 21:05:42 +01:00
Dmitriy Zaporozhets 77faffbda3 Merge pull request #3305 from dosire/update-ruby
Update ruby to latest version.
2013-03-22 11:04:00 -07:00
Sytse Sijbrandij 5cc5b74e8e Update ruby to latest version. 2013-03-22 18:34:59 +01:00
Dmitriy Zaporozhets e48fdde4f8 Merge pull request #3300 from aus/patch-1
Change gollum repo to use https:// instead of git://
2013-03-22 10:11:15 -07:00
Dmitriy Zaporozhets 747706a83a Merge pull request #3303 from dosire/attribute
Attribution as mentioned in https://news.ycombinator.com/item?id=5423635
2013-03-22 10:10:07 -07:00
Sytse Sijbrandij 78dd9a1481 All involved are mentioned. https://news.ycombinator.com/item?id=5424050 2013-03-22 17:54:42 +01:00
Dmitriy Zaporozhets c0da61c6d8 fix xss issue in blame 2013-03-22 18:52:25 +02:00
Sytse Sijbrandij 3869cfecc1 Use real name. 2013-03-22 17:42:31 +01:00
Sytse Sijbrandij ccc8806758 Attribution as mentioned in https://news.ycombinator.com/item?id=5423635 2013-03-22 17:39:22 +01:00
Austin Robertson ba1dbd39fb Change Gemfile.lock repo to use https:// 2013-03-22 10:38:27 -05:00
Austin Robertson 693dcce6bc Change gollum repo to use https:// instead of git://
A lot of people might have firewalls blocking the git:// protocol. Using https:// makes this easier and matches the other git repositories in the Gemfile.
2013-03-22 10:31:19 -05:00
Dmitriy Zaporozhets de2c189ec1 fix blame view head nav 2013-03-22 15:11:16 +02:00
Dmitriy Zaporozhets 84043e8e44 Fix lines and line numbers being squashed in File -> blame 2013-03-22 15:08:02 +02:00
Dmitriy Zaporozhets 235605fc6d Merge pull request #3288 from hiroponz/fix-style-network-graph
Fix style of network graph.
2013-03-22 00:43:26 -07:00
Sato Hiroyuki f5e001bd8c Using arrowed line only if it connects to not first parent.
It is easy to see which branch is merged.
2013-03-22 16:09:21 +09:00
Sato Hiroyuki 26606aa2ec Fix style of network graph.
refs #3258
2013-03-22 10:11:53 +09:00
Dmitriy Zaporozhets 5f9d654939 Dont show '0 additions and 0 deletions' message for commit 2013-03-21 22:50:18 +02:00
Dmitriy Zaporozhets ad5ea14210 Move commit.show partial from commits/ to commit/ 2013-03-21 22:22:54 +02:00
Dmitriy Zaporozhets fec283889b fix commit-description css on commit.show 2013-03-21 22:22:21 +02:00
Dmitriy Zaporozhets c4299bb45a Move directory logic out of model. Use Gitlab:Shell class to interact with file system 2013-03-21 22:11:08 +02:00
Dmitriy Zaporozhets 0103363191 replace Gitolited mixin with Gitlab::ShellAdapter 2013-03-21 21:01:14 +02:00
Dmitriy Zaporozhets d6338a8482 Merge pull request #3258 from hiroponz/display-commit-msg
Display commit message on network graph.
2013-03-21 09:58:57 -07:00
Sato Hiroyuki 06c5389780 Fix travis failure randomly, because Capybara.default_wait_time is too short. 2013-03-21 15:24:06 +00:00
Sato Hiroyuki a1fe375e44 Fix 404 error while displaying json files.
It uses params[:id] instead of request.fullpath.
It should fix #3132.
2013-03-21 15:10:14 +00:00
Dmitriy Zaporozhets 02f70851e4 Update readme to match 5-0-stable 2013-03-21 16:29:53 +02:00
Sato Hiroyuki a19e3d898d Display icon and commit message on network graph. 2013-03-21 13:08:54 +00:00
Sato Hiroyuki 916c61fc64 Refactor: clean up code. 2013-03-21 12:34:15 +00:00
Sato Hiroyuki 1f6b6b6c62 Rotating graph orientation. 2013-03-20 12:28:22 +00:00
Sato Hiroyuki 175e09f167 Change graph element size. 2013-03-19 19:27:15 +09:00
Sato Hiroyuki 351c952192 Refactor: extract method. 2013-03-19 18:42:46 +09:00
Sato Hiroyuki 96a584211b Refactor: Clean up code. 2013-03-19 18:08:27 +09:00
210 changed files with 2803 additions and 2236 deletions

2
.rspec
View File

@ -1 +1 @@
--colour
--colour --drb

View File

@ -8,7 +8,7 @@ branches:
only:
- 'master'
rvm:
- 1.9.3-p327
- 1.9.3-p392
services:
- mysql
- postgresql

View File

@ -1,3 +1,10 @@
v 5.1.0
- You can login with email or username now
- Corrected project transfer rollback when repository cannot be moved
- Move both repo and wiki when project transfer requrested
- Admin area: project editing was removed from admin namespace
- Access: admin user has now access to any project.
v 5.0.0
- Replaced gitolite with gitlab-shell
- Removed gitolite-related libraries
@ -14,7 +21,7 @@ v 5.0.0
- Add validations for Group and Team names
- Restyle team page for project
- Update capybara, rspec-rails, poltergeist to recent versions
- Wiki on git using Gollum
- Wiki on git using Gollum
- Added Solarized Dark theme for code review
- Dont show user emails in autocomplete lists, profile pages
- Added settings tab for group, team, project
@ -24,7 +31,7 @@ v 5.0.0
- Fixed search field on projects page
- Added teams to search autocomplete
- Move groups and teams on dashboard sidebar to sub-tabs
- API: improved return codes and docs.
- API: improved return codes and docs. (Felix Gilcher, Sebastian Ziebell)
- Redesign wall to be more like chat
- Snippets, Wall features are disabled by default for new projects
@ -56,7 +63,7 @@ v 4.1.0
- cleanup rake tasks
- fix backup/restore
- scss cleanup
- show preview for note images
- show preview for note images
- improved network-graph
- get rid of app/roles/
- added new classes Team, Repository
@ -70,7 +77,7 @@ v 4.1.0
v 4.0.0
- Remove project code and path from API. Use id instead
- Return valid clonable url to repo for web hook
- Fixed backup issue
- Fixed backup issue
- Reorganized settings
- Fixed commits compare
- Refactored scss

View File

@ -1,35 +1,18 @@
# Contribute to GitLab
If you have a question or want to contribute to GitLab this guide show you the appropriate channel to use.
This guide details how to use pull requests and the issues to improve GitLab.
## Ruling out common errors
## Closing policy for pull requests and issues
Some errors are common and it may so happen, that you are not the only one who stumbled over a particular issue. We have [collected several of those and documented quick solutions](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide) for them.
## Support forum
Please visit our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) for any kind of question regarding the usage or adiministration/configuration of GitLab.
### Use the support forum if ...
* You get permission denied errors
* You can't see your repos
* You have issues cloning, pulling or pushing
* You have issues with web_hooks not firing
**Search** for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and had it resolved.
## Paid support
Community support in the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) is done by volunteers. A support subscription is available from [GitLab.com](http://blog.gitlab.com/subscription/)
## Feature suggestions
Feature suggestions don't belong in issues but can go to [Feedback forum](http://gitlab.uservoice.com/forums/176466-general) where they can be voted on.
Pull requests and issues not in line with the guidelines listed in this document will be closed with just a link to this paragraph. GitLab is a popular open source project and the capacity to deal with issues and pull requests is limited. To get support for your problems please use other channels as detailed in [the getting help section of the readme](https://github.com/gitlabhq/gitlabhq#getting-help). Professional [support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from [GitLab.com](http://www.gitlab.com/).
## Pull requests
Code speaks louder than words. If you can please submit a pull request with the fix including tests. The workflow to make a pull request is as follows:
We welcome pull request with improvements to GitLab code and/or documentation. The issues we would really like a pull request for are listed with the [status 'accepting merge/pull requests' on our feedback forum](http://feedback.gitlab.com/forums/176466-general/status/796455) but other improvements are also welcome.
### Pull request guidelines
If you can please submit a pull request with the fix including tests. The workflow to make a pull request is as follows:
1. Fork the project on GitHub
1. Create a feature branch
@ -51,26 +34,20 @@ We will accept pull requests if:
For examples of feedback on pull requests please look at already [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed).
## Submitting via GitHub's issue tracker
## Issue tracker
* For obvious bugs or misbehavior in GitLab in the master branch. Please include the revision id and a reproducible test case.
* For problematic or insufficient documentation. Please give a suggestion on how to improve it.
The [issue tracker](https://github.com/gitlabhq/gitlabhq/issues) is only for obvious bugs or misbehavior in the master branch of GitLab. When submitting an issue please conform to the issue submission guidelines listed below.
If you're unsure where to post, post it to the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) first.
There are a lot of helpful GitLab users there who may be able to help you quickly.
If your particular issue turns out to be a bug, it will find its way from there to the [issue tracker on GitHub](https://github.com/gitlabhq/gitlabhq/issues).
Please send a pull request with a tested solution or a pull request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there.
### When submitting an issue
### Issue tracker guidelines
**Search** for similar entries before submitting your own, there's a good chance somebody else had the same issue or idea. Show your support with `:+1:` and/or join the discussion.
Please consider the following points when submitting an **issue**:
* Summarize your issue in one sentence (what happened wrong, when you did/expected something else)
* Describe your issue in detail (including steps to reproduce)
* Summarize your issue in one sentence (what goes wrong, what did you expect to happen)
* Describe your issue in detail
* How can we reproduce the issue on the [GitLab Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) (start with: vagrant destroy && vagrant up && vagrant ssh)
* Add the last commit sha1 of the GitLab version you used to replicate the issue
* Add logs or screen shots when possible
* Link to the line of code that might be responsible for the problem
* Describe your setup (use relevant parts from `sudo -u gitlab -H bundle exec rake gitlab:env:info`)
## Thank you!
By taking the time to use the right channel, you help the development team to organize and prioritize issues and suggestions in order to make GitLab a better product for us all.

15
Gemfile
View File

@ -22,8 +22,9 @@ gem 'omniauth-twitter'
gem 'omniauth-github'
# Extracting information from a git repository
gem "gitlab-grit", '~> 1.0.0', require: 'grit'
gem 'grit_ext', '~> 0.6.2'
# Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead
gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: '42297cdcee16284d2e4eff23d41377f52fc28b9d'
gem 'grit_ext', '~> 0.8.1'
# Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 1.0.0', require: 'grack'
@ -104,7 +105,7 @@ gem 'settingslogic'
# github-linquist needs pygments 0.4.2 but Gollum 2.4.11
# requires pygments 0.3.2. The latest master Gollum has been updated
# to use pygments 0.4.2. Change this after next Gollum release.
gem "gollum", "~> 2.4.0", git: "git://github.com/gollum/gollum.git", ref: "5dcd3c8c8f"
gem "gollum", "~> 2.4.0", git: "https://github.com/gollum/gollum.git", ref: "5dcd3c8c8f"
# Misc
gem "foreman"
@ -153,9 +154,9 @@ end
group :development, :test do
gem 'coveralls', require: false
gem 'rails-dev-tweaks'
gem 'spinach-rails', '0.2.0'
gem "rspec-rails", '2.12.2'
gem "capybara", '2.0.2'
gem 'spinach-rails'
gem "rspec-rails"
gem "capybara"
gem "pry"
gem "awesome_print"
gem "database_cleaner"
@ -173,6 +174,8 @@ group :development, :test do
# PhantomJS driver for Capybara
gem 'poltergeist', '1.1.0'
gem 'spork', '~> 1.0rc'
end
group :test do

View File

@ -1,5 +1,29 @@
GIT
remote: git://github.com/gollum/gollum.git
remote: https://github.com/ctran/annotate_models.git
revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e
specs:
annotate (2.6.0.beta1)
activerecord (>= 2.3.0)
rake (>= 0.8.7)
GIT
remote: https://github.com/gitlabhq/grit.git
revision: 42297cdcee16284d2e4eff23d41377f52fc28b9d
ref: 42297cdcee16284d2e4eff23d41377f52fc28b9d
specs:
grit (2.5.0)
diff-lcs (~> 1.1)
mime-types (~> 1.15)
posix-spawn (~> 0.3.6)
GIT
remote: https://github.com/gitlabhq/raphael-rails.git
revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58
specs:
raphael-rails (2.1.0)
GIT
remote: https://github.com/gollum/gollum.git
revision: 5dcd3c8c8f68158e43ff79861279088ee56d0ebe
ref: 5dcd3c8c8f
specs:
@ -15,20 +39,6 @@ GIT
stringex (~> 1.5.1)
useragent (~> 0.4.16)
GIT
remote: https://github.com/ctran/annotate_models.git
revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e
specs:
annotate (2.6.0.beta1)
activerecord (>= 2.3.0)
rake (>= 0.8.7)
GIT
remote: https://github.com/gitlabhq/raphael-rails.git
revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58
specs:
raphael-rails (2.1.0)
GEM
remote: https://rubygems.org/
specs:
@ -95,7 +105,7 @@ GEM
thor (~> 0.14)
code_analyzer (0.3.1)
sexp_processor
coderay (1.0.8)
coderay (1.0.9)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
@ -112,7 +122,7 @@ GEM
rest-client
simplecov (>= 0.7)
thor
crack (0.3.1)
crack (0.3.2)
daemons (1.1.9)
database_cleaner (0.9.1)
debug_inspector (0.0.2)
@ -122,7 +132,7 @@ GEM
orm_adapter (~> 0.1)
railties (~> 3.1)
warden (~> 1.2.1)
diff-lcs (1.1.3)
diff-lcs (1.2.1)
draper (1.1.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
@ -137,7 +147,7 @@ GEM
eventmachine (1.0.0)
execjs (1.4.0)
multi_json (~> 1.0)
facter (1.6.17)
facter (1.6.18)
factory_girl (4.1.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.1.0)
@ -166,10 +176,6 @@ GEM
github-markup (0.7.5)
gitlab-grack (1.0.0)
rack (~> 1.4.1)
gitlab-grit (1.0.0)
diff-lcs (~> 1.1)
mime-types (~> 1.15)
posix-spawn (~> 0.3.6)
gitlab-pygments.rb (0.3.2)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
@ -194,19 +200,16 @@ GEM
grape-entity (0.2.0)
activesupport
multi_json (>= 1.3.2)
grit (2.5.0)
diff-lcs (~> 1.1)
mime-types (~> 1.15)
posix-spawn (~> 0.3.6)
grit_ext (0.6.2)
grit_ext (0.8.1)
charlock_holmes (~> 0.6.9)
growl (1.0.3)
guard (1.5.4)
listen (>= 0.4.2)
guard (1.6.2)
listen (>= 0.6.0)
lumberjack (>= 1.0.2)
pry (>= 0.9.10)
terminal-table (>= 1.4.3)
thor (>= 0.14.6)
guard-rspec (2.1.2)
guard-rspec (2.5.1)
guard (>= 1.1)
rspec (~> 2.11)
guard-spinach (0.0.2)
@ -246,9 +249,9 @@ GEM
addressable (~> 2.3)
letter_opener (1.0.0)
launchy (>= 2.0.4)
libv8 (3.3.10.4)
listen (0.5.3)
lumberjack (1.0.2)
libv8 (3.11.8.17)
listen (0.7.3)
lumberjack (1.0.3)
mail (2.5.3)
i18n (>= 0.4.0)
mime-types (~> 1.16)
@ -257,7 +260,7 @@ GEM
mime-types (1.21)
modernizr (2.6.2)
sprockets (~> 2.0)
multi_json (1.7.1)
multi_json (1.7.2)
multi_xml (0.5.3)
multipart-post (1.1.5)
mustache (0.99.4)
@ -297,11 +300,10 @@ GEM
http_parser.rb (~> 0.5.3)
polyglot (0.3.3)
posix-spawn (0.3.6)
progressbar (0.12.0)
pry (0.9.10)
pry (0.9.12)
coderay (~> 1.0.5)
method_source (~> 0.8)
slop (~> 3.3.1)
slop (~> 3.4)
pygments.rb (0.4.2)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
@ -334,14 +336,14 @@ GEM
rails-dev-tweaks (0.6.1)
actionpack (~> 3.1)
railties (~> 3.1)
rails_best_practices (1.13.2)
rails_best_practices (1.13.4)
activesupport
awesome_print
code_analyzer
colored
erubis
i18n
progressbar
ruby-progressbar
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
@ -350,14 +352,14 @@ GEM
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
raindrops (0.10.0)
rake (10.0.3)
rake (10.0.4)
rb-fsevent (0.9.2)
rb-inotify (0.8.8)
ffi (>= 0.5.0)
rdoc (3.12.2)
json (~> 1.4)
redcarpet (2.2.2)
redis (3.0.2)
redis (3.0.3)
redis-actionpack (3.2.3)
actionpack (~> 3.2.3)
redis-rack (~> 1.4.0)
@ -376,30 +378,32 @@ GEM
redis-store (~> 1.1.0)
redis-store (1.1.3)
redis (>= 2.2.0)
ref (1.0.4)
request_store (1.0.5)
rest-client (1.6.7)
mime-types (>= 1.16)
rspec (2.12.0)
rspec-core (~> 2.12.0)
rspec-expectations (~> 2.12.0)
rspec-mocks (~> 2.12.0)
rspec-core (2.12.0)
rspec-expectations (2.12.0)
diff-lcs (~> 1.1.3)
rspec-mocks (2.12.0)
rspec-rails (2.12.2)
rspec (2.13.0)
rspec-core (~> 2.13.0)
rspec-expectations (~> 2.13.0)
rspec-mocks (~> 2.13.0)
rspec-core (2.13.1)
rspec-expectations (2.13.0)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.13.0)
rspec-rails (2.13.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 2.12.0)
rspec-expectations (~> 2.12.0)
rspec-mocks (~> 2.12.0)
rspec-core (~> 2.13.0)
rspec-expectations (~> 2.13.0)
rspec-mocks (~> 2.13.0)
ruby-progressbar (1.0.2)
rubyntlm (0.1.1)
rubyzip (0.9.9)
sanitize (2.0.3)
nokogiri (>= 1.4.4, < 1.6)
sass (3.2.5)
sass-rails (3.2.5)
sass (3.2.7)
sass-rails (3.2.6)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
@ -418,10 +422,10 @@ GEM
rubyzip
websocket (~> 1.0.4)
settingslogic (2.0.9)
sexp_processor (4.1.3)
sexp_processor (4.2.0)
shoulda-matchers (1.3.0)
activesupport (>= 3.0.0)
sidekiq (2.7.5)
sidekiq (2.8.0)
celluloid (~> 0.12.0)
connection_pool (~> 1.0)
multi_json (~> 1)
@ -439,7 +443,7 @@ GEM
slim (1.3.6)
temple (~> 0.5.5)
tilt (~> 1.3.3)
slop (3.3.3)
slop (3.4.4)
spinach (0.7.0)
colorize
gherkin-ruby (~> 0.2.0)
@ -447,6 +451,7 @@ GEM
capybara (~> 2.0.0)
railties (>= 3)
spinach (>= 0.4)
spork (1.0.0rc3)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
@ -456,14 +461,16 @@ GEM
state_machine (1.1.2)
stringex (1.5.1)
temple (0.5.5)
terminal-table (1.4.5)
test_after_commit (0.0.1)
therubyracer (0.10.2)
libv8 (~> 3.3.10)
therubyracer (0.11.4)
libv8 (~> 3.11.8.12)
ref
thin (1.5.0)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
thor (0.17.0)
thor (0.18.0)
tilt (1.3.6)
timers (1.1.0)
treetop (1.4.12)
@ -501,7 +508,7 @@ DEPENDENCIES
better_errors
binding_of_caller
bootstrap-sass (= 2.2.1.1)
capybara (= 2.0.2)
capybara
carrierwave
chosen-rails (= 0.9.8)
coffee-rails (~> 3.2.2)
@ -521,7 +528,6 @@ DEPENDENCIES
github-linguist (~> 2.3.4)
github-markup (~> 0.7.4)
gitlab-grack (~> 1.0.0)
gitlab-grit (~> 1.0.0)
gitlab-pygments.rb (~> 0.3.2)
gitlab_meta (= 5.0)
gitlab_omniauth-ldap (= 1.0.2)
@ -530,7 +536,8 @@ DEPENDENCIES
gon
grape (~> 0.3.1)
grape-entity (~> 0.2.0)
grit_ext (~> 0.6.2)
grit (~> 2.5.0)!
grit_ext (~> 0.8.1)
growl
guard-rspec
guard-spinach
@ -561,7 +568,7 @@ DEPENDENCIES
rb-inotify
redcarpet (~> 2.2.2)
redis-rails
rspec-rails (= 2.12.2)
rspec-rails
sass-rails (~> 3.2.5)
sdoc
seed-fu
@ -573,7 +580,8 @@ DEPENDENCIES
sinatra
six
slim
spinach-rails (= 0.2.0)
spinach-rails
spork (~> 1.0rc)
stamp
state_machine
test_after_commit

View File

@ -12,7 +12,7 @@
* powered by Ruby on Rails
* completely free and open source (MIT license)
* used by 10.000 organizations to keep their code secure
* used by more than 10.000 organizations to keep their code secure
### Code status
@ -30,7 +30,7 @@
* GitLab.org community site: [Homepage](http://gitlab.org) [Screenshots](http://gitlab.org/screenshots/) [Blog](http://blog.gitlab.org/) [Demo](http://demo.gitlabhq.com/users/sign_in)
* GitLab.com commercial services: [Homepage](http://blog.gitlab.com/) [GitLab Cloud](http://blog.gitlab.com/cloud/) [Subscription](http://blog.gitlab.com/subscription/) [Consultancy](http://blog.gitlab.com/consultancy/) [Blog](http://blog.gitlab.com/blog/)
* GitLab.com commercial services: [Homepage](http://www.gitlab.com/) [Subscription](http://www.gitlab.com/subscription/) [Consultancy](http://www.gitlab.com/consultancy/) [GitLab Cloud](http://www.gitlab.com/cloud/) [Blog](http://blog.gitlab.com/)
* GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server
@ -47,22 +47,45 @@
### Installation
#### For production
#### Official production installation
Follow the installation guide for production server.
* [Installation guide for latest stable release (4.2)](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md) - **Recommended**
* [Installation guide for latest stable release (5.0)](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) - **Recommended**
* [Installation guide for the current master branch (5.0)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md)
* [Installation guide for the current master branch (5.1)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md)
#### For development
#### Official development installation
If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working sandboxed and with all dependencies.
If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working with all dependencies.
* [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm)
### Starting
#### Unsupported production installation
* [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes) for setup on different platforms
* [Unofficial installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides)
* [BitNami one-click installers](http://bitnami.com/stack/gitlab)
* [TurnKey Linux virtual appliance](http://www.turnkeylinux.org/gitlab)
### New versions and upgrading
Each month on the 22th a new version is released together with an upgrade guide.
* [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki)
* [Changelog](https://github.com/gitlabhq/gitlabhq/blob/master/CHANGELOG)
* [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md)
### Getting started
1. The Installation guide contains instructions to download an init script and run that on boot. With the init script you can also start GitLab
@ -100,38 +123,35 @@ If you want to contribute, please first read our [Contributing Guidelines](https
bundle exec rake spinach
### Getting help
* [Troubleshooting guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide)
* [Support forum](https://groups.google.com/forum/#!forum/gitlabhq)
* [Feedback and suggestions forum](http://gitlab.uservoice.com/forums/176466-general)
* [Support subscription](http://blog.gitlab.com/subscription/)
* [Consultancy](http://blog.gitlab.com/consultancy/)
### New versions and the API
Each month on the 22th a new version is released together with an upgrade guide.
* [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki)
* [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md)
### Other documentation
### GitLab interfaces
* [GitLab API](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/README.md)
* [Rake tasks](https://github.com/gitlabhq/gitlabhq/tree/master/doc/raketasks)
* [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes)
* [Directory structure](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/structure.md)
* [Databases](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/databases.md)
### Getting help
* [Troubleshooting guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide) contains solutions to common problems.
* [Support forum](https://groups.google.com/forum/#!forum/gitlabhq) is the best place to ask questions. For example you can use it if you have questions about: permission denied errors, invisible repos, can't clone/pull/push or with web hooks that don't fire. Please search for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and had it resolved. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there to a fix.
* [Feedback and suggestions forum](http://gitlab.uservoice.com/forums/176466-general) is the place to propose and discuss new features for GitLab.
* [Support subscription](http://www.gitlab.com/subscription/) connect you to the knowledge of GitLab experts that will resolve your issues and answer your questions.
* [Consultancy](http://www.gitlab.com/consultancy/) allows you hire GitLab exports for installations, upgrades and customizations.
* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) describes how to submit pull requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed without comment.
### Getting in touch
* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md)
* [Core team](https://github.com/gitlabhq?tab=members)
* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors)

View File

@ -1,7 +1,5 @@
## GitLab Roadmap
### v5.0 March 22
### v5.1 April 22
* Replace gitolite with gitlab-shell
* Usability improvements
* Notification improvements
* Not decided yet.

View File

@ -1 +1 @@
5.0.0
5.1.0pre

View File

@ -3,3 +3,11 @@ $ ->
container = $(@).closest(".js-toggler-container")
container.toggleClass("on")
$("body").on "click", ".js-toggle-visibility-link", (e) ->
$(@).find('i').
toggleClass('icon-chevron-down').
toggleClass('icon-chevron-up')
container = $(".js-toggle-visibility-container")
container.toggleClass("hide")
e.preventDefault()

View File

@ -5,6 +5,10 @@ class BranchGraph
@mspace = 0
@parents = {}
@colors = ["#000"]
@offsetX = 120
@offsetY = 20
@unitTime = 30
@unitSpace = 10
@load()
load: ->
@ -20,8 +24,6 @@ class BranchGraph
prepareData: (@days, @commits) ->
@collectParents()
@mtime += 4
@mspace += 10
for c in @commits
c.isParent = true if c.id of @parents
@ -35,6 +37,7 @@ class BranchGraph
@mspace = Math.max(@mspace, c.space)
for p in c.parents
@parents[p[0]] = true
@mspace = Math.max(@mspace, p[1])
collectColors: ->
k = 0
@ -46,25 +49,23 @@ class BranchGraph
k++
buildGraph: ->
graphHeight = $(@element).height()
graphWidth = $(@element).width()
ch = @mspace * 20 + 100
cw = Math.max(graphWidth, @mtime * 20 + 260)
r = Raphael(@element.get(0), cw, ch)
ch = Math.max(graphHeight, @offsetY + @unitTime * @mtime + 150)
cw = Math.max(graphWidth, @offsetX + @unitSpace * @mspace + 300)
@r = r = Raphael(@element.get(0), cw, ch)
top = r.set()
cuday = 0
cumonth = ""
offsetX = 20
offsetY = 60
barWidth = Math.max(graphWidth, @days.length * 20 + 320)
scrollLeft = cw
@raphael = r
r.rect(0, 0, barWidth, 20).attr fill: "#222"
r.rect(0, 20, barWidth, 20).attr fill: "#444"
barHeight = Math.max(graphHeight, @unitTime * @days.length + 320)
r.rect(0, 0, 26, barHeight).attr fill: "#222"
r.rect(26, 0, 20, barHeight).attr fill: "#444"
for day, mm in @days
if cuday isnt day[0]
# Dates
r.text(offsetX + mm * 20, 31, day[0])
r.text(36, @offsetY + @unitTime * mm, day[0])
.attr(
font: "12px Monaco, monospace"
fill: "#DDD"
@ -73,7 +74,7 @@ class BranchGraph
if cumonth isnt day[1]
# Months
r.text(offsetX + mm * 20, 11, day[1])
r.text(13, @offsetY + @unitTime * mm, day[1])
.attr(
font: "12px Monaco, monospace"
fill: "#EEE"
@ -81,61 +82,20 @@ class BranchGraph
cumonth = day[1]
for commit in @commits
x = offsetX + 20 * commit.time
y = offsetY + 10 * commit.space
# Draw dot
r.circle(x, y, 3).attr(
fill: @colors[commit.space]
stroke: "none"
)
x = @offsetX + @unitSpace * (@mspace - commit.space)
y = @offsetY + @unitTime * commit.time
# Draw lines
for parent in commit.parents
parentCommit = @preparedCommits[parent[0]]
parentX = offsetX + 20 * parentCommit.time
parentY1 = offsetY + 10 * parentCommit.space
parentY2 = offsetY + 10 * parent[1]
if parentCommit.space is commit.space and parentCommit.space is parent[1]
r.path(["M", x, y, "L", parentX, parentY1]).attr(
stroke: @colors[parentCommit.space]
"stroke-width": 2
)
@drawDot(x, y, commit)
else if parentCommit.space < commit.space
if y is parentY2
r.path(["M", x - 5, y, "l-5,-2,0,4,5,-2", "L", x - 10, y, "L", x - 15, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr(
stroke: @colors[commit.space]
"stroke-width": 2
)
@drawLines(x, y, commit)
else
r.path(["M", x - 3, y - 6, "l-4,-3,4,-2,0,5", "L", x - 5, y - 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr(
stroke: @colors[commit.space]
"stroke-width": 2
)
@appendLabel(x, y, commit.refs) if commit.refs
else
r.path(["M", x - 3, y + 6, "l-4,3,4,2,0,-5", "L", x - 5, y + 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr(
stroke: @colors[parentCommit.space]
"stroke-width": 2
)
@appendAnchor(top, commit, x, y)
@appendLabel x, y, commit.refs if commit.refs
# Mark commit and displayed in the center
if commit.id is @options.commit_id
r.path(["M", x, y - 5, "L", x + 4, y - 15, "L", x - 4, y - 15, "Z"]).attr(
fill: "#000"
"fill-opacity": .7
stroke: "none"
)
scrollLeft = x - graphWidth / 2
@appendAnchor top, commit, x, y
@markCommit(x, y, commit, graphHeight)
top.toFront()
@element.scrollLeft scrollLeft
@bindEvents()
bindEvents: ->
@ -167,35 +127,37 @@ class BranchGraph
element.scrollTop element.scrollTop() + 50 if event.keyCode is 40
appendLabel: (x, y, refs) ->
r = @raphael
r = @r
shortrefs = refs
# Truncate if longer than 15 chars
shortrefs = shortrefs.substr(0, 15) + "" if shortrefs.length > 17
text = r.text(x + 5, y + 8 + 10, shortrefs).attr(
text = r.text(x + 4, y, shortrefs).attr(
"text-anchor": "start"
font: "10px Monaco, monospace"
fill: "#FFF"
title: refs
)
textbox = text.getBBox()
text.transform ["t", textbox.height / -4, textbox.width / 2 + 5, "r90"]
# Create rectangle based on the size of the textbox
rect = r.rect(x, y, textbox.width + 15, textbox.height + 5, 4).attr(
rect = r.rect(x, y - 7, textbox.width + 5, textbox.height + 5, 4).attr(
fill: "#000"
"fill-opacity": .7
"fill-opacity": .5
stroke: "none"
)
triangle = r.path(["M", x, y + 5, "L", x + 4, y + 15, "L", x - 4, y + 15, "Z"]).attr(
triangle = r.path(["M", x - 5, y, "L", x - 15, y - 4, "L", x - 15, y + 4, "Z"]).attr(
fill: "#000"
"fill-opacity": .7
"fill-opacity": .5
stroke: "none"
)
# Rotate and reposition rectangle over text
rect.transform ["r", 90, x, y, "t", 15, -9]
label = r.set(rect, text)
label.transform(["t", -rect.getBBox().width - 15, 0])
# Set text to front
text.toFront()
appendAnchor: (top, commit, x, y) ->
r = @raphael
r = @r
options = @options
anchor = r.circle(x, y, 10).attr(
fill: "#000"
@ -204,18 +166,92 @@ class BranchGraph
).click(->
window.open options.commit_url.replace("%s", commit.id), "_blank"
).hover(->
@tooltip = r.commitTooltip(x, y + 5, commit)
@tooltip = r.commitTooltip(x + 5, y, commit)
top.push @tooltip.insertBefore(this)
, ->
@tooltip and @tooltip.remove() and delete @tooltip
)
top.push anchor
drawDot: (x, y, commit) ->
r = @r
r.circle(x, y, 3).attr(
fill: @colors[commit.space]
stroke: "none"
)
r.rect(@offsetX + @unitSpace * @mspace + 10, y - 10, 20, 20).attr(
fill: "url(#{commit.author.icon})"
stroke: @colors[commit.space]
"stroke-width": 2
)
r.text(@offsetX + @unitSpace * @mspace + 35, y, commit.message.split("\n")[0]).attr(
"text-anchor": "start"
font: "14px Monaco, monospace"
)
drawLines: (x, y, commit) ->
r = @r
for parent, i in commit.parents
parentCommit = @preparedCommits[parent[0]]
parentY = @offsetY + @unitTime * parentCommit.time
parentX1 = @offsetX + @unitSpace * (@mspace - parentCommit.space)
parentX2 = @offsetX + @unitSpace * (@mspace - parent[1])
# Set line color
if parentCommit.space <= commit.space
color = @colors[commit.space]
else
color = @colors[parentCommit.space]
# Build line shape
if parent[1] is commit.space
offset = [0, 5]
arrow = "l-2,5,4,0,-2,-5,0,5"
else if parent[1] < commit.space
offset = [3, 3]
arrow = "l5,0,-2,4,-3,-4,4,2"
else
offset = [-3, 3]
arrow = "l-5,0,2,4,3,-4,-4,2"
# Start point
route = ["M", x + offset[0], y + offset[1]]
# Add arrow if not first parent
if i > 0
route.push(arrow)
# Circumvent if overlap
if commit.space isnt parentCommit.space or commit.space isnt parent[1]
route.push(
"L", parentX2, y + 10,
"L", parentX2, parentY - 5,
)
# End point
route.push("L", parentX1, parentY)
r
.path(route)
.attr(
stroke: color
"stroke-width": 2)
markCommit: (x, y, commit, graphHeight) ->
if commit.id is @options.commit_id
r = @r
r.path(["M", x + 5, y, "L", x + 15, y + 4, "L", x + 15, y - 4, "Z"]).attr(
fill: "#000"
"fill-opacity": .5
stroke: "none"
)
# Displayed in the center
@element.scrollTop(y - graphHeight / 2)
Raphael::commitTooltip = (x, y, commit) ->
icon = undefined
nameText = undefined
idText = undefined
messageText = undefined
boxWidth = 300
boxHeight = 200
icon = @image(commit.author.icon, x, y, 20, 20)

View File

@ -0,0 +1,9 @@
$.fn.showAndHide = ->
$(@).show().
delay(3000).
fadeOut()
$.fn.enableButton = ->
$(@).removeAttr('disabled').
removeClass('disabled')

View File

@ -7,6 +7,8 @@ window.slugify = (text) ->
window.ajaxGet = (url) ->
$.ajax({type: "GET", url: url, dataType: "script"})
window.showAndHide = (selector) ->
window.errorMessage = (message) ->
ehtml = $("<p>")
ehtml.addClass("error_message")

View File

@ -15,6 +15,8 @@ $ ->
$(this).find('.update-failed').hide()
$('.update-username form').on 'ajax:complete', ->
$(this).find('.save-btn').removeAttr('disabled')
$(this).find('.save-btn').removeClass('disabled')
$(this).find('.btn-save').enableButton()
$(this).find('.loading-gif').hide()
$('.update-notifications').on 'ajax:complete', ->
$(this).find('.btn-save').enableButton()

View File

@ -6,7 +6,7 @@ $ ->
$('span.log_loading:first').removeClass('hide')
$('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live "click", ->
$("#tree-content-holder").hide("slide", { direction: "left" }, 150)
$("#tree-content-holder").hide("slide", { direction: "left" }, 400)
# Make the entire tree-item row clickable, but not if clicking another link (like a commit message)
$("#tree-slider .tree-item").live 'click', (e) ->

View File

@ -58,14 +58,26 @@
form.show()
renderNote: (note) ->
author = '<strong class="wall-author">' + note.author.name + '</strong>'
body = '<span class="wall-text">' + linkify(sanitize(note.body)) + '</span>'
file = ''
time = '<abbr class="timeago" title="' + note.created_at + '">' + note.created_at + '</time>'
template = Wall.noteTemplate()
template = template.replace('{{author_name}}', note.author.name)
template = template.replace('{{created_at}}', note.created_at)
template = template.replace('{{text}}', linkify(sanitize(note.body)))
if note.attachment
file = '<span class="wall-file"><a href="/files/note/' + note.id + '/' + note.attachment + '">' + note.attachment + '</a></span>'
html = '<li>' + author + body + file + time + '</li>'
file = '<i class="icon-paper-clip"/><a href="/files/note/' + note.id + '/' + note.attachment + '">' + note.attachment + '</a>'
else
file = ''
template = template.replace('{{file}}', file)
$('ul.notes').append(html)
$('ul.notes').append(template)
noteTemplate: ->
return '<li>
<strong class="wall-author">{{author_name}}</strong>
<span class="wall-text">
{{text}}
<span class="wall-file">{{file}}</span>
</span>
<abbr class="timeago" title="{{created_at}}">{{created_at}}</abbr>
</li>'

View File

@ -100,8 +100,9 @@
margin-top: 0;
}
.btn-tiny {
@include box-shadow(0 0px 0px 1px #f1f1f1);
.btn {
position: relative;
top: -2px;
}
.nav-pills {

View File

@ -413,3 +413,9 @@
padding: 4px;
background-color: #EEE;
}
.commit-description {
background: none;
border: none;
margin: 0;
}

View File

@ -12,7 +12,7 @@
.graph {
background: #f1f1f1;
cursor: move;
height: 70%;
height: 500px;
overflow: hidden;
}
}

View File

@ -1,68 +1,64 @@
/*
* Main Menu of Application
*
*/
ul.main_menu {
margin: auto;
.main-nav {
margin: 30px 0;
margin-top: 10px;
height: 38px;
position: relative;
overflow: hidden;
.count {
position: relative;
top: -1px;
display: inline-block;
height: 15px;
margin: 0 0 0 5px;
padding: 0 8px 1px 8px;
height: auto;
font-size: 0.82em;
line-height: 14px;
text-align: center;
color: #777;
}
.label {
background: $hover;
text-shadow: none;
color: $style_color;
}
li {
list-style-type: none;
margin: 0;
display: table-cell;
width: 1%;
border-bottom: 2px solid #EEE;
&.active {
border-bottom: 2px solid #474D57;
a {
color: $style_color;
}
}
border-bottom: 1px solid #E1E1E1;
&.home {
a {
i {
font-size: 20px;
position: relative;
top: 4px;
ul {
margin: auto;
height: 39px;
position: relative;
top: 3px;
overflow: hidden;
.count {
position: relative;
top: -1px;
display: inline-block;
height: 15px;
margin: 0 0 0 5px;
padding: 0 8px 1px 8px;
height: auto;
font-size: 0.82em;
line-height: 14px;
text-align: center;
color: #777;
}
.label {
background: $hover;
text-shadow: none;
color: $style_color;
}
li {
list-style-type: none;
margin: 0;
display: table-cell;
width: 1%;
&.active {
border-bottom: 3px solid #777;
a {
color: $style_color;
font-weight: bolder;
}
}
&.home {
a {
i {
font-size: 20px;
position: relative;
top: 4px;
}
}
}
}
}
a {
display: block;
text-align: center;
font-weight: normal;
height: 36px;
line-height: 36px;
color: #777;
text-shadow: 0 1px 1px white;
padding: 0 10px;
a {
display: block;
text-align: center;
font-weight: normal;
height: 36px;
line-height: 34px;
color: #777;
text-shadow: 0 1px 1px white;
padding: 0 10px;
}
}
}
/*
* End of Main Menu
*
*/

View File

@ -274,6 +274,15 @@ ul.notes {
}
.common-note-form {
margin: 0;
height: 140px;
background: #F9F9F9;
padding: 3px;
padding-bottom: 25px;
border: 1px solid #DDD;
}
.note-form-actions {
background: #F9F9F9;
@ -281,8 +290,8 @@ ul.notes {
padding: 0 5px;
.note-form-option {
margin-top: 8px;
margin-left: 15px;
margin-top: 10px;
margin-left: 30px;
@extend .pull-left;
}

View File

@ -14,12 +14,31 @@
.notes {
margin-bottom: 160px;
background: #FFE;
border: 1px solid #EED;
> li {
@extend .clearfix;
border-bottom: 1px solid #EED;
padding: 10px;
}
.wall-author {
color: #666;
margin-right: 10px;
border-right: 1px solid #CCC;
padding-right: 5px
float: left;
font-size: 12px;
width: 120px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.wall-text {
border-left: 1px solid #CCC;
margin-left: 10px;
padding-left: 10px;
float: left;
width: 75%;
}
.wall-file {

View File

@ -12,7 +12,6 @@ class CommitLoadContext < BaseContext
commit = project.repository.commit(params[:id])
if commit
commit = CommitDecorator.decorate(commit)
line_notes = project.notes.for_commit_id(commit.id).inline
result[:commit] = commit

View File

@ -3,8 +3,6 @@ module Notes
def execute
note = project.notes.new(params[:note])
note.author = current_user
note.notify = params[:notify].present?
note.notify_author = params[:notify_author].present?
note.save
note
end

View File

@ -0,0 +1,27 @@
module Projects
class TransferContext < BaseContext
def execute(role = :default)
namespace_id = params[:project].delete(:namespace_id)
allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin
if allowed_transfer && namespace_id.present?
if namespace_id == Namespace.global_id
if project.namespace.present?
# Transfer to global namespace from anyone
project.transfer(nil)
end
elsif namespace_id.to_i != project.namespace_id
# Transfer to someone namespace
namespace = Namespace.find(namespace_id)
project.transfer(namespace)
end
end
rescue ProjectTransferService::TransferError => ex
project.reload
project.errors.add(:namespace_id, ex.message)
false
end
end
end

View File

@ -1,24 +1,8 @@
module Projects
class UpdateContext < BaseContext
def execute(role = :default)
namespace_id = params[:project].delete(:namespace_id)
params[:project].delete(:namespace_id)
params[:project].delete(:public) unless can?(current_user, :change_public_mode, project)
allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin
if allowed_transfer && namespace_id.present?
if namespace_id == Namespace.global_id
if project.namespace.present?
# Transfer to global namespace from anyone
project.transfer(nil)
end
elsif namespace_id.to_i != project.namespace_id
# Transfer to someone namespace
namespace = Namespace.find(namespace_id)
project.transfer(namespace)
end
end
project.update_attributes(params[:project], as: role)
end
end

View File

@ -19,34 +19,6 @@ class Admin::ProjectsController < Admin::ApplicationController
@users = @users.all
end
def edit
end
def team_update
@project.team.add_users_ids(params[:user_ids], params[:project_access])
redirect_to [:admin, @project], notice: 'Project was successfully updated.'
end
def update
project.creator = current_user unless project.creator
status = ::Projects::UpdateContext.new(project, current_user, params).execute(:admin)
if status
redirect_to [:admin, @project], notice: 'Project was successfully updated.'
else
render action: "edit"
end
end
def destroy
@project.team.truncate
@project.destroy
redirect_to admin_projects_path, notice: 'Project was successfully deleted.'
end
protected
def project

View File

@ -84,6 +84,8 @@ class Admin::UsersController < Admin::ApplicationController
format.html { redirect_to [:admin, admin_user], notice: 'User was successfully updated.' }
format.json { head :ok }
else
# restore username to keep form action url.
admin_user.username = params[:id]
format.html { render action: "edit" }
format.json { render json: admin_user.errors, status: :unprocessable_entity }
end

View File

@ -7,10 +7,7 @@ class BlameController < ProjectResourceController
before_filter :authorize_code_access!
before_filter :require_non_empty_project
before_filter :assign_ref_vars
def show
@repo = @project.repo
@blame = Grit::Blob.blame(@repo, @commit.id, @path)
@blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path)
end
end

View File

@ -7,8 +7,6 @@ class BlobController < ProjectResourceController
before_filter :authorize_code_access!
before_filter :require_non_empty_project
before_filter :assign_ref_vars
def show
if @tree.is_blob?
send_data(

View File

@ -13,7 +13,6 @@ class CommitsController < ProjectResourceController
@limit, @offset = (params[:limit] || 40), (params[:offset] || 0)
@commits = @repo.commits(@ref, @path, @limit, @offset)
@commits = CommitDecorator.decorate_collection(@commits)
respond_to do |format|
format.html # index.html.erb

View File

@ -8,15 +8,13 @@ class CompareController < ProjectResourceController
end
def show
result = Commit.compare(project, params[:from], params[:to])
compare = Gitlab::Git::Compare.new(project.repository, params[:from], params[:to])
@commits = result[:commits]
@commit = result[:commit]
@diffs = result[:diffs]
@refs_are_same = result[:same]
@commits = compare.commits
@commit = compare.commit
@diffs = compare.diffs
@refs_are_same = compare.same
@line_notes = []
@commits = CommitDecorator.decorate_collection(@commits)
end
def create

View File

@ -0,0 +1,47 @@
# Controller for edit a repository's file
class EditTreeController < ProjectResourceController
include ExtractsPath
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :require_non_empty_project
before_filter :edit_requirements, only: [:edit, :update]
def show
@last_commit = @project.repository.last_commit_for(@ref, @path).sha
end
def update
edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, @project, @ref, @path)
updated_successfully = edit_file_action.commit!(
params[:content],
params[:commit_message],
params[:last_commit]
)
if updated_successfully
redirect_to project_tree_path(@project, @id), notice: "Your changes have been successfully commited"
else
flash[:notice] = "Your changes could not be commited, because the file has been changed"
render :edit
end
end
private
def edit_requirements
unless @tree.is_blob? && @tree.text?
redirect_to project_tree_path(@project, @id), notice: "You can only edit text files"
end
allowed = if project.protected_branch? @ref
can?(current_user, :push_code_to_protected_branches, project)
else
can?(current_user, :push_code, project)
end
return access_denied! unless allowed
end
end

View File

@ -94,12 +94,10 @@ class MergeRequestsController < ProjectResourceController
def branch_from
@commit = @repository.commit(params[:ref])
@commit = CommitDecorator.decorate(@commit)
end
def branch_to
@commit = @repository.commit(params[:ref])
@commit = CommitDecorator.decorate(@commit)
end
def ci_status
@ -129,11 +127,11 @@ class MergeRequestsController < ProjectResourceController
def validates_merge_request
# Show git not found page if target branch doesn't exist
return invalid_mr unless @project.repo.heads.map(&:name).include?(@merge_request.target_branch)
return invalid_mr unless @project.repository.branch_names.include?(@merge_request.target_branch)
# Show git not found page if source branch doesn't exist
# and there is no saved commits between source & target branch
return invalid_mr if !@project.repo.heads.map(&:name).include?(@merge_request.source_branch) && @merge_request.commits.blank?
return invalid_mr if !@project.repository.branch_names.include?(@merge_request.source_branch) && @merge_request.commits.blank?
end
def define_show_vars
@ -143,7 +141,6 @@ class MergeRequestsController < ProjectResourceController
# Get commits from repository
# or from cache if already merged
@commits = @merge_request.commits
@commits = CommitDecorator.decorate_collection(@commits)
@allowed_to_merge = allowed_to_merge?
@show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge

View File

@ -0,0 +1,13 @@
class NotificationsController < ApplicationController
layout 'profile'
def show
@notification = current_user.notification
@projects = current_user.authorized_projects
end
def update
current_user.notification_level = params[:notification_level]
@saved = current_user.save
end
end

View File

@ -4,7 +4,7 @@ class ProjectsController < ProjectResourceController
# Authorize
before_filter :authorize_read_project!, except: [:index, :new, :create]
before_filter :authorize_admin_project!, only: [:edit, :update, :destroy]
before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer]
before_filter :require_non_empty_project, only: [:blob, :tree, :graph]
layout 'application', only: [:new, :create]
@ -45,10 +45,10 @@ class ProjectsController < ProjectResourceController
format.js
end
end
end
rescue Project::TransferError => ex
@error = ex
render :update_failed
def transfer
::Projects::TransferContext.new(project, current_user, params).execute
end
def show
@ -57,11 +57,11 @@ class ProjectsController < ProjectResourceController
respond_to do |format|
format.html do
if @project.repository && !@project.repository.empty?
if @project.empty_repo?
render "projects/empty"
else
@last_push = current_user.recent_push(@project.id)
render :show
else
render "projects/empty"
end
end
format.js

View File

@ -34,7 +34,6 @@ class RefsController < ProjectResourceController
@logs = contents.map do |content|
file = params[:path] ? File.join(params[:path], content.name) : content.name
last_commit = @repo.commits(@commit.id, file, 1).last
last_commit = CommitDecorator.decorate(last_commit)
{
file_name: content.name,
commit: last_commit
@ -49,9 +48,7 @@ class RefsController < ProjectResourceController
@repo = project.repository
@commit = @repo.commit(@ref)
@commit = CommitDecorator.decorate(@commit)
@tree = Tree.new(@commit.tree, @ref, params[:path])
@tree = TreeDecorator.new(@tree)
@hex_path = Digest::SHA1.hexdigest(params[:path] || "")
if params[:path]

View File

@ -7,9 +7,6 @@ class TreeController < ProjectResourceController
before_filter :authorize_code_access!
before_filter :require_non_empty_project
before_filter :assign_ref_vars
before_filter :edit_requirements, only: [:edit, :update]
def show
@hex_path = Digest::SHA1.hexdigest(@path)
@logs_path = logs_file_project_ref_path(@project, @ref, @path)
@ -20,40 +17,4 @@ class TreeController < ProjectResourceController
format.js { no_cache_headers }
end
end
def edit
@last_commit = @project.repository.last_commit_for(@ref, @path).sha
end
def update
edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, @project, @ref, @path)
updated_successfully = edit_file_action.commit!(
params[:content],
params[:commit_message],
params[:last_commit]
)
if updated_successfully
redirect_to project_tree_path(@project, @id), notice: "Your changes have been successfully commited"
else
flash[:notice] = "Your changes could not be commited, because the file has been changed"
render :edit
end
end
private
def edit_requirements
unless @tree.is_blob? && @tree.text?
redirect_to project_tree_path(@project, @id), notice: "You can only edit text files"
end
allowed = if project.protected_branch? @ref
can?(current_user, :push_code_to_protected_branches, project)
else
can?(current_user, :push_code, project)
end
return access_denied! unless allowed
end
end

View File

@ -1,93 +0,0 @@
class CommitDecorator < ApplicationDecorator
decorates :commit
# Returns a string describing the commit for use in a link title
#
# Example
#
# "Commit: Alex Denisov - Project git clone panel"
def link_title
"Commit: #{author_name} - #{title}"
end
# Returns the commits title.
#
# Usually, the commit title is the first line of the commit message.
# In case this first line is longer than 80 characters, it is cut off
# after 70 characters and ellipses (`&hellp;`) are appended.
def title
title = safe_message
return no_commit_message if title.blank?
title_end = title.index(/\n/)
if (!title_end && title.length > 80) || (title_end && title_end > 80)
title[0..69] << "&hellip;".html_safe
else
title.split(/\n/, 2).first
end
end
# Returns the commits description
#
# cut off, ellipses (`&hellp;`) are prepended to the commit message.
def description
description = safe_message
title_end = description.index(/\n/)
if (!title_end && description.length > 80) || (title_end && title_end > 80)
"&hellip;".html_safe << description[70..-1]
else
description.split(/\n/, 2)[1].try(:chomp)
end
end
# Returns a link to the commit author. If the author has a matching user and
# is a member of the current @project it will link to the team member page.
# Otherwise it will link to the author email as specified in the commit.
#
# options:
# avatar: true will prepend the avatar image
# size: size of the avatar image in px
def author_link(options = {})
person_link(options.merge source: :author)
end
# Just like #author_link but for the committer.
def committer_link(options = {})
person_link(options.merge source: :committer)
end
protected
def no_commit_message
"--no commit message"
end
# Private: Returns a link to a person. If the person has a matching user and
# is a member of the current @project it will link to the team member page.
# Otherwise it will link to the person email as specified in the commit.
#
# options:
# source: one of :author or :committer
# avatar: true will prepend the avatar image
# size: size of the avatar image in px
def person_link(options = {})
source_name = send "#{options[:source]}_name".to_sym
source_email = send "#{options[:source]}_email".to_sym
text = if options[:avatar]
avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: ""
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
else
source_name
end
user = User.where('name like ? or email like ?', source_name, source_email).first
if user.nil?
h.mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link")
else
h.link_to(text.html_safe, h.user_path(user), class: "commit-#{options[:source]}-link")
end
end
end

View File

@ -1,33 +0,0 @@
class TreeDecorator < ApplicationDecorator
decorates :tree
def breadcrumbs(max_links = 2)
if path
part_path = ""
parts = path.split("\/")
yield('..', nil) if parts.count > max_links
parts.each do |part|
part_path = File.join(part_path, part) unless part_path.empty?
part_path = part if part_path.empty?
next unless parts.last(2).include?(part) if parts.count > max_links
yield(part, h.tree_join(ref, part_path))
end
end
end
def up_dir?
path.present?
end
def up_dir_path
file = File.join(path, "..")
h.tree_join(ref, file)
end
def readme
@readme ||= contents.find { |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }
end
end

View File

@ -96,7 +96,7 @@ module ApplicationHelper
]
project_nav = []
if @project && @project.repository && @project.repository.root_ref
if @project && @project.repository.exists? && @project.repository.root_ref
project_nav = [
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Issues", url: project_issues_path(@project) },
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Commits", url: project_commits_path(@project, @ref || @project.repository.root_ref) },

View File

@ -1,4 +1,20 @@
module CommitsHelper
# Returns a link to the commit author. If the author has a matching user and
# is a member of the current @project it will link to the team member page.
# Otherwise it will link to the author email as specified in the commit.
#
# options:
# avatar: true will prepend the avatar image
# size: size of the avatar image in px
def commit_author_link(commit, options = {})
commit_person_link(commit, options.merge(source: :author))
end
# Just like #author_link but for the committer.
def commit_committer_link(commit, options = {})
commit_person_link(commit, options.merge(source: :committer))
end
def identification_type(line)
if line[0] == "+"
"new"
@ -93,9 +109,7 @@ module CommitsHelper
end
def commit_to_html commit
if commit.model
escape_javascript(render 'commits/commit', commit: commit)
end
escape_javascript(render 'commits/commit', commit: commit)
end
def diff_line_content(line)
@ -105,4 +119,58 @@ module CommitsHelper
line
end
end
# Breadcrumb links for a Project and, if applicable, a tree path
def commits_breadcrumbs
return unless @project && @ref
# Add the root project link and the arrow icon
crumbs = content_tag(:li) do
content_tag(:span, nil, class: 'arrow') +
link_to(@project.name, project_commits_path(@project, @ref))
end
if @path
parts = @path.split('/')
parts.each_with_index do |part, i|
crumbs += content_tag(:span, '/', class: 'divider')
crumbs += content_tag(:li) do
# The text is just the individual part, but the link needs all the parts before it
link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
end
end
end
crumbs.html_safe
end
protected
# Private: Returns a link to a person. If the person has a matching user and
# is a member of the current @project it will link to the team member page.
# Otherwise it will link to the person email as specified in the commit.
#
# options:
# source: one of :author or :committer
# avatar: true will prepend the avatar image
# size: size of the avatar image in px
def commit_person_link(commit, options = {})
source_name = commit.send "#{options[:source]}_name".to_sym
source_email = commit.send "#{options[:source]}_email".to_sym
text = if options[:avatar]
avatar = image_tag(gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
else
source_name
end
user = User.where('name like ? or email like ?', source_name, source_email).first
if user.nil?
mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link")
else
link_to(text.html_safe, user_path(user), class: "commit-#{options[:source]}-link")
end
end
end

View File

@ -1,6 +1,13 @@
module GraphHelper
def join_with_space(ary)
ary.collect{|r|r.name}.join(" ") unless ary.nil?
def get_refs(commit)
refs = ""
refs += commit.refs.collect{|r|r.name}.join(" ") if commit.refs
# append note count
notes = @project.notes.for_commit_id(commit.id)
refs += "[#{notes.count}]" if notes.any?
refs
end
def parents_zip_spaces(parents, parent_spaces)

View File

@ -48,19 +48,31 @@ module IssuesHelper
if @project.used_default_issues_tracker?
project_issues_filter_path(@project)
else
url = Settings[:issues_tracker][@project.issues_tracker]["project_url"]
url = Gitlab.config.issues_tracker[@project.issues_tracker]["project_url"]
url.gsub(':project_id', @project.id.to_s)
.gsub(':issues_tracker_id', @project.issues_tracker_id.to_s)
end
end
def url_for_new_issue
return "" if @project.nil?
if @project.used_default_issues_tracker?
url = new_project_issue_path project_id: @project
else
url = Gitlab.config.issues_tracker[@project.issues_tracker]["new_issue_url"]
url.gsub(':project_id', @project.id.to_s)
.gsub(':issues_tracker_id', @project.issues_tracker_id.to_s)
end
end
def url_for_issue(issue_id)
return "" if @project.nil?
if @project.used_default_issues_tracker?
url = project_issue_url project_id: @project, id: issue_id
else
url = Settings[:issues_tracker][@project.issues_tracker]["issues_url"]
url = Gitlab.config.issues_tracker[@project.issues_tracker]["issues_url"]
url.gsub(':id', issue_id.to_s)
.gsub(':project_id', @project.id.to_s)
.gsub(':issues_tracker_id', @project.issues_tracker_id.to_s)

View File

@ -0,0 +1,2 @@
module NotificationsHelper
end

View File

@ -70,28 +70,26 @@ module TreeHelper
end
end
# Breadcrumb links for a Project and, if applicable, a tree path
def breadcrumbs
return unless @project && @ref
def tree_breadcrumbs(tree, max_links = 2)
if tree.path
part_path = ""
parts = tree.path.split("\/")
# Add the root project link and the arrow icon
crumbs = content_tag(:li) do
content_tag(:span, nil, class: 'arrow') +
link_to(@project.name, project_commits_path(@project, @ref))
end
yield('..', nil) if parts.count > max_links
if @path
parts = @path.split('/')
parts.each do |part|
part_path = File.join(part_path, part) unless part_path.empty?
part_path = part if part_path.empty?
parts.each_with_index do |part, i|
crumbs += content_tag(:span, '/', class: 'divider')
crumbs += content_tag(:li) do
# The text is just the individual part, but the link needs all the parts before it
link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
end
next unless parts.last(2).include?(part) if parts.count > max_links
yield(part, tree_join(tree.ref, part_path))
end
end
crumbs.html_safe
end
def up_dir_path tree
file = File.join(tree.path, "..")
tree_join(tree.ref, file)
end
end

View File

@ -1,9 +1,9 @@
module Emails
module Issues
def new_issue_email(issue_id)
def new_issue_email(recipient_id, issue_id)
@issue = Issue.find(issue_id)
@project = @issue.project
mail(to: @issue.assignee_email, subject: subject("new issue ##{@issue.id}", @issue.title))
mail(to: recipient(recipient_id), subject: subject("new issue ##{@issue.id}", @issue.title))
end
def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id)
@ -13,6 +13,14 @@ module Emails
mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.id}", @issue.title))
end
def closed_issue_email(recipient_id, issue_id, updated_by_user_id)
@issue = Issue.find issue_id
@project = @issue.project
@updated_by = User.find updated_by_user_id
mail(to: recipient(recipient_id),
subject: subject("Closed issue ##{@issue.id}", @issue.title))
end
def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id)
@issue = Issue.find issue_id
@issue_status = status

View File

@ -1,9 +1,9 @@
module Emails
module MergeRequests
def new_merge_request_email(merge_request_id)
def new_merge_request_email(recipient_id, merge_request_id)
@merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project
mail(to: @merge_request.assignee_email, subject: subject("new merge request !#{@merge_request.id}", @merge_request.title))
mail(to: recipient(recipient_id), subject: subject("new merge request !#{@merge_request.id}", @merge_request.title))
end
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
@ -12,5 +12,18 @@ module Emails
@project = @merge_request.project
mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.id}", @merge_request.title))
end
def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
@merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project
@updated_by = User.find updated_by_user_id
mail(to: recipient(recipient_id), subject: subject("Closed merge request !#{@merge_request.id}", @merge_request.title))
end
def merged_merge_request_email(recipient_id, merge_request_id)
@merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project
mail(to: recipient(recipient_id), subject: subject("Accepted merge request !#{@merge_request.id}", @merge_request.title))
end
end
end

View File

@ -3,7 +3,6 @@ module Emails
def note_commit_email(recipient_id, note_id)
@note = Note.find(note_id)
@commit = @note.noteable
@commit = CommitDecorator.decorate(@commit)
@project = @note.project
mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title))
end

View File

@ -41,7 +41,7 @@ class Ability
rules << project_guest_rules
end
if project.owner == user
if project.owner == user || user.admin?
rules << project_admin_rules
end

View File

@ -8,168 +8,70 @@ class Commit
#
DIFF_SAFE_SIZE = 100
attr_accessor :commit, :head, :refs
delegate :message, :authored_date, :committed_date, :parents, :sha,
:date, :committer, :author, :diffs, :tree, :id, :stats,
:to_patch, to: :commit
class << self
def find_or_first(repo, commit_id = nil, root_ref)
commit = if commit_id
repo.commit(commit_id)
else
repo.commits(root_ref).first
end
Commit.new(commit) if commit
end
def fresh_commits(repo, n = 10)
commits = repo.heads.map do |h|
repo.commits(h.name, n).map { |c| Commit.new(c, h) }
end.flatten.uniq { |c| c.id }
commits.sort! do |x, y|
y.committed_date <=> x.committed_date
end
commits[0...n]
end
def commits_with_refs(repo, n = 20)
commits = repo.branches.map { |ref| Commit.new(ref.commit, ref) }
commits.sort! do |x, y|
y.committed_date <=> x.committed_date
end
commits[0..n]
end
def commits_since(repo, date)
commits = repo.heads.map do |h|
repo.log(h.name, nil, since: date).each { |c| Commit.new(c, h) }
end.flatten.uniq { |c| c.id }
commits.sort! do |x, y|
y.committed_date <=> x.committed_date
end
commits
end
def commits(repo, ref, path = nil, limit = nil, offset = nil)
if path
repo.log(ref, path, max_count: limit, skip: offset)
elsif limit && offset
repo.commits(ref, limit, offset)
else
repo.commits(ref)
end.map{ |c| Commit.new(c) }
end
def commits_between(repo, from, to)
repo.commits_between(from, to).map { |c| Commit.new(c) }
end
def compare(project, from, to)
result = {
commits: [],
diffs: [],
commit: nil,
same: false
}
return result unless from && to
first = project.repository.commit(to.try(:strip))
last = project.repository.commit(from.try(:strip))
if first && last
result[:same] = (first.id == last.id)
result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Commit.new(c)}
# Dont load diff for 100+ commits
result[:diffs] = if result[:commits].size > 100
[]
else
project.repo.diff(last.id, first.id) rescue []
end
result[:commit] = Commit.new(first)
end
result
end
def self.decorate(commits)
commits.map { |c| self.new(c) }
end
def initialize(raw_commit, head = nil)
attr_accessor :raw
def initialize(raw_commit)
raise "Nil as raw commit passed" unless raw_commit
@commit = raw_commit
@head = head
@raw = raw_commit
end
def short_id(length = 10)
id.to_s[0..length]
def id
@raw.id
end
def safe_message
@safe_message ||= message
end
def created_at
committed_date
end
def author_email
author.email
end
def author_name
author.name
end
# Was this commit committed by a different person than the original author?
def different_committer?
author_name != committer_name || author_email != committer_email
end
def committer_name
committer.name
end
def committer_email
committer.email
end
def prev_commit
@prev_commit ||= if parents.present?
Commit.new(parents.first)
else
nil
end
end
def prev_commit_id
prev_commit.try :id
end
# Shows the diff between the commit's parent and the commit.
# Returns a string describing the commit for use in a link title
#
# Cuts out the header and stats from #to_patch and returns only the diff.
def to_diff
# see Grit::Commit#show
patch = to_patch
# Example
#
# "Commit: Alex Denisov - Project git clone panel"
def link_title
"Commit: #{author_name} - #{title}"
end
# discard lines before the diff
lines = patch.split("\n")
while !lines.first.start_with?("diff --git") do
lines.shift
# Returns the commits title.
#
# Usually, the commit title is the first line of the commit message.
# In case this first line is longer than 80 characters, it is cut off
# after 70 characters and ellipses (`&hellp;`) are appended.
def title
title = safe_message
return no_commit_message if title.blank?
title_end = title.index(/\n/)
if (!title_end && title.length > 80) || (title_end && title_end > 80)
title[0..69] << "&hellip;".html_safe
else
title.split(/\n/, 2).first
end
lines.pop if lines.last =~ /^[\d.]+$/ # Git version
lines.pop if lines.last == "-- " # end of diff
lines.join("\n")
end
# Returns the commits description
#
# cut off, ellipses (`&hellp;`) are prepended to the commit message.
def description
description = safe_message
title_end = description.index(/\n/)
if (!title_end && description.length > 80) || (title_end && title_end > 80)
"&hellip;".html_safe << description[70..-1]
else
description.split(/\n/, 2)[1].try(:chomp)
end
end
def method_missing(m, *args, &block)
@raw.send(m, *args, &block)
end
def respond_to?(method)
return true if @raw.respond_to?(method)
super
end
end

View File

@ -50,7 +50,7 @@ class GollumWiki
# Returns the last 30 Commit objects across the entire
# repository.
def recent_history
Commit.fresh_commits(wiki.repo, 30)
Gitlab::Git::Commit.fresh_commits(wiki.repo, 30)
end
# Finds a page within the repository based on a tile
@ -90,13 +90,17 @@ class GollumWiki
private
def create_repo!
if gitlab_shell.add_repository(path_with_namespace)
if init_repo(path_with_namespace)
Gollum::Wiki.new(path_to_repo)
else
raise CouldNotCreateWikiError
end
end
def init_repo(path_with_namespace)
gitlab_shell.add_repository(path_with_namespace)
end
def commit_details(action, message = nil, title = nil)
commit_message = message || default_message(action, title)
@ -114,5 +118,4 @@ class GollumWiki
def path_to_repo
@path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git")
end
end

View File

@ -152,7 +152,17 @@ class MergeRequest < ActiveRecord::Base
end
def commits
st_commits || []
if st_commits.present?
# check if merge request commits are valid
if st_commits.first.respond_to?(:short_id)
st_commits
else
# if commits are invalid - simply reload it from repo
reloaded_commits
end
else
[]
end
end
def probably_merged?
@ -162,6 +172,12 @@ class MergeRequest < ActiveRecord::Base
def reloaded_commits
if opened? && unmerged_commits.any?
# we need to reset st_commits field first
# in order to prevent internal rails comparison
self.st_commits = []
save
# Then we can safely write unmerged commits
self.st_commits = unmerged_commits
save
end
@ -169,9 +185,8 @@ class MergeRequest < ActiveRecord::Base
end
def unmerged_commits
self.project.repo.
self.project.repository.
commits_between(self.target_branch, self.source_branch).
map {|c| Commit.new(c)}.
sort_by(&:created_at).
reverse
end

View File

@ -13,6 +13,8 @@
#
class Namespace < ActiveRecord::Base
include Gitlab::ShellAdapter
attr_accessible :name, :description, :path
has_many :projects, dependent: :destroy
@ -31,7 +33,7 @@ class Namespace < ActiveRecord::Base
delegate :name, to: :owner, allow_nil: true, prefix: true
after_create :ensure_dir_exist
after_update :move_dir
after_update :move_dir, if: :path_changed?
after_destroy :rm_dir
scope :root, -> { where('type IS NULL') }
@ -53,46 +55,32 @@ class Namespace < ActiveRecord::Base
end
def ensure_dir_exist
unless dir_exists?
FileUtils.mkdir( namespace_full_path, mode: 0770 )
end
end
def dir_exists?
File.exists?(namespace_full_path)
end
def namespace_full_path
@namespace_full_path ||= File.join(Gitlab.config.gitlab_shell.repos_path, path)
end
def move_dir
if path_changed?
old_path = File.join(Gitlab.config.gitlab_shell.repos_path, path_was)
new_path = File.join(Gitlab.config.gitlab_shell.repos_path, path)
if File.exists?(new_path)
raise "Already exists"
end
begin
# Remove satellite when moving repo
if path_was.present?
satellites_path = File.join(Gitlab.config.satellites.path, path_was)
FileUtils.rm_r( satellites_path, force: true )
end
FileUtils.mv( old_path, new_path )
send_update_instructions
rescue Exception => e
raise "Namespace move error #{old_path} #{new_path}"
end
end
gitlab_shell.add_namespace(path)
end
def rm_dir
dir_path = File.join(Gitlab.config.gitlab_shell.repos_path, path)
FileUtils.rm_r( dir_path, force: true )
gitlab_shell.rm_namespace(path)
end
def move_dir
if gitlab_shell.mv_namespace(path_was, path)
# If repositories moved successfully we need to remove old satellites
# and send update instructions to users.
# However we cannot allow rollback since we moved namespace dir
# So we basically we mute exceptions in next actions
begin
gitlab_shell.rm_satellites(path_was)
send_update_instructions
rescue
# Returning false does not rolback after_* transaction but gives
# us information about failing some of tasks
false
end
else
# if we cannot move namespace directory we should rollback
# db changes in order to prevent out of sync between db and fs
raise Exception.new('namespace directory cannot be moved')
end
end
def send_update_instructions

View File

@ -8,7 +8,7 @@ module Network
attr_accessor :time, :spaces, :parent_spaces
def initialize(raw_commit, refs)
@commit = ::Commit.new(raw_commit)
@commit = Gitlab::Git::Commit.new(raw_commit)
@time = -1
@spaces = []
@parent_spaces = []

View File

@ -40,15 +40,12 @@ module Network
def index_commits
days = []
@map = {}
@reserved = {}
@commits.reverse.each_with_index do |c,i|
@commits.each_with_index do |c,i|
c.time = i
days[i] = c.committed_date
@map[c.id] = c
end
@reserved = {}
days.each_index do |i|
@reserved[i] = []
end
@ -135,11 +132,7 @@ module Network
spaces = []
commit.parents(@map).each do |parent|
range = if commit.time < parent.time then
commit.time..parent.time
else
parent.time..commit.time
end
range = commit.time..parent.time
space = if commit.space >= parent.space then
find_free_parent_space(range, parent.space, -1, commit.space)
@ -166,7 +159,7 @@ module Network
range.each do |i|
if i != range.first &&
i != range.last &&
@commits[reversed_index(i)].spaces.include?(overlap_space) then
@commits[i].spaces.include?(overlap_space) then
return true;
end
@ -184,7 +177,7 @@ module Network
return
end
time_range = leaves.last.time..leaves.first.time
time_range = leaves.first.time..leaves.last.time
space_base = get_space_base(leaves)
space = find_free_space(time_range, 2, space_base)
leaves.each do |l|
@ -198,17 +191,17 @@ module Network
end
# and mark it as reserved
min_time = leaves.last.time
leaves.last.parents(@map).each do |parent|
if parent.time < min_time
min_time = parent.time
end
if parent_time.nil?
min_time = leaves.first.time
else
min_time = parent_time + 1
end
if parent_time.nil?
max_time = leaves.first.time
else
max_time = parent_time - 1
max_time = leaves.last.time
leaves.last.parents(@map).each do |parent|
if max_time < parent.time
max_time = parent.time
end
end
mark_reserved(min_time..max_time, space)
@ -289,9 +282,5 @@ module Network
end
refs_cache
end
def reversed_index(index)
-index - 1
end
end
end

View File

@ -22,9 +22,6 @@ class Note < ActiveRecord::Base
attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
:attachment, :line_code, :commit_id
attr_accessor :notify
attr_accessor :notify_author
belongs_to :project
belongs_to :noteable, polymorphic: true
belongs_to :author, class_name: "User"
@ -143,14 +140,6 @@ class Note < ActiveRecord::Base
nil
end
def notify
@notify ||= false
end
def notify_author
@notify_author ||= false
end
# Returns true if this is an upvote note,
# otherwise false is returned
def upvote?

View File

@ -0,0 +1,30 @@
class Notification
#
# Notification levels
#
N_DISABLED = 0
N_PARTICIPATING = 1
N_WATCH = 2
attr_accessor :user
def self.notification_levels
[N_DISABLED, N_PARTICIPATING, N_WATCH]
end
def initialize(user)
@user = user
end
def disabled?
user.notification_level == N_DISABLED
end
def participating?
user.notification_level == N_PARTICIPATING
end
def watch?
user.notification_level == N_WATCH
end
end

View File

@ -18,16 +18,15 @@
# public :boolean default(FALSE), not null
# issues_tracker :string(255) default("gitlab"), not null
# issues_tracker_id :string(255)
# snippets_enabled :boolean default(TRUE), not null
#
require "grit"
class Project < ActiveRecord::Base
include Gitolited
include Gitlab::ShellAdapter
extend Enumerize
class TransferError < StandardError; end
attr_accessible :name, :path, :description, :default_branch, :issues_tracker,
:issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id,
:wiki_enabled, :public, :import_url, as: [:default, :admin]
@ -142,13 +141,7 @@ class Project < ActiveRecord::Base
end
def repository
if path
@repository ||= Repository.new(path_with_namespace, default_branch)
else
nil
end
rescue Grit::NoSuchPathError
nil
@repository ||= Repository.new(path_with_namespace, default_branch)
end
def saved?
@ -333,14 +326,14 @@ class Project < ActiveRecord::Base
end
def valid_repo?
repo
repository.exists?
rescue
errors.add(:path, "Invalid repository path")
false
end
def empty_repo?
!repository || repository.empty?
!repository.exists? || repository.empty?
end
def ensure_satellite_exists
@ -364,18 +357,25 @@ class Project < ActiveRecord::Base
end
def repo_exists?
@repo_exists ||= (repository && repository.branches.present?)
@repo_exists ||= repository.exists?
rescue
@repo_exists = false
end
def open_branches
if protected_branches.empty?
self.repo.heads
else
pnames = protected_branches.map(&:name)
self.repo.heads.reject { |h| pnames.include?(h.name) }
end.sort_by(&:name)
all_branches = repository.branches
if protected_branches.present?
all_branches.reject! do |branch|
protected_branches_names.include?(branch.name)
end
end
all_branches
end
def protected_branches_names
@protected_branches_names ||= protected_branches.map(&:name)
end
def root_ref?(branch)
@ -397,6 +397,6 @@ class Project < ActiveRecord::Base
# Check if current branch name is marked as protected in the system
def protected_branch? branch_name
protected_branches.map(&:name).include?(branch_name)
protected_branches_names.include?(branch_name)
end
end

View File

@ -10,7 +10,7 @@
#
class ProtectedBranch < ActiveRecord::Base
include Gitolited
include Gitlab::ShellAdapter
attr_accessible :name

View File

@ -1,169 +1,45 @@
class Repository
include Gitlab::Popen
attr_accessor :raw_repository
# Repository directory name with namespace direcotry
# Examples:
# gitlab/gitolite
# diaspora
#
attr_accessor :path_with_namespace
# Grit repo object
attr_accessor :repo
# Default branch in the repository
attr_accessor :root_ref
def initialize(path_with_namespace, root_ref = 'master')
@root_ref = root_ref || "master"
@path_with_namespace = path_with_namespace
# Init grit repo object
repo
def initialize(path_with_namespace, default_branch)
@raw_repository = Gitlab::Git::Repository.new(path_with_namespace, default_branch)
rescue Gitlab::Git::Repository::NoRepository
nil
end
def raw
repo
end
def path_to_repo
@path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git")
end
def repo
@repo ||= Grit::Repo.new(path_to_repo)
end
def commit(commit_id = nil)
Commit.find_or_first(repo, commit_id, root_ref)
end
def fresh_commits(n = 10)
Commit.fresh_commits(repo, n)
end
def commits_with_refs(n = 20)
Commit.commits_with_refs(repo, n)
end
def commits_since(date)
Commit.commits_since(repo, date)
end
def commits(ref, path = nil, limit = nil, offset = nil)
Commit.commits(repo, ref, path, limit, offset)
end
def last_commit_for(ref, path = nil)
commits(ref, path, 1).first
end
def commits_between(from, to)
Commit.commits_between(repo, from, to)
end
# Returns an Array of branch names
def branch_names
repo.branches.collect(&:name).sort
end
# Returns an Array of Branches
def branches
repo.branches.sort_by(&:name)
end
# Returns an Array of tag names
def tag_names
repo.tags.collect(&:name).sort.reverse
end
# Returns an Array of Tags
def tags
repo.tags.sort_by(&:name).reverse
end
# Returns an Array of branch and tag names
def ref_names
[branch_names + tag_names].flatten
end
def heads
@heads ||= repo.heads
end
def tree(fcommit, path = nil)
fcommit = commit if fcommit == :head
tree = fcommit.tree
path ? (tree / path) : tree
end
def has_commits?
!!commit
rescue Grit::NoSuchPathError
false
def exists?
raw_repository
end
def empty?
!has_commits?
raw_repository.empty?
end
# Discovers the default branch based on the repository's available branches
#
# - If no branches are present, returns nil
# - If one branch is present, returns its name
# - If two or more branches are present, returns the one that has a name
# matching root_ref (default_branch or 'master' if default_branch is nil)
def discover_default_branch
if branch_names.length == 0
nil
elsif branch_names.length == 1
branch_names.first
else
branch_names.select { |v| v == root_ref }.first
end
def commit(id = nil)
commit = raw_repository.commit(id)
commit = Commit.new(commit) if commit
commit
end
# Archive Project to .tar.gz
#
# Already packed repo archives stored at
# app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
#
def archive_repo(ref)
ref = ref || self.root_ref
commit = self.commit(ref)
return nil unless commit
# Build file path
file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz"
storage_path = Rails.root.join("tmp", "repositories")
file_path = File.join(storage_path, self.path_with_namespace, file_name)
# Put files into a directory before archiving
prefix = File.basename(self.path_with_namespace) + "/"
# Create file if not exists
unless File.exists?(file_path)
FileUtils.mkdir_p File.dirname(file_path)
file = self.repo.archive_to_file(ref, prefix, file_path)
end
file_path
def commits(ref, path = nil, limit = nil, offset = nil)
commits = raw_repository.commits(ref, path, limit, offset)
commits = Commit.decorate(commits) if commits.present?
commits
end
# Return repo size in megabytes
# Cached in redis
def size
Rails.cache.fetch(cache_key(:size)) do
size = popen('du -s', path_to_repo).first.strip.to_i
(size.to_f / 1024).round(2)
end
def commits_between(target, source)
commits = raw_repository.commits_between(target, source)
commits = Commit.decorate(commits) if commits.present?
commits
end
def expire_cache
Rails.cache.delete(cache_key(:size))
def method_missing(m, *args, &block)
raw_repository.send(m, *args, &block)
end
def cache_key(type)
"#{type}:#{path_with_namespace}"
def respond_to?(method)
return true if raw_repository.respond_to?(method)
super
end
end

View File

@ -26,4 +26,12 @@ class Tree
def empty?
data.blank?
end
def up_dir?
path.present?
end
def readme
@readme ||= contents.find { |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }
end
end

View File

@ -33,6 +33,7 @@
# can_create_team :boolean default(TRUE), not null
# state :string(255)
# color_scheme_id :integer default(1), not null
# notification_level :integer default(1), not null
#
class User < ActiveRecord::Base
@ -46,6 +47,13 @@ class User < ActiveRecord::Base
attr_accessor :force_random_password
# Virtual attribute for authenticating by either username or email
attr_accessor :login
# Add login to attr_accessible
attr_accessible :login
#
# Relations
#
@ -101,6 +109,9 @@ class User < ActiveRecord::Base
format: { with: Gitlab::Regex.username_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
validates :notification_level,
inclusion: { in: Notification.notification_levels },
presence: true
validate :namespace_uniq, if: ->(user) { user.username_changed? }
@ -140,6 +151,16 @@ class User < ActiveRecord::Base
# Class methods
#
class << self
# Devise method overriden to allow sing in with email or username
def find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { value: login.downcase }]).first
else
where(conditions).first
end
end
def filter filter_name
case filter_name
when "admins"; self.admins
@ -191,6 +212,10 @@ class User < ActiveRecord::Base
username
end
def notification
@notification ||= Notification.new(self)
end
def generate_password
if self.force_random_password
self.password = self.password_confirmation = Devise.friendly_token.first(8)

View File

@ -11,7 +11,7 @@
#
class UsersProject < ActiveRecord::Base
include Gitolited
include Gitlab::ShellAdapter
GUEST = 10
REPORTER = 20
@ -38,7 +38,7 @@ class UsersProject < ActiveRecord::Base
scope :masters, -> { where(project_access: MASTER) }
scope :in_project, ->(project) { where(project_id: project.id) }
scope :in_projects, ->(projects) { where(project_id: project_ids) }
scope :in_projects, ->(projects) { where(project_id: projects.map { |p| p.id }) }
scope :with_user, ->(user) { where(user_id: user.id) }
class << self

View File

@ -79,14 +79,14 @@ class WikiPage
def version
return nil unless persisted?
@version ||= Commit.new(@page.version)
@version ||= Commit.new(Gitlab::Git::Commit.new(@page.version))
end
# Returns an array of Gitlab Commit instances.
def versions
return [] unless persisted?
@page.versions.map { |v| Commit.new(v) }
@page.versions.map { |v| Commit.new(Gitlab::Git::Commit.new(v)) }
end
# Returns the Date that this latest version was

View File

@ -1,4 +1,4 @@
class ActivityObserver < ActiveRecord::Observer
class ActivityObserver < BaseObserver
observe :issue, :merge_request, :note, :milestone
def after_create(record)

View File

@ -0,0 +1,9 @@
class BaseObserver < ActiveRecord::Observer
def notification
NotificationService.new
end
def log_info message
Gitlab::AppLogger.info message
end
end

View File

@ -1,42 +1,30 @@
class IssueObserver < ActiveRecord::Observer
class IssueObserver < BaseObserver
cattr_accessor :current_user
def after_create(issue)
if issue.assignee && issue.assignee != current_user
Notify.delay.new_issue_email(issue.id)
end
notification.new_issue(issue, current_user)
end
def after_close(issue, transition)
send_reassigned_email(issue) if issue.is_being_reassigned?
notification.close_issue(issue, current_user)
create_note(issue)
end
def after_reopen(issue, transition)
send_reassigned_email(issue) if issue.is_being_reassigned?
create_note(issue)
end
def after_update(issue)
send_reassigned_email(issue) if issue.is_being_reassigned?
if issue.is_being_reassigned?
notification.reassigned_issue(issue, current_user)
end
end
protected
# Create issue note with service comment like 'Status changed to closed'
def create_note(issue)
Note.create_status_change_note(issue, current_user, issue.state)
[issue.author, issue.assignee].compact.uniq.each do |recipient|
Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id)
end
end
def send_reassigned_email(issue)
recipient_ids = [issue.assignee_id, issue.assignee_id_was].keep_if {|id| id && id != current_user.id }
recipient_ids.each do |recipient_id|
Notify.delay.reassigned_issue_email(recipient_id, issue.id, issue.assignee_id_was)
end
end
end

View File

@ -1,6 +1,4 @@
class KeyObserver < ActiveRecord::Observer
include Gitolited
class KeyObserver < BaseObserver
def after_save(key)
GitlabShellWorker.perform_async(
:add_key,
@ -8,8 +6,7 @@ class KeyObserver < ActiveRecord::Observer
key.key
)
# Notify about ssh key being added
Notify.delay.new_ssh_key_email(key.id) if key.user
notification.new_key(key)
end
def after_destroy(key)

View File

@ -1,36 +1,25 @@
class MergeRequestObserver < ActiveRecord::Observer
class MergeRequestObserver < BaseObserver
cattr_accessor :current_user
def after_create(merge_request)
if merge_request.assignee && merge_request.assignee != current_user
Notify.delay.new_merge_request_email(merge_request.id)
end
notification.new_merge_request(merge_request, current_user)
end
def after_close(merge_request, transition)
send_reassigned_email(merge_request) if merge_request.is_being_reassigned?
Note.create_status_change_note(merge_request, current_user, merge_request.state)
notification.close_mr(merge_request, current_user)
end
def after_merge(merge_request, transition)
notification.merge_mr(merge_request)
end
def after_reopen(merge_request, transition)
send_reassigned_email(merge_request) if merge_request.is_being_reassigned?
Note.create_status_change_note(merge_request, current_user, merge_request.state)
end
def after_update(merge_request)
send_reassigned_email(merge_request) if merge_request.is_being_reassigned?
end
protected
def send_reassigned_email(merge_request)
recipients_ids = merge_request.assignee_id_was, merge_request.assignee_id
recipients_ids.delete current_user.id
recipients_ids.each do |recipient_id|
Notify.delay.reassigned_merge_request_email(recipient_id, merge_request.id, merge_request.assignee_id_was)
end
notification.reassigned_merge_request(merge_request, current_user) if merge_request.is_being_reassigned?
end
end

View File

@ -1,38 +1,5 @@
class NoteObserver < ActiveRecord::Observer
class NoteObserver < BaseObserver
def after_create(note)
send_notify_mails(note)
end
protected
def send_notify_mails(note)
if note.notify
notify_team(note)
elsif note.notify_author
# Notify only author of resource
if note.commit_author
Notify.delay.note_commit_email(note.commit_author.id, note.id)
end
else
# Otherwise ignore it
nil
end
end
# Notifies the whole team except the author of note
def notify_team(note)
# Note: wall posts are not "attached" to anything, so fall back to "Wall"
noteable_type = note.noteable_type.presence || "Wall"
notify_method = "note_#{noteable_type.underscore}_email".to_sym
if Notify.respond_to? notify_method
team_without_note_author(note).map do |u|
Notify.delay.send(notify_method, u.id, note.id)
end
end
end
def team_without_note_author(note)
note.project.users.reject { |u| u.id == note.author.id }
notification.new_note(note)
end
end

View File

@ -1,4 +1,4 @@
class ProjectObserver < ActiveRecord::Observer
class ProjectObserver < BaseObserver
def after_create(project)
GitlabShellWorker.perform_async(
:add_repository,
@ -27,10 +27,4 @@ class ProjectObserver < ActiveRecord::Observer
log_info("Project \"#{project.name}\" was removed")
end
protected
def log_info message
Gitlab::AppLogger.info message
end
end

View File

@ -1,4 +1,4 @@
class SystemHookObserver < ActiveRecord::Observer
class SystemHookObserver < BaseObserver
observe :user, :project, :users_project
def after_create(model)

View File

@ -1,9 +1,8 @@
class UserObserver < ActiveRecord::Observer
class UserObserver < BaseObserver
def after_create(user)
log_info("User \"#{user.name}\" (#{user.email}) was created")
# Dont email omniauth created users
Notify.delay.new_user_email(user.id, user.password) unless user.extern_uid?
notification.new_user(user)
end
def after_destroy user
@ -19,10 +18,4 @@ class UserObserver < ActiveRecord::Observer
end
end
end
protected
def log_info message
Gitlab::AppLogger.info message
end
end

View File

@ -1,7 +1,6 @@
class UsersProjectObserver < ActiveRecord::Observer
class UsersProjectObserver < BaseObserver
def after_commit(users_project)
return if users_project.destroyed?
Notify.delay.project_access_granted_email(users_project.id)
end
def after_create(users_project)
@ -10,6 +9,12 @@ class UsersProjectObserver < ActiveRecord::Observer
action: Event::JOINED,
author_id: users_project.user.id
)
notification.new_team_member(users_project)
end
def after_update(users_project)
notification.update_team_member(users_project)
end
def after_destroy(users_project)

View File

@ -0,0 +1,197 @@
# NotificationService class
#
# Used for notifing users with emails about different events
#
# Ex.
# NotificationService.new.new_issue(issue, current_user)
#
class NotificationService
# Always notify user about ssh key added
# only if ssh key is not deploy key
#
# This is security email so it will be sent
# even if user disabled notifications
def new_key(key)
if key.user
Notify.delay.new_ssh_key_email(key.id)
end
end
# When create an issue we should send next emails:
#
# * issue assignee if his notification level is not Disabled
# * project team members with notification level higher then Participating
#
def new_issue(issue, current_user)
new_resource_email(issue, 'new_issue_email')
end
# When we close an issue we should send next emails:
#
# * issue author if his notification level is not Disabled
# * issue assignee if his notification level is not Disabled
# * project team members with notification level higher then Participating
#
def close_issue(issue, current_user)
close_resource_email(issue, current_user, 'closed_issue_email')
end
# When we reassign an issue we should send next emails:
#
# * issue old assignee if his notification level is not Disabled
# * issue new assignee if his notification level is not Disabled
#
def reassigned_issue(issue, current_user)
reassign_resource_email(issue, current_user, 'reassigned_issue_email')
end
# When create a merge request we should send next emails:
#
# * mr assignee if his notification level is not Disabled
#
def new_merge_request(merge_request, current_user)
new_resource_email(merge_request, 'new_merge_request_email')
end
# When we reassign a merge_request we should send next emails:
#
# * merge_request old assignee if his notification level is not Disabled
# * merge_request assignee if his notification level is not Disabled
#
def reassigned_merge_request(merge_request, current_user)
reassign_resource_email(merge_request, current_user, 'reassigned_merge_request_email')
end
# When we close a merge request we should send next emails:
#
# * merge_request author if his notification level is not Disabled
# * merge_request assignee if his notification level is not Disabled
# * project team members with notification level higher then Participating
#
def close_mr(merge_request, current_user)
close_resource_email(merge_request, current_user, 'closed_merge_request_email')
end
# When we merge a merge request we should send next emails:
#
# * merge_request author if his notification level is not Disabled
# * merge_request assignee if his notification level is not Disabled
# * project team members with notification level higher then Participating
#
def merge_mr(merge_request)
recipients = reject_muted_users([merge_request.author, merge_request.assignee])
recipients = recipients.concat(project_watchers(merge_request.project)).uniq
recipients.each do |recipient|
Notify.delay.merged_merge_request_email(recipient.id, merge_request.id)
end
end
# Notify new user with email after creation
def new_user(user)
# Dont email omniauth created users
Notify.delay.new_user_email(user.id, user.password) unless user.extern_uid?
end
# Notify users on new note in system
#
# TODO: split on methods and refactor
#
def new_note(note)
# ignore wall messages
return true unless note.noteable_type.present?
opts = { noteable_type: note.noteable_type, project_id: note.project_id }
if note.commit_id.present?
opts.merge!(commit_id: note.commit_id)
recipients = [note.commit_author]
else
opts.merge!(noteable_id: note.noteable_id)
target = note.noteable
recipients = []
recipients << target.assignee if target.respond_to?(:assignee)
recipients << target.author if target.respond_to?(:author)
end
# Get users who left comment in thread
recipients = recipients.concat(User.where(id: Note.where(opts).pluck(:author_id)))
# Merge project watchers
recipients = recipients.concat(project_watchers(note.project)).compact.uniq
# Reject mutes users
recipients = reject_muted_users(recipients)
# Reject author
recipients.delete(note.author)
# build notify method like 'note_commit_email'
notify_method = "note_#{note.noteable_type.underscore}_email".to_sym
recipients.each do |recipient|
Notify.delay.send(notify_method, recipient.id, note.id)
end
end
def new_team_member(users_project)
Notify.delay.project_access_granted_email(users_project.id)
end
def update_team_member(users_project)
Notify.delay.project_access_granted_email(users_project.id)
end
protected
# Get project users with WATCH notification level
def project_watchers(project)
project.users.where(notification_level: Notification::N_WATCH)
end
# Remove users with disabled notifications from array
# Also remove duplications and nil recipients
def reject_muted_users(users)
users.compact.uniq.reject do |user|
user.notification.disabled?
end
end
def new_resource_email(target, method)
recipients = reject_muted_users([target.assignee])
recipients = recipients.concat(project_watchers(target.project)).uniq
recipients.delete(target.author)
recipients.each do |recipient|
Notify.delay.send(method, recipient.id, target.id)
end
end
def close_resource_email(target, current_user, method)
recipients = reject_muted_users([target.author, target.assignee])
recipients = recipients.concat(project_watchers(target.project)).uniq
recipients.delete(current_user)
recipients.each do |recipient|
Notify.delay.send(method, recipient.id, target.id, current_user.id)
end
end
def reassign_resource_email(target, current_user, method)
recipients = User.where(id: [target.assignee_id, target.assignee_id_was])
# Add watchers to email list
recipients = recipients.concat(project_watchers(target.project))
# reject users with disabled notifications
recipients = reject_muted_users(recipients)
# Reject me from recipients if I reassign an item
recipients.delete(current_user)
recipients.each do |recipient|
Notify.delay.send(method, recipient.id, target.id, target.assignee_id_was)
end
end
end

View File

@ -3,7 +3,9 @@
# Used for transfer project to another namespace
#
class ProjectTransferService
include Gitolited
include Gitlab::ShellAdapter
class TransferError < StandardError; end
attr_accessor :project
@ -19,14 +21,16 @@ class ProjectTransferService
project.namespace = new_namespace
project.save!
# Move main repository
unless gitlab_shell.mv_repository(old_path, new_path)
raise TransferError.new('Cannot move project')
end
# Move wiki repo also if present
gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki")
true
end
rescue => ex
raise Project::TransferError.new(ex.message)
end
end

View File

@ -1,86 +0,0 @@
= form_for [:admin, project] do |f|
-if project.errors.any?
.alert.alert-error
%ul
- project.errors.full_messages.each do |msg|
%li= msg
.clearfix.project_name_holder
= f.label :name do
Project name is
.input
= f.text_field :name, placeholder: "Example Project", class: "xxlarge"
- if project.repo_exists?
%fieldset.adv_settings
%legend Advanced settings:
.clearfix
= f.label :path do
Path
.input
= text_field_tag :ppath, @project.repository.path_to_repo, class: "xlarge", disabled: true
.clearfix
= f.label :default_branch, "Default Branch"
.input= f.select(:default_branch, @project.repository.heads.map(&:name), {}, style: "width:210px;")
%fieldset.adv_settings
%legend Features:
.clearfix
= f.label :issues_enabled, "Issues"
.input= f.check_box :issues_enabled
- if Project.issues_tracker.values.count > 1
.clearfix
= f.label :issues_tracker, "Issues tracker", class: 'control-label'
.input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled })
.clearfix
= f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label'
.input= f.text_field :issues_tracker_id, class: "xxlarge", disabled: !@project.can_have_issues_tracker_id?
.clearfix
= f.label :merge_requests_enabled, "Merge Requests"
.input= f.check_box :merge_requests_enabled
.clearfix
= f.label :wall_enabled, "Wall"
.input= f.check_box :wall_enabled
.clearfix
= f.label :wiki_enabled, "Wiki"
.input= f.check_box :wiki_enabled
%fieldset.features
%legend Public mode:
.clearfix
= f.label :public do
%span Allow public http clone
.input= f.check_box :public
%fieldset.features
%legend Transfer:
.control-group
= f.label :namespace_id do
%span Namespace
.controls
= f.select :namespace_id, namespaces_options(@project.namespace_id, :all), {}, {class: 'chosen'}
%br
%ul.prepend-top-10.cred
%li Be careful. Changing project namespace can have unintended side effects
%li You can transfer project only to namespaces you can manage
%li You will need to update your local repositories to point to the new location.
.actions
= f.submit 'Save Project', class: "btn btn-save"
= link_to 'Cancel', admin_projects_path, class: "btn btn-cancel"
:javascript
$(function(){
new Projects();
})

View File

@ -1,3 +0,0 @@
%h3.page_title #{@project.name} &rarr; Edit project
%hr
= render 'form', project: @project

View File

@ -52,8 +52,8 @@
%i.icon-lock.cgreen
= link_to project.name_with_namespace, [:admin, project]
.pull-right
= link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
= link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
= link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
= link_to 'Destroy', [project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
- if @projects.blank?
%p.nothing_here_message 0 projects matches
- else

View File

@ -1,129 +1,90 @@
%h3.page_title
Project: #{@project.name_with_namespace}
= link_to edit_admin_project_path(@project), class: "btn pull-right" do
= link_to edit_project_path(@project), class: "btn pull-right" do
%i.icon-edit
Edit
%hr
.row
.span6
.ui-box
%h5.title
Project info:
%ul.well-list
%li
%span.light Name:
%strong= @project.name
%li
%span.light Namespace:
%strong
- if @project.namespace
= link_to @project.namespace.human_name, [:admin, @project.group || @project.owner]
- else
Global
%li
%span.light Owned by:
%strong
- if @project.owner
= link_to @project.owner_name, admin_user_path(@project.owner)
- else
(deleted)
%li
%span.light Created by:
%strong
= @project.creator.try(:name) || '(deleted)'
%br
%table.zebra-striped
%thead
%tr
%th Project
%th
%tr
%td
%b
Name:
%td
= @project.name
%tr
%td
%b
Namespace:
%td
- if @project.namespace
= @project.namespace.human_name
- else
Global
%tr
%td
%b
Owned by:
%td
- if @project.owner
= link_to @project.owner_name, admin_user_path(@project.owner)
- else
(deleted)
%tr
%td
%b
Created by:
%td
= @project.creator.try(:name) || '(deleted)'
%tr
%td
%b
Created at:
%td
= @project.created_at.stamp("March 1, 1999")
%tr
%td
%b
Smart HTTP:
%td
= link_to @project.http_url_to_repo
%tr
%td
%b
SSH:
%td
= link_to @project.ssh_url_to_repo
- if @project.public
%tr.bgred
%td
%b
Public Read-Only Code access:
%td
= check_box_tag 'public', nil, @project.public
%li
%span.light Created at:
%strong
= @project.created_at.stamp("March 1, 1999")
- if @repository
%table.zebra-striped
%thead
%tr
%th Repository
%th
%tr
%td
%b
FS Path:
%td
%code= @repository.path_to_repo
%tr
%td
%b
Last commit at:
%td
= last_commit(@project)
%li
%span.light http:
%strong
= link_to @project.http_url_to_repo
%li
%span.light ssh:
%strong
= link_to @project.ssh_url_to_repo
- if @project.repository.exists?
%li
%span.light fs:
%strong
= @repository.path_to_repo
%br
%h5
Team
%small
(#{@project.users.count})
%br
%table.zebra-striped.team_members
%thead
%tr
%th Name
%th Project Access
%th Repository Access
%th
%li
%span.light last commit:
%strong
= last_commit(@project)
- else
%li
%span.light repository:
%strong.cred
does not exist
- @project.users.each do |tm|
%tr
%td
= link_to tm.name, admin_user_path(tm)
%td= @project.project_access_human(tm)
%td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn btn-small"
%td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove small"
%br
%h5 Add new team member
%br
= form_tag team_update_admin_project_path(@project), class: "bulk_import", method: :put do
%table.zebra-striped
%thead
%tr
%th Users
%th Project Access:
%tr
%td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
%td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
%tr
%td= submit_tag 'Add', class: "btn btn-primary"
%td
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
%li
%span.light access:
%strong
- if @project.public
%span.cblue
%i.icon-share
Public
- else
%span.cgreen
%i.icon-lock
Private
.span6
.ui-box
%h5.title
Team
%small
(#{@project.users.count})
= link_to project_team_index_path(@project), class: "btn btn-tiny" do
%i.icon-edit
Edit Team
%ul.well-list.team_members
- @project.users.each do |tm|
%li
%strong
= link_to tm.name, admin_user_path(tm)
%span.pull-right.light= @project.project_access_human(tm)

View File

@ -1,7 +1,2 @@
%ul.nav.nav-tabs
%li
= render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]}
= nav_link(controller: :refs) do
= link_to 'Source', project_tree_path(@project, @ref)
%li.pull-right
= render "shared/clone_panel"
%div.tree-ref-holder
= render 'shared/ref_switcher', destination: 'tree', path: params[:path]

View File

@ -3,10 +3,10 @@
#tree-holder.tree-holder
%ul.breadcrumb
%li
%span.arrow
%i.icon-angle-right
= link_to project_tree_path(@project, @ref) do
= @project.name
- @tree.breadcrumbs(6) do |link|
- tree_breadcrumbs(@tree, 6) do |link|
\/
%li= link
.clear
@ -22,13 +22,13 @@
%table
- current_line = 1
- @blame.each do |commit, lines|
- commit = CommitDecorator.decorate(Commit.new(commit))
- commit = Commit.new(commit)
%tr
%td.blame-commit
%span.commit
= link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id"
&nbsp;
= commit.author_link avatar: true, size: 16
= commit_author_link(commit, avatar: true, size: 16)
&nbsp;
= link_to_gfm truncate(commit.title, length: 20), project_commit_path(@project, commit.id), class: "row_title"
%td.lines.blame-numbers
@ -39,8 +39,10 @@
- else
- lines.each do |line|
= current_line
\
- current_line += 1
%td.lines
%pre
- lines.each do |line|
= line
\

View File

@ -24,14 +24,14 @@
.row
.span5
.author
= @commit.author_link avatar: true, size: 32
= commit_author_link(@commit, avatar: true, size: 32)
authored
%time{title: @commit.authored_date.stamp("Aug 21, 2011 9:23pm")}
#{time_ago_in_words(@commit.authored_date)} ago
- if @commit.different_committer?
.committer
&rarr;
= @commit.committer_link
= commit_committer_link(@commit)
committed
%time{title: @commit.committed_date.stamp("Aug 21, 2011 9:23pm")}
#{time_ago_in_words(@commit.committed_date)} ago

View File

@ -1,10 +1,11 @@
= render "commits/commit_box"
= render "commit_box"
%p.pull-right.cgray
This commit has
%span.cgreen #{@commit.stats.additions} additions
and
%span.cred #{@commit.stats.deletions} deletions
- unless @commit.has_zero_stats?
%p.pull-right.cgray
This commit has
%span.cgreen #{@commit.stats.additions} additions
and
%span.cred #{@commit.stats.deletions} deletions
= render "commits/diffs", diffs: @commit.diffs
= render "notes/notes_with_form"

View File

@ -4,7 +4,7 @@
%strong= link_to "Browse Code »", project_tree_path(@project, commit), class: "right"
%p
= link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id"
= commit.author_link avatar: true, size: 24
= commit_author_link(commit, avatar: true, size: 24)
&nbsp;
= link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "row_title"

View File

@ -2,7 +2,7 @@
- if @path.present?
%ul.breadcrumb
= breadcrumbs
= commits_breadcrumbs
%div{id: dom_id(@project)}
#commits-list= render "commits"

View File

@ -16,7 +16,7 @@
%div.ui-box
%h5.title
Commits (#{@commits.count})
%ul.well-list= render @commits
%ul.well-list= render Commit.decorate(@commits)
- unless @diffs.empty?
%h4 Diff

View File

@ -1,11 +1,11 @@
.ui-box
%h5.title
Groups
%small
%span.light
(#{groups.count})
- if current_user.can_create_group?
%span.pull-right
= link_to new_group_path, class: "btn btn-tiny info" do
= link_to new_group_path, class: "btn btn-small" do
%i.icon-plus
New Group
%ul.well-list

View File

@ -1,11 +1,11 @@
.ui-box
%h5.title
Projects
%small
%span.light
(#{@projects_count})
- if current_user.can_create_project?
%span.pull-right
= link_to new_project_path, class: "btn btn-tiny info" do
= link_to new_project_path, class: "btn btn-small" do
%i.icon-plus
New Project

View File

@ -1,10 +1,10 @@
.ui-box.teams-box
%h5.title
Teams
%small
%span.light
(#{teams.count})
%span.pull-right
= link_to new_team_path, class: "btn btn-tiny info" do
= link_to new_team_path, class: "btn btn-small" do
%i.icon-plus
New Team
%ul.well-list

View File

@ -1,19 +1,19 @@
- if ldap_enable?
= render :partial => 'devise/sessions/new_ldap'
= render partial: 'devise/sessions/new_ldap'
- else
= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f|
= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo"
= f.email_field :email, :class => "text top", :placeholder => "Email", :autofocus => "autofocus"
= f.password_field :password, :class => "text bottom", :placeholder => "Password"
= form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: "login-box" }) do |f|
= image_tag "login-logo.png", width: "304", height: "66", class: "login-logo", alt: "Login Logo"
= f.text_field :login, class: "text top", placeholder: "Username or Email", autofocus: "autofocus"
= f.password_field :password, class: "text bottom", placeholder: "Password"
- if devise_mapping.rememberable?
.clearfix.inputs-list
%label.checkbox.remember_me{:for => "user_remember_me"}
%label.checkbox.remember_me{for: "user_remember_me"}
= f.check_box :remember_me
%span Remember me
%br/
= f.submit "Sign in", :class => "btn-create btn"
= f.submit "Sign in", class: "btn-create btn"
.pull-right
= link_to "Forgot your password?", new_password_path(resource_name), :class => "btn"
= link_to "Forgot your password?", new_password_path(resource_name), class: "btn"
%br/
- if Gitlab.config.gitlab.signup_enabled
%hr/

View File

@ -1,5 +1,5 @@
.file-editor
= form_tag(project_tree_path(@project, @id), method: :put, class: "form-horizontal") do
= form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do
.file_holder
.file_title
%i.icon-file

View File

@ -1,4 +1,3 @@
- commit = CommitDecorator.decorate(commit)
%li.commit
%p
= link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id"

View File

@ -13,7 +13,7 @@
},
time: c.time,
space: c.spaces.first,
refs: join_with_space(c.refs),
refs: get_refs(c),
id: c.sha,
date: c.date,
message: c.message,

View File

@ -4,24 +4,8 @@
%body{class: "#{app_theme} admin"}
= render "layouts/head_panel", title: "Admin area"
= render "layouts/flash"
.container
%ul.main_menu
= nav_link(controller: :dashboard, html_options: {class: 'home'}) do
= link_to admin_root_path, title: "Stats" do
%i.icon-home
= nav_link(controller: :projects) do
= link_to "Projects", admin_projects_path
= nav_link(controller: :teams) do
= link_to "Teams", admin_teams_path
= nav_link(controller: :groups) do
= link_to "Groups", admin_groups_path
= nav_link(controller: :users) do
= link_to "Users", admin_users_path
= nav_link(controller: :logs) do
= link_to "Logs", admin_logs_path
= nav_link(controller: :hooks) do
= link_to "Hooks", admin_hooks_path
= nav_link(controller: :resque) do
= link_to "Background Jobs", admin_resque_path
%nav.main-nav
.container= render 'layouts/nav/admin'
.container
.content= yield

View File

@ -4,25 +4,8 @@
%body{class: "#{app_theme} application"}
= render "layouts/head_panel", title: "Dashboard"
= render "layouts/flash"
.container
%ul.main_menu
= nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
= link_to root_path, title: "Home" do
%i.icon-home
= nav_link(path: 'dashboard#projects') do
= link_to projects_dashboard_path do
Projects
= nav_link(path: 'dashboard#issues') do
= link_to issues_dashboard_path do
Issues
%span.count= current_user.assigned_issues.opened.count
= nav_link(path: 'dashboard#merge_requests') do
= link_to merge_requests_dashboard_path do
Merge Requests
%span.count= current_user.cared_merge_requests.opened.count
= nav_link(path: 'search#show') do
= link_to "Search", search_path
= nav_link(controller: :help) do
= link_to "Help", help_path
%nav.main-nav
.container= render 'layouts/nav/dashboard'
.container
.content= yield

View File

@ -4,25 +4,8 @@
%body{class: "#{app_theme} application"}
= render "layouts/head_panel", title: "group: #{@group.name}"
= render "layouts/flash"
%nav.main-nav
.container= render 'layouts/nav/group'
.container
%ul.main_menu
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do
= link_to group_path(@group), title: "Home" do
%i.icon-home
= nav_link(path: 'groups#issues') do
= link_to issues_group_path(@group) do
Issues
%span.count= current_user.assigned_issues.opened.of_group(@group).count
= nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group) do
Merge Requests
%span.count= current_user.cared_merge_requests.opened.of_group(@group).count
= nav_link(path: 'groups#people') do
= link_to "People", people_group_path(@group)
- if can?(current_user, :manage_group, @group)
= nav_link(path: 'groups#edit') do
= link_to edit_group_path(@group), class: "tab " do
Settings
.content= yield

View File

@ -0,0 +1,19 @@
%ul
= nav_link(controller: :dashboard, html_options: {class: 'home'}) do
= link_to admin_root_path, title: "Stats" do
%i.icon-home
= nav_link(controller: :projects) do
= link_to "Projects", admin_projects_path
= nav_link(controller: :teams) do
= link_to "Teams", admin_teams_path
= nav_link(controller: :groups) do
= link_to "Groups", admin_groups_path
= nav_link(controller: :users) do
= link_to "Users", admin_users_path
= nav_link(controller: :logs) do
= link_to "Logs", admin_logs_path
= nav_link(controller: :hooks) do
= link_to "Hooks", admin_hooks_path
= nav_link(controller: :resque) do
= link_to "Background Jobs", admin_resque_path

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