summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml5
-rw-r--r--Gemfile9
-rw-r--r--Gemfile.lock91
-rw-r--r--app/assets/javascripts/application.js2
-rw-r--r--app/assets/javascripts/issues.js8
-rw-r--r--app/assets/javascripts/main.js.coffee19
-rw-r--r--app/assets/javascripts/notes.js36
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/common.scss8
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/lists.scss10
-rw-r--r--app/assets/stylesheets/sections/events.scss1
-rw-r--r--app/assets/stylesheets/sections/issues.scss2
-rw-r--r--app/assets/stylesheets/sections/merge_requests.scss2
-rw-r--r--app/controllers/repositories_controller.rb7
-rw-r--r--app/models/milestone.rb1
-rw-r--r--app/views/commits/_commit.html.haml4
-rw-r--r--app/views/commits/_head.html.haml5
-rw-r--r--app/views/projects/create.js.haml4
-rw-r--r--app/views/projects/update.js.haml2
-rw-r--r--app/views/repositories/stats.html.haml41
-rw-r--r--config/routes.rb1
-rw-r--r--db/fixtures/development/002_project.rb6
-rw-r--r--db/fixtures/development/004_teams.rb6
-rw-r--r--db/fixtures/development/006_wall.rb59
-rw-r--r--db/fixtures/development/007_issues.rb37
-rw-r--r--db/fixtures/development/008_merge_requests.rb41
-rw-r--r--db/fixtures/development/009_source_code.rb27
-rw-r--r--db/schema.rb28
-rw-r--r--doc/install/installation.md8
-rw-r--r--features/project/commits/commits.feature4
-rw-r--r--features/steps/dashboard/dashboard.rb8
-rw-r--r--features/steps/dashboard/dashboard_search.rb2
-rw-r--r--features/steps/group/group.rb6
-rw-r--r--features/steps/profile/profile.rb2
-rw-r--r--features/steps/profile/profile_ssh_keys.rb2
-rw-r--r--features/steps/project/project_browse_commits.rb7
-rw-r--r--features/steps/project/project_hooks.rb2
-rw-r--r--features/steps/project/project_issues.rb32
-rw-r--r--features/steps/project/project_labels.rb2
-rw-r--r--features/steps/project/project_merge_requests.rb18
-rw-r--r--features/steps/project/project_milestones.rb4
-rw-r--r--features/steps/project/project_team_management.rb6
-rw-r--r--features/steps/shared/paths.rb4
-rw-r--r--features/steps/shared/project.rb2
-rw-r--r--features/support/env.rb25
-rw-r--r--lib/gitlab/backend/gitolite_config.rb6
-rw-r--r--lib/gitlab/git_stats.rb73
-rw-r--r--lib/gitlab/seeder.rb10
-rw-r--r--lib/redcarpet/render/gitlab_html.rb6
-rw-r--r--lib/tasks/gitlab/status.rake20
-rw-r--r--spec/factories.rb18
-rw-r--r--spec/mailers/notify_spec.rb40
-rw-r--r--spec/models/event_spec.rb2
-rw-r--r--spec/models/issue_spec.rb9
-rw-r--r--spec/models/key_spec.rb4
-rw-r--r--spec/models/merge_request_spec.rb14
-rw-r--r--spec/models/milestone_spec.rb4
-rw-r--r--spec/models/note_spec.rb36
-rw-r--r--spec/models/project_hooks_spec.rb16
-rw-r--r--spec/models/project_security_spec.rb6
-rw-r--r--spec/models/project_spec.rb22
-rw-r--r--spec/models/system_hook_spec.rb18
-rw-r--r--spec/models/user_spec.rb2
-rw-r--r--spec/models/web_hook_spec.rb4
-rw-r--r--spec/observers/activity_observer_spec.rb18
-rw-r--r--spec/observers/issue_observer_spec.rb4
-rw-r--r--spec/observers/merge_request_observer_spec.rb4
-rw-r--r--spec/observers/note_observer_spec.rb2
-rw-r--r--spec/observers/user_observer_spec.rb2
-rw-r--r--spec/observers/users_project_observer_spec.rb14
-rw-r--r--spec/requests/admin/admin_hooks_spec.rb8
-rw-r--r--spec/requests/admin/admin_projects_spec.rb8
-rw-r--r--spec/requests/admin/admin_users_spec.rb10
-rw-r--r--spec/requests/api/issues_spec.rb6
-rw-r--r--spec/requests/api/merge_requests_spec.rb16
-rw-r--r--spec/requests/api/milestones_spec.rb6
-rw-r--r--spec/requests/api/projects_spec.rb18
-rw-r--r--spec/requests/api/session_spec.rb2
-rw-r--r--spec/requests/api/users_spec.rb12
-rw-r--r--spec/requests/atom/dashboard_issues_spec.rb10
-rw-r--r--spec/requests/atom/dashboard_spec.rb2
-rw-r--r--spec/requests/atom/issues_spec.rb6
-rw-r--r--spec/requests/gitlab_flavored_markdown_spec.rb38
-rw-r--r--spec/requests/issues_spec.rb63
-rw-r--r--spec/requests/projects_deploy_keys_spec.rb6
-rw-r--r--spec/requests/projects_spec.rb10
-rw-r--r--spec/requests/search_spec.rb4
-rw-r--r--spec/requests/security/profile_access_spec.rb2
-rw-r--r--spec/requests/snippets_spec.rb14
-rw-r--r--spec/roles/issue_commonality_spec.rb1
-rw-r--r--spec/spec_helper.rb10
-rw-r--r--spec/support/login_helpers.rb2
-rw-r--r--spec/support/matchers.rb4
-rw-r--r--spec/workers/post_receive_spec.rb4
-rw-r--r--vendor/assets/javascripts/g.bar-min.js7
-rw-r--r--vendor/assets/javascripts/g.raphael-min.js28
95 files changed, 748 insertions, 499 deletions
diff --git a/.travis.yml b/.travis.yml
index fe602a591b1..868a6c6c238 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,10 @@ env:
- DB=mysql
before_install:
- sudo apt-get install libicu-dev -y
- - sudo apt-get install libqt4-dev libqtwebkit-dev -y
+ - wget -P /tmp http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-i686.tar.bz2
+ - tar -xf /tmp/phantomjs-1.7.0-linux-i686.tar.bz2 -C /tmp/
+ - sudo rm -rf /usr/local/phantomjs
+ - sudo mv /tmp/phantomjs-1.7.0-linux-i686 /usr/local/phantomjs
- gem install charlock_holmes -v="0.6.9"
branches:
only:
diff --git a/Gemfile b/Gemfile
index 2a5b95b3803..d4cd45cef66 100644
--- a/Gemfile
+++ b/Gemfile
@@ -8,7 +8,7 @@ def linux_only(require_as)
RUBY_PLATFORM.include?('linux') && require_as
end
-gem "rails", "3.2.8"
+gem "rails", "3.2.9"
# Supported DBs
gem "sqlite3", group: :sqlite
@@ -68,7 +68,7 @@ gem "redcarpet", "~> 2.1.1"
gem "github-markup", "~> 0.7.4", require: 'github/markup'
# Servers
-gem "thin"
+gem "thin", '~> 1.5.0'
gem "unicorn"
# Issue tags
@@ -123,8 +123,6 @@ group :development, :test do
gem 'spinach-rails'
gem "rspec-rails"
gem "capybara"
- gem "capybara-webkit"
- gem "headless"
gem "pry"
gem "awesome_print"
gem "database_cleaner"
@@ -139,6 +137,9 @@ group :development, :test do
gem 'rb-fsevent', require: darwin_only('rb-fsevent')
gem 'growl', require: darwin_only('growl')
gem 'rb-inotify', require: linux_only('rb-inotify')
+
+ # PhantomJS driver for Capybara
+ gem 'poltergeist'
end
group :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index a78e7379514..3c1fa68dcb1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -60,31 +60,31 @@ GIT
GEM
remote: http://rubygems.org/
specs:
- actionmailer (3.2.8)
- actionpack (= 3.2.8)
+ actionmailer (3.2.9)
+ actionpack (= 3.2.9)
mail (~> 2.4.4)
- actionpack (3.2.8)
- activemodel (= 3.2.8)
- activesupport (= 3.2.8)
+ actionpack (3.2.9)
+ activemodel (= 3.2.9)
+ activesupport (= 3.2.9)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
rack (~> 1.4.0)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
- sprockets (~> 2.1.3)
- activemodel (3.2.8)
- activesupport (= 3.2.8)
+ sprockets (~> 2.2.1)
+ activemodel (3.2.9)
+ activesupport (= 3.2.9)
builder (~> 3.0.0)
- activerecord (3.2.8)
- activemodel (= 3.2.8)
- activesupport (= 3.2.8)
+ activerecord (3.2.9)
+ activemodel (= 3.2.9)
+ activesupport (= 3.2.9)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
- activeresource (3.2.8)
- activemodel (= 3.2.8)
- activesupport (= 3.2.8)
- activesupport (3.2.8)
+ activeresource (3.2.9)
+ activemodel (= 3.2.9)
+ activesupport (= 3.2.9)
+ activesupport (3.2.9)
i18n (~> 0.6)
multi_json (~> 1.0)
acts-as-taggable-on (2.3.1)
@@ -95,7 +95,7 @@ GEM
bcrypt-ruby (3.0.1)
blankslate (2.1.2.4)
bootstrap-sass (2.0.4.0)
- builder (3.0.2)
+ builder (3.0.4)
capybara (1.1.2)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
@@ -103,9 +103,6 @@ GEM
rack-test (>= 0.5.4)
selenium-webdriver (~> 2.0)
xpath (~> 0.1.4)
- capybara-webkit (0.12.1)
- capybara (>= 1.0.0, < 1.2)
- json
carrierwave (0.6.2)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
@@ -126,7 +123,7 @@ GEM
colored (1.2)
colorize (0.5.8)
crack (0.3.1)
- daemons (1.1.8)
+ daemons (1.1.9)
database_cleaner (0.8.0)
devise (2.1.2)
bcrypt-ruby (~> 3.0)
@@ -142,7 +139,7 @@ GEM
rspec (~> 2.0)
erubis (2.7.0)
escape_utils (0.2.4)
- eventmachine (0.12.10)
+ eventmachine (1.0.0)
execjs (1.4.0)
multi_json (~> 1.0)
factory_girl (4.0.0)
@@ -152,6 +149,8 @@ GEM
railties (>= 3.0.0)
faraday (0.8.4)
multipart-post (~> 1.1)
+ faye-websocket (0.4.6)
+ eventmachine (>= 0.12.0)
ffaker (1.14.0)
ffi (1.0.11)
font-awesome-sass-rails (2.0.0.0)
@@ -198,8 +197,8 @@ GEM
hashery (1.5.0)
blankslate
hashie (1.2.0)
- headless (0.3.1)
hike (1.2.1)
+ http_parser.rb (0.5.3)
httparty (0.8.3)
multi_json (~> 1.0)
multi_xml
@@ -236,7 +235,7 @@ GEM
mime-types (1.19)
modernizr (2.5.3)
sprockets (~> 2.0)
- multi_json (1.3.6)
+ multi_json (1.3.7)
multi_xml (0.5.1)
multipart-post (1.1.5)
mysql2 (0.3.11)
@@ -269,6 +268,12 @@ GEM
omniauth-oauth (~> 1.0)
orm_adapter (0.3.0)
pg (0.14.0)
+ poltergeist (1.0.2)
+ capybara (~> 1.1)
+ childprocess (~> 0.3)
+ faye-websocket (~> 0.4, >= 0.4.4)
+ http_parser.rb (~> 0.5.3)
+ multi_json (~> 1.0)
polyglot (0.3.3)
posix-spawn (0.3.6)
pry (0.9.9.6)
@@ -289,28 +294,28 @@ GEM
rack
rack-ssl (1.3.2)
rack
- rack-test (0.6.1)
+ rack-test (0.6.2)
rack (>= 1.0)
- rails (3.2.8)
- actionmailer (= 3.2.8)
- actionpack (= 3.2.8)
- activerecord (= 3.2.8)
- activeresource (= 3.2.8)
- activesupport (= 3.2.8)
+ rails (3.2.9)
+ actionmailer (= 3.2.9)
+ actionpack (= 3.2.9)
+ activerecord (= 3.2.9)
+ activeresource (= 3.2.9)
+ activesupport (= 3.2.9)
bundler (~> 1.0)
- railties (= 3.2.8)
+ railties (= 3.2.9)
rails-dev-tweaks (0.6.1)
actionpack (~> 3.1)
railties (~> 3.1)
- railties (3.2.8)
- actionpack (= 3.2.8)
- activesupport (= 3.2.8)
+ railties (3.2.9)
+ actionpack (= 3.2.9)
+ activesupport (= 3.2.9)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
raindrops (0.9.0)
- rake (0.9.2.2)
+ rake (10.0.0)
raphael-rails (1.5.2)
rb-fsevent (0.9.1)
rb-inotify (0.8.8)
@@ -381,8 +386,9 @@ GEM
capybara (~> 1)
railties (>= 3)
spinach (>= 0.4)
- sprockets (2.1.3)
+ sprockets (2.2.1)
hike (~> 1.2)
+ multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.6)
@@ -390,16 +396,16 @@ GEM
test_after_commit (0.0.1)
therubyracer (0.10.1)
libv8 (~> 3.3.10)
- thin (1.3.1)
+ thin (1.5.0)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
thor (0.16.0)
tilt (1.3.3)
- treetop (1.4.10)
+ treetop (1.4.12)
polyglot
polyglot (>= 0.3.1)
- tzinfo (0.3.33)
+ tzinfo (0.3.35)
uglifier (1.0.3)
execjs (>= 0.3.0)
multi_json (>= 1.0.2)
@@ -427,7 +433,6 @@ DEPENDENCIES
awesome_print
bootstrap-sass (= 2.0.4)
capybara
- capybara-webkit
carrierwave
chosen-rails
coffee-rails (= 3.2.2)
@@ -454,7 +459,6 @@ DEPENDENCIES
guard-rspec
guard-spinach
haml-rails
- headless
httparty
jquery-atwho-rails (= 0.1.6)
jquery-rails (= 2.0.2)
@@ -470,11 +474,12 @@ DEPENDENCIES
omniauth-ldap!
omniauth-twitter
pg
+ poltergeist
pry
pygments.rb!
quiet_assets (= 1.0.1)
rack-mini-profiler
- rails (= 3.2.8)
+ rails (= 3.2.9)
rails-dev-tweaks
raphael-rails (= 1.5.2)
rb-fsevent
@@ -495,7 +500,7 @@ DEPENDENCIES
stamp
test_after_commit
therubyracer
- thin
+ thin (~> 1.5.0)
uglifier (= 1.0.3)
unicorn
webmock
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index ae2c925c153..49effdf9c15 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -18,6 +18,8 @@
//= require modernizr
//= require chosen-jquery
//= require raphael
+//= require g.raphael-min
+//= require g.bar-min
//= require branch-graph
//= require ace-src-noconflict/ace
//= require_tree .
diff --git a/app/assets/javascripts/issues.js b/app/assets/javascripts/issues.js
index db3ad7f745c..55db72c39f0 100644
--- a/app/assets/javascripts/issues.js
+++ b/app/assets/javascripts/issues.js
@@ -39,10 +39,10 @@ function backToIssues(){
}
function initIssuesSearch() {
- var href = $('.issue_search').parent().attr('action');
+ var href = $('#issue_search_form').attr('action');
var last_terms = '';
- $('.issue_search').keyup(function() {
+ $('#issue_search').keyup(function() {
var terms = $(this).val();
var milestone_id = $('#milestone_id').val();
var status = $('#status').val();
@@ -57,10 +57,6 @@ function initIssuesSearch() {
}
}
});
-
- $('.delete-issue').live('ajax:success', function() {
- $(this).closest('tr').fadeOut(); updatePage();
- });
}
/**
diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee
index 04e6b2ef9d1..b41651bf77b 100644
--- a/app/assets/javascripts/main.js.coffee
+++ b/app/assets/javascripts/main.js.coffee
@@ -58,25 +58,6 @@ $ ->
$(@).next('table').show()
$(@).remove()
- # Note markdown preview
- $(document).on 'click', '#preview-link', (e) ->
- $('#preview-note').text 'Loading...'
-
- previewLinkText = if $(@).text() is 'Preview' then 'Edit' else 'Preview'
- $(@).text previewLinkText
-
- note = $('#note_note').val()
-
- if note.trim().length is 0
- $('#preview-note').text 'Nothing to preview.'
- else
- $.post $(@).attr('href'), {note: note}, (data) ->
- $('#preview-note').html(data)
-
- $('#preview-note, #note_note').toggle()
- e.preventDefault()
- false
-
(($) ->
_chosen = $.fn.chosen
$.fn.extend chosen: (options) ->
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 558643d504d..b6f65b7aa5e 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -14,8 +14,8 @@ var NoteList = {
this.notes_path = path + ".js";
this.target_id = tid;
this.target_type = tt;
- this.reversed = $("#notes-list").hasClass("reversed");
- this.target_params = "&target_type=" + this.target_type + "&target_id=" + this.target_id;
+ this.reversed = $("#notes-list").is(".reversed");
+ this.target_params = "target_type=" + this.target_type + "&target_id=" + this.target_id;
// get initial set of notes
this.getContent();
@@ -33,6 +33,8 @@ var NoteList = {
$(".note-form-holder").on("ajax:complete", function(){
$(".submit_note").enable();
+ $('#preview-note').hide();
+ $('#note_note').show();
})
disableButtonIfEmptyField(".note-text", ".submit_note");
@@ -52,6 +54,26 @@ var NoteList = {
$('.note_advanced_opts').show();
});
}
+
+ // Setup note preview
+ $(document).on('click', '#preview-link', function(e) {
+ $('#preview-note').text('Loading...');
+
+ $(this).text($(this).text() === "Edit" ? "Preview" : "Edit");
+
+ var note_text = $('#note_note').val();
+
+ if(note_text.trim().length === 0) {
+ $('#preview-note').text('Nothing to preview.');
+ } else {
+ $.post($(this).attr('href'), {note: note_text}).success(function(data) {
+ $('#preview-note').html(data);
+ });
+ }
+
+ $('#preview-note, #note_note').toggle();
+ e.preventDefault();
+ });
},
@@ -69,7 +91,7 @@ var NoteList = {
$.ajax({
type: "GET",
url: this.notes_path,
- data: "?" + this.target_params,
+ data: this.target_params,
complete: function(){ $('.notes-status').removeClass("loading")},
beforeSend: function() { $('.notes-status').addClass("loading") },
dataType: "script"});
@@ -131,7 +153,7 @@ var NoteList = {
$.ajax({
type: "GET",
url: this.notes_path,
- data: "loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id + this.target_params,
+ data: this.target_params + "&loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id,
complete: function(){ $('.notes-status').removeClass("loading")},
beforeSend: function() { $('.notes-status').addClass("loading") },
dataType: "script"});
@@ -192,7 +214,7 @@ var NoteList = {
$.ajax({
type: "GET",
url: this.notes_path,
- data: "loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id) + this.target_params,
+ data: this.target_params + "&loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id),
dataType: "script"});
},
@@ -264,7 +286,7 @@ var PerLineNotes = {
$(this).closest("tr").after(form);
form.find("#note_line_code").val($(this).data("lineCode"));
form.show();
- return false;
+ e.preventDefault();
});
disableButtonIfEmptyField(".line-note-text", ".submit_inline_note");
@@ -285,7 +307,7 @@ var PerLineNotes = {
// elements must really be removed for this to work reliably
var trLine = trNote.prev();
var trRpl = trNote.next();
- if (trLine.hasClass("line_holder") && trRpl.hasClass("reply")) {
+ if (trLine.is(".line_holder") && trRpl.is(".reply")) {
trRpl.fadeOut(function() { $(this).remove(); });
}
});
diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index aa9c421fbdf..25c355e90ce 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -68,10 +68,10 @@
.alert-message.error { @extend .alert-error; }
/** AVATARS **/
-img.avatar { float:left; margin-right:15px; width:40px; border:1px solid #ddd; padding:1px; }
-img.avatar.s16 { width:16px; height:16px; }
-img.avatar.s24 { width:24px; height:24px; }
-img.avatar.s32 { width:32px; height:32px; }
+img.avatar { float:left; margin-right:12px; width:40px; border:1px solid #ddd; padding:1px; }
+img.avatar.s16 { width:16px; height:16px; margin-right:6px; }
+img.avatar.s24 { width:24px; height:24px; margin-right:8px; }
+img.avatar.s32 { width:32px; height:32px; margin-right:10px; }
img.lil_av { padding-left: 4px; padding-right:3px; }
/** HELPERS **/
diff --git a/app/assets/stylesheets/gitlab_bootstrap/lists.scss b/app/assets/stylesheets/gitlab_bootstrap/lists.scss
index a5d6bd0af4c..4fe45ecc277 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/lists.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/lists.scss
@@ -21,7 +21,7 @@ ul {
.author { color: #999; }
p {
- padding-top:5px;
+ padding-top: 1px;
margin:0;
color:#222;
img {
@@ -31,3 +31,11 @@ ul {
}
}
}
+
+ol, ul {
+ &.styled {
+ li {
+ padding:2px;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss
index 99523639fe7..369ebc81e31 100644
--- a/app/assets/stylesheets/sections/events.scss
+++ b/app/assets/stylesheets/sections/events.scss
@@ -43,6 +43,7 @@
.event-body {
p {
color:#555;
+ padding-top: 5px;
}
.event-info {
color:#666;
diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss
index 3ad9d6f7c81..93622d6149a 100644
--- a/app/assets/stylesheets/sections/issues.scss
+++ b/app/assets/stylesheets/sections/issues.scss
@@ -44,7 +44,7 @@
img.avatar {
width:32px;
- margin-top:4px;
+ margin-top:1px;
}
}
}
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index fc9ad47207a..78e3fa397cb 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -71,7 +71,7 @@ li.merge_request {
padding:7px 10px;
img.avatar {
width: 32px;
- margin-top: 4px;
+ margin-top: 1px;
}
p {
padding: 0px;
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index 18b240e4550..7678fbff3f1 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -16,9 +16,14 @@ class RepositoriesController < ProjectResourceController
@tags = @project.tags
end
+ def stats
+ @stats = Gitlab::GitStats.new(@project.repo, @project.root_ref)
+ @graph = @stats.graph
+ end
+
def archive
unless can?(current_user, :download_code, @project)
- render_404 and return
+ render_404 and return
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 41412a13bf5..1dcc93bf2a4 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -7,6 +7,7 @@ class Milestone < ActiveRecord::Base
validates :title, presence: true
validates :project, presence: true
+ validates :closed, inclusion: { in: [true, false] }
def self.active
where("due_date > ? OR due_date IS NULL", Date.today)
diff --git a/app/views/commits/_commit.html.haml b/app/views/commits/_commit.html.haml
index 8e96d16abaf..156ff1e9d85 100644
--- a/app/views/commits/_commit.html.haml
+++ b/app/views/commits/_commit.html.haml
@@ -4,8 +4,8 @@
%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"
- %strong= commit.author_link avatar: true, size: 24
- %span.dash &ndash;
+ = commit.author_link avatar: true, size: 24
+ &nbsp;
= link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, commit.id), class: "row_title"
%span.committed_ago
diff --git a/app/views/commits/_head.html.haml b/app/views/commits/_head.html.haml
index c001c2f70ce..2ec1d24bbef 100644
--- a/app/views/commits/_head.html.haml
+++ b/app/views/commits/_head.html.haml
@@ -16,6 +16,11 @@
Tags
%span.badge= @project.tags.length
+ = nav_link(controller: :repositories, action: :stats) do
+ = link_to stats_project_repository_path(@project) do
+ Stats
+
+
- if current_controller?(:commits) && current_user.private_token
%li.right
%span.rss-icon
diff --git a/app/views/projects/create.js.haml b/app/views/projects/create.js.haml
index 2f6264a15af..e86845656f9 100644
--- a/app/views/projects/create.js.haml
+++ b/app/views/projects/create.js.haml
@@ -4,8 +4,8 @@
- else
- if @project.git_error?
location.href = "#{errors_githost_path}";
- -else
+ -else
:plain
$('.project_new_holder').show();
$("#new_project").replaceWith("#{escape_javascript(render('new_form'))}");
- $('.ajax_loader').hide();
+ $('.save-project-loader').hide();
diff --git a/app/views/projects/update.js.haml b/app/views/projects/update.js.haml
index a961dc39791..8aaa0e491dd 100644
--- a/app/views/projects/update.js.haml
+++ b/app/views/projects/update.js.haml
@@ -5,4 +5,4 @@
:plain
$('.project_edit_holder').show();
$(".edit_project").replaceWith("#{escape_javascript(render('form'))}");
- $('.ajax_loader').hide();
+ $('.save-project-loader').hide();
diff --git a/app/views/repositories/stats.html.haml b/app/views/repositories/stats.html.haml
new file mode 100644
index 00000000000..a93814a4777
--- /dev/null
+++ b/app/views/repositories/stats.html.haml
@@ -0,0 +1,41 @@
+= render "commits/head"
+.row
+ .span5
+ %h4
+ Stats:
+ %p
+ %b Total commits:
+ %span= @stats.commits_count
+ %p
+ %b Total files in #{@project.root_ref}:
+ %span= @stats.files_count
+ %p
+ %b Authors:
+ %span= @stats.authors_count
+
+ %br
+ %div#activity-chart
+ .span7
+ %h4 Top 50 Committers:
+ %ol.styled
+ - @stats.authors[0...50].each do |author|
+ %li
+ = image_tag gravatar_icon(author.email, 16), class: 'avatar s16'
+ = author.name
+ %small.light= author.email
+ .right
+ = author.commits
+
+
+:javascript
+ $(function(){
+ var labels = [#{@graph.labels.to_json}];
+ var commits = [#{@graph.commits.join(', ')}];
+ var r = Raphael('activity-chart');
+ r.text(160, 10, "Commit activity for last #{@graph.weeks} weeks").attr({ font: "13px sans-serif" });
+ r.barchart(
+ 10, 10, 400, 160,
+ [commits],
+ {colors:["#456"]}
+ ).label(labels, true);
+ })
diff --git a/config/routes.rb b/config/routes.rb
index e597c61e0a2..bf762865436 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -128,6 +128,7 @@ Gitlab::Application.routes.draw do
member do
get "branches"
get "tags"
+ get "stats"
get "archive"
end
end
diff --git a/db/fixtures/development/002_project.rb b/db/fixtures/development/002_project.rb
index eea987ffcc2..eb68b5fe93a 100644
--- a/db/fixtures/development/002_project.rb
+++ b/db/fixtures/development/002_project.rb
@@ -1,5 +1,5 @@
Project.seed(:id, [
- { :id => 1, :name => "Rubinius", :path => "rubinius", :code => "rubinius", :owner_id => 1 },
- { :id => 2, :name => "Diaspora", :path => "diaspora", :code => "diaspora", :owner_id => 1 },
- { :id => 3, :name => "Ruby on Rails", :path => "ruby_on_rails", :code => "ruby_on_rails", :owner_id => 1 }
+ { id: 1, name: "Underscore.js", path: "underscore", code: "underscore", owner_id: 1 },
+ { id: 2, name: "Diaspora", path: "diaspora", code: "diaspora", owner_id: 1 },
+ { id: 3, name: "Ruby on Rails", path: "rails", code: "rails", owner_id: 1 }
])
diff --git a/db/fixtures/development/004_teams.rb b/db/fixtures/development/004_teams.rb
index 5af98b92c02..2752cb44e1d 100644
--- a/db/fixtures/development/004_teams.rb
+++ b/db/fixtures/development/004_teams.rb
@@ -1,3 +1,5 @@
+UsersProject.skip_callback(:save, :after, :update_repository)
+
UsersProject.seed(:id, [
{ :id => 1, :project_id => 1, :user_id => 1, :project_access => UsersProject::MASTER },
{ :id => 2, :project_id => 1, :user_id => 2, :project_access => UsersProject::REPORTER},
@@ -18,4 +20,8 @@ UsersProject.seed(:id, [
{ :id => 16, :project_id => 3, :user_id => 5, :project_access => UsersProject::MASTER}
])
+UsersProject.set_callback(:save, :after, :update_repository)
+puts "\nRebuild gitolite\n".yellow
+Project.all.each(&:update_repository)
+puts "OK".green
diff --git a/db/fixtures/development/006_wall.rb b/db/fixtures/development/006_wall.rb
index 7c0d25d1000..a9fb66dda6b 100644
--- a/db/fixtures/development/006_wall.rb
+++ b/db/fixtures/development/006_wall.rb
@@ -1,40 +1,19 @@
-Note.seed(:id, [
- { :id => 1, :project_id => 1, :author_id => 1, :note => Faker::Lorem.sentence(6) },
- { :id => 2, :project_id => 1, :author_id => 2, :note => Faker::Lorem.sentence(6) },
- { :id => 3, :project_id => 1, :author_id => 3, :note => Faker::Lorem.sentence(6) },
- { :id => 4, :project_id => 1, :author_id => 4, :note => Faker::Lorem.sentence(6) },
- { :id => 5, :project_id => 1, :author_id => 5, :note => Faker::Lorem.sentence(6) },
-
- { :id => 6, :project_id => 2, :author_id => 1, :note => Faker::Lorem.sentence(6) },
- { :id => 7, :project_id => 2, :author_id => 2, :note => Faker::Lorem.sentence(6) },
- { :id => 8, :project_id => 2, :author_id => 3, :note => Faker::Lorem.sentence(6) },
- { :id => 9, :project_id => 2, :author_id => 4, :note => Faker::Lorem.sentence(6) },
- { :id => 11, :project_id => 2, :author_id => 5, :note => Faker::Lorem.sentence(6) },
-
- { :id => 12, :project_id => 3, :author_id => 1, :note => Faker::Lorem.sentence(6)},
- { :id => 13, :project_id => 3, :author_id => 2, :note => Faker::Lorem.sentence(6)},
- { :id => 14, :project_id => 3, :author_id => 3, :note => Faker::Lorem.sentence(6)},
- { :id => 15, :project_id => 3, :author_id => 4, :note => Faker::Lorem.sentence(6)},
- { :id => 16, :project_id => 3, :author_id => 5, :note => Faker::Lorem.sentence(6)},
-
- { :id => 21, :project_id => 1, :author_id => 1, :note => Faker::Lorem.sentence(6) },
- { :id => 22, :project_id => 1, :author_id => 2, :note => Faker::Lorem.sentence(6) },
- { :id => 23, :project_id => 1, :author_id => 3, :note => Faker::Lorem.sentence(6) },
- { :id => 24, :project_id => 1, :author_id => 4, :note => Faker::Lorem.sentence(6) },
- { :id => 25, :project_id => 1, :author_id => 5, :note => Faker::Lorem.sentence(6) },
-
- { :id => 26, :project_id => 2, :author_id => 1, :note => Faker::Lorem.sentence(6) },
- { :id => 27, :project_id => 2, :author_id => 2, :note => Faker::Lorem.sentence(6) },
- { :id => 28, :project_id => 2, :author_id => 3, :note => Faker::Lorem.sentence(6) },
- { :id => 29, :project_id => 2, :author_id => 4, :note => Faker::Lorem.sentence(6) },
- { :id => 30, :project_id => 2, :author_id => 5, :note => Faker::Lorem.sentence(6) },
-
- { :id => 32, :project_id => 3, :author_id => 1, :note => Faker::Lorem.sentence(6)},
- { :id => 33, :project_id => 3, :author_id => 2, :note => Faker::Lorem.sentence(6)},
- { :id => 34, :project_id => 3, :author_id => 3, :note => Faker::Lorem.sentence(6)},
- { :id => 35, :project_id => 3, :author_id => 4, :note => Faker::Lorem.sentence(6)},
- { :id => 36, :project_id => 3, :author_id => 5, :note => Faker::Lorem.sentence(6)}
-])
-
-
-
+Gitlab::Seeder.quiet do
+ (1..300).each do |i|
+ # Random Project
+ project_id = rand(2) + 1
+ project = Project.find(project_id)
+
+ # Random user
+ user = project.users.sample
+ user_id = user.id
+
+ Note.seed(:id, [{
+ id: i,
+ project_id: project_id,
+ author_id: user_id,
+ note: Faker::Lorem.sentence(6)
+ }])
+ print('.')
+ end
+end
diff --git a/db/fixtures/development/007_issues.rb b/db/fixtures/development/007_issues.rb
index d60af71e6a2..98e32fccc3d 100644
--- a/db/fixtures/development/007_issues.rb
+++ b/db/fixtures/development/007_issues.rb
@@ -1,20 +1,23 @@
-(1..300).each do |i|
- # Random Project
- project_id = rand(2) + 1
- project = Project.find(project_id)
+Gitlab::Seeder.quiet do
+ (1..300).each do |i|
+ # Random Project
+ project_id = rand(2) + 1
+ project = Project.find(project_id)
- # Random user
- user = project.users.sample
- user_id = user.id
- IssueObserver.current_user = user
+ # Random user
+ user = project.users.sample
+ user_id = user.id
+ IssueObserver.current_user = user
- Issue.seed(:id, [{
- id: i,
- project_id: project_id,
- author_id: user_id,
- assignee_id: user_id,
- closed: [true, false].sample,
- milestone: project.milestones.sample,
- title: Faker::Lorem.sentence(6)
- }])
+ Issue.seed(:id, [{
+ id: i,
+ project_id: project_id,
+ author_id: user_id,
+ assignee_id: user_id,
+ closed: [true, false].sample,
+ milestone: project.milestones.sample,
+ title: Faker::Lorem.sentence(6)
+ }])
+ print('.')
+ end
end
diff --git a/db/fixtures/development/008_merge_requests.rb b/db/fixtures/development/008_merge_requests.rb
index 8d20e628113..698c55ad95f 100644
--- a/db/fixtures/development/008_merge_requests.rb
+++ b/db/fixtures/development/008_merge_requests.rb
@@ -1,22 +1,25 @@
-(1..300).each do |i|
- # Random Project
- project_id = rand(2) + 1
- project = Project.find(project_id)
+Gitlab::Seeder.quiet do
+ (1..300).each do |i|
+ # Random Project
+ project_id = rand(2) + 1
+ project = Project.find(project_id)
- # Random user
- user = project.users.sample
- user_id = user.id
- MergeRequestObserver.current_user = user
+ # Random user
+ user = project.users.sample
+ user_id = user.id
+ MergeRequestObserver.current_user = user
- MergeRequest.seed(:id, [{
- id: i,
- source_branch: 'master',
- target_branch: 'feature',
- project_id: project_id,
- author_id: user_id,
- assignee_id: user_id,
- closed: [true, false].sample,
- milestone: project.milestones.sample,
- title: Faker::Lorem.sentence(6)
- }])
+ MergeRequest.seed(:id, [{
+ id: i,
+ source_branch: 'master',
+ target_branch: 'feature',
+ project_id: project_id,
+ author_id: user_id,
+ assignee_id: user_id,
+ closed: [true, false].sample,
+ milestone: project.milestones.sample,
+ title: Faker::Lorem.sentence(6)
+ }])
+ print('.')
+ end
end
diff --git a/db/fixtures/development/009_source_code.rb b/db/fixtures/development/009_source_code.rb
new file mode 100644
index 00000000000..489bd02ea32
--- /dev/null
+++ b/db/fixtures/development/009_source_code.rb
@@ -0,0 +1,27 @@
+root = Gitlab.config.git_base_path
+
+projects = [
+ { path: 'underscore.git', git: 'https://github.com/documentcloud/underscore.git' },
+ { path: 'diaspora.git', git: 'https://github.com/diaspora/diaspora.git' },
+ { path: 'rails.git', git: 'https://github.com/rails/rails.git' },
+]
+
+projects.each do |project|
+ project_path = File.join(root, project[:path])
+
+
+ next if File.exists?(project_path)
+
+ cmds = [
+ "cd #{root} && sudo -u git -H git clone --bare #{project[:git]}",
+ "sudo cp ./lib/hooks/post-receive #{project_path}/hooks/post-receive",
+ "sudo chown git:git #{project_path}/hooks/post-receive"
+ ]
+
+ cmds.each do |cmd|
+ puts cmd.yellow
+ `#{cmd}`
+ end
+end
+
+puts "OK".green
diff --git a/db/schema.rb b/db/schema.rb
index 51ab2072448..e7eb5696b0e 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -156,30 +156,30 @@ ActiveRecord::Schema.define(:version => 20121026114600) do
end
create_table "users", :force => true do |t|
- t.string "email", :default => "", :null => false
- t.string "encrypted_password", :limit => 128, :default => "", :null => false
+ t.string "email", :default => "", :null => false
+ t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
- t.integer "sign_in_count", :default => 0
+ t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
t.string "name"
- t.boolean "admin", :default => false, :null => false
- t.integer "projects_limit", :default => 10
- t.string "skype", :default => "", :null => false
- t.string "linkedin", :default => "", :null => false
- t.string "twitter", :default => "", :null => false
+ t.boolean "admin", :default => false, :null => false
+ t.integer "projects_limit", :default => 10
+ t.string "skype", :default => "", :null => false
+ t.string "linkedin", :default => "", :null => false
+ t.string "twitter", :default => "", :null => false
t.string "authentication_token"
- t.boolean "dark_scheme", :default => false, :null => false
- t.integer "theme_id", :default => 1, :null => false
+ t.boolean "dark_scheme", :default => false, :null => false
+ t.integer "theme_id", :default => 1, :null => false
t.string "bio"
- t.boolean "blocked", :default => false, :null => false
- t.integer "failed_attempts", :default => 0
+ t.boolean "blocked", :default => false, :null => false
+ t.integer "failed_attempts", :default => 0
t.datetime "locked_at"
t.string "extern_uid"
t.string "provider"
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 04a22a43b13..07ed0b0f9de 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -180,6 +180,14 @@ and ensure you have followed all of the above steps carefully.
sudo gem install bundler
sudo -u gitlab -H bundle install --without development test sqlite postgres --deployment
+#### Configure git client
+
+Gitlab needs to be able to commit and push changes to gitolite.
+Git requires a username and email in order to be able to do that.
+
+ sudo -u gitlab -H git config --global user.email "gitlab@localhost"
+ sudo -u gitlab -H git config --global user.name "Gitlab"
+
#### Setup application
sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production
diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature
index f5a11048b2a..56069cdc977 100644
--- a/features/project/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -23,3 +23,7 @@ Feature: Project Browse commits
Scenario: I browse commits for a specific path
Given I visit my project's commits page for a specific path
Then I see breadcrumb links
+
+ Scenario: I browse commits stats
+ Given I visit my project's commits stats page
+ Then I see commits stats
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index 008c1451455..99c48738876 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -32,7 +32,7 @@ class Dashboard < Spinach::FeatureSteps
end
Given 'user with name "John Doe" joined project "Shop"' do
- user = create :user, {name: "John Doe"}
+ user = create(:user, {name: "John Doe"})
project = Project.find_by_name "Shop"
Event.create(
project: project,
@@ -65,9 +65,9 @@ class Dashboard < Spinach::FeatureSteps
end
And 'I have group with projects' do
- @group = create :group
- @project = create :project, group: @group
- @event = create :closed_issue_event, project: @project
+ @group = create(:group)
+ @project = create(:project, group: @group)
+ @event = create(:closed_issue_event, project: @project)
@project.add_access current_user, :admin
end
diff --git a/features/steps/dashboard/dashboard_search.rb b/features/steps/dashboard/dashboard_search.rb
index 53d74bf3ab7..a34c14d0c5f 100644
--- a/features/steps/dashboard/dashboard_search.rb
+++ b/features/steps/dashboard/dashboard_search.rb
@@ -12,7 +12,7 @@ class DashboardSearch < Spinach::FeatureSteps
end
And 'I own project "Shop"' do
- @project = create :project, name: "Shop"
+ @project = create(:project, :name => "Shop")
@project.add_access(@user, :admin)
end
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index 51581a1ec7b..4de260ec33e 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -9,9 +9,9 @@ class Groups < Spinach::FeatureSteps
end
And 'I have group with projects' do
- @group = Factory :group
- @project = Factory :project, group: @group
- @event = Factory :closed_issue_event, project: @project
+ @group = create(:group)
+ @project = create(:project, group: @group)
+ @event = create(:closed_issue_event, project: @project)
@project.add_access current_user, :admin
end
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index efab1010481..151182f687b 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -53,7 +53,7 @@ class Profile < Spinach::FeatureSteps
end
Given 'I have activity' do
- Factory :closed_issue_event, author: current_user
+ create(:closed_issue_event, author: current_user)
end
Then 'I should see my activity' do
diff --git a/features/steps/profile/profile_ssh_keys.rb b/features/steps/profile/profile_ssh_keys.rb
index 535c3862860..8ae1fa91025 100644
--- a/features/steps/profile/profile_ssh_keys.rb
+++ b/features/steps/profile/profile_ssh_keys.rb
@@ -43,6 +43,6 @@ class ProfileSshKeys < Spinach::FeatureSteps
end
And 'I have ssh key "ssh-rsa Work"' do
- Factory :key, :user => @user, :title => "ssh-rsa Work", :key => "jfKLJDFKSFJSHFJssh-rsa Work"
+ create(:key, :user => @user, :title => "ssh-rsa Work", :key => "jfKLJDFKSFJSHFJssh-rsa Work")
end
end
diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb
index 036b6297337..6bf164e2c8f 100644
--- a/features/steps/project/project_browse_commits.rb
+++ b/features/steps/project/project_browse_commits.rb
@@ -51,4 +51,11 @@ class ProjectBrowseCommits < Spinach::FeatureSteps
find('ul.breadcrumb li:first a')['href'].should match(/#{@project.path}\/commits\/master\z/)
find('ul.breadcrumb li:last a')['href'].should match(%r{master/app/models/project\.rb\z})
end
+
+ Then 'I see commits stats' do
+ page.should have_content 'Stats'
+ page.should have_content 'Committers'
+ page.should have_content 'Total commits'
+ page.should have_content 'Authors'
+ end
end
diff --git a/features/steps/project/project_hooks.rb b/features/steps/project/project_hooks.rb
index 1786fe5bc05..36555fb8e8c 100644
--- a/features/steps/project/project_hooks.rb
+++ b/features/steps/project/project_hooks.rb
@@ -6,7 +6,7 @@ class ProjectHooks < Spinach::FeatureSteps
include RSpec::Mocks::ExampleMethods
Given 'project has hook' do
- @hook = Factory :project_hook, project: current_project
+ @hook = create(:project_hook, project: current_project)
end
Then 'I should see project hook' do
diff --git a/features/steps/project/project_issues.rb b/features/steps/project/project_issues.rb
index 64af24490aa..88bfac638d0 100644
--- a/features/steps/project/project_issues.rb
+++ b/features/steps/project/project_issues.rb
@@ -79,16 +79,16 @@ class ProjectIssues < Spinach::FeatureSteps
Given 'project "Shop" has milestone "v2.2"' do
project = Project.find_by_name("Shop")
- milestone = Factory :milestone, :title => "v2.2", :project => project
+ milestone = create(:milestone, :title => "v2.2", :project => project)
- 3.times { Factory :issue, :project => project, :milestone => milestone }
+ 3.times { create(:issue, :project => project, :milestone => milestone) }
end
And 'project "Shop" has milestone "v3.0"' do
project = Project.find_by_name("Shop")
- milestone = Factory :milestone, :title => "v3.0", :project => project
+ milestone = create(:milestone, :title => "v3.0", :project => project)
- 3.times { Factory :issue, :project => project, :milestone => milestone }
+ 3.times { create(:issue, :project => project, :milestone => milestone) }
end
When 'I select milestone "v3.0"' do
@@ -96,8 +96,7 @@ class ProjectIssues < Spinach::FeatureSteps
end
Then 'I should see selected milestone with title "v3.0"' do
- issues_milestone_selector = "#issue_milestone_id_chzn/a"
- wait_until { page.has_content?("Details") }
+ issues_milestone_selector = "#milestone_id_chzn > a"
page.find(issues_milestone_selector).should have_content("v3.0")
end
@@ -108,8 +107,7 @@ class ProjectIssues < Spinach::FeatureSteps
end
Then 'I should see first assignee from "Shop" as selected assignee' do
- issues_assignee_selector = "#issue_assignee_id_chzn/a"
- wait_until { page.has_content?("Details") }
+ issues_assignee_selector = "#assignee_id_chzn > a"
project = Project.find_by_name "Shop"
assignee_name = project.users.first.name
page.find(issues_assignee_selector).should have_content(assignee_name)
@@ -117,18 +115,18 @@ class ProjectIssues < Spinach::FeatureSteps
And 'project "Shop" have "Release 0.4" open issue' do
project = Project.find_by_name("Shop")
- Factory.create(:issue,
- :title => "Release 0.4",
- :project => project,
- :author => project.users.first)
+ create(:issue,
+ :title => "Release 0.4",
+ :project => project,
+ :author => project.users.first)
end
And 'project "Shop" have "Release 0.3" closed issue' do
project = Project.find_by_name("Shop")
- Factory.create(:issue,
- :title => "Release 0.3",
- :project => project,
- :author => project.users.first,
- :closed => true)
+ create(:issue,
+ :title => "Release 0.3",
+ :project => project,
+ :author => project.users.first,
+ :closed => true)
end
end
diff --git a/features/steps/project/project_labels.rb b/features/steps/project/project_labels.rb
index 1a347bf358f..915190f3dae 100644
--- a/features/steps/project/project_labels.rb
+++ b/features/steps/project/project_labels.rb
@@ -18,7 +18,7 @@ class ProjectLabels < Spinach::FeatureSteps
And 'project "Shop" have issues tags: "bug", "feature"' do
project = Project.find_by_name("Shop")
['bug', 'feature'].each do |label|
- Factory :issue, project: project, label_list: label
+ create(:issue, project: project, label_list: label)
end
end
end
diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb
index 80e83906c72..d153ad28d2b 100644
--- a/features/steps/project/project_merge_requests.rb
+++ b/features/steps/project/project_merge_requests.rb
@@ -63,18 +63,18 @@ class ProjectMergeRequests < Spinach::FeatureSteps
And 'project "Shop" have "Bug NS-04" open merge request' do
project = Project.find_by_name("Shop")
- Factory.create(:merge_request,
- :title => "Bug NS-04",
- :project => project,
- :author => project.users.first)
+ create(:merge_request,
+ :title => "Bug NS-04",
+ :project => project,
+ :author => project.users.first)
end
And 'project "Shop" have "Feature NS-03" closed merge request' do
project = Project.find_by_name("Shop")
- Factory.create(:merge_request,
- :title => "Feature NS-03",
- :project => project,
- :author => project.users.first,
- :closed => true)
+ create(:merge_request,
+ :title => "Feature NS-03",
+ :project => project,
+ :author => project.users.first,
+ :closed => true)
end
end
diff --git a/features/steps/project/project_milestones.rb b/features/steps/project/project_milestones.rb
index 4d689c95d25..1c9ad6da651 100644
--- a/features/steps/project/project_milestones.rb
+++ b/features/steps/project/project_milestones.rb
@@ -32,9 +32,9 @@ class ProjectMilestones < Spinach::FeatureSteps
And 'project "Shop" has milestone "v2.2"' do
project = Project.find_by_name("Shop")
- milestone = Factory :milestone, :title => "v2.2", :project => project
+ milestone = create(:milestone, :title => "v2.2", :project => project)
- 3.times { Factory :issue, :project => project, :milestone => milestone }
+ 3.times { create(:issue, :project => project, :milestone => milestone) }
end
Given 'the milestone has open and closed issues' do
diff --git a/features/steps/project/project_team_management.rb b/features/steps/project/project_team_management.rb
index 5c3a9b31129..6bde0b64dfa 100644
--- a/features/steps/project/project_team_management.rb
+++ b/features/steps/project/project_team_management.rb
@@ -74,11 +74,11 @@ class ProjectTeamManagement < Spinach::FeatureSteps
end
And 'gitlab user "Mike"' do
- Factory :user, :name => "Mike"
+ create(:user, :name => "Mike")
end
And 'gitlab user "Sam"' do
- Factory :user, :name => "Sam"
+ create(:user, :name => "Sam")
end
And '"Sam" is "Shop" developer' do
@@ -88,7 +88,7 @@ class ProjectTeamManagement < Spinach::FeatureSteps
end
Given 'I own project "Website"' do
- @project = Factory :project, :name => "Website"
+ @project = create(:project, :name => "Website")
@project.add_access(@user, :admin)
end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index e24555543ee..33a94027472 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -125,6 +125,10 @@ module SharedPaths
visit project_commits_path(@project, @project.root_ref + "/app/models/project.rb", {limit: 5})
end
+ Given 'I visit my project\'s commits stats page' do
+ visit stats_project_repository_path(@project)
+ end
+
Given "I visit my project's network page" do
# Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650)
Gitlab::Graph::JsonBuilder.stub(max_count: 10)
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
index ae871d63ed5..dfc8ce9d99c 100644
--- a/features/steps/shared/project.rb
+++ b/features/steps/shared/project.rb
@@ -9,7 +9,7 @@ module SharedProject
# Create a specific project called "Shop"
And 'I own project "Shop"' do
- @project = Factory :project, :name => "Shop"
+ @project = create(:project, :name => "Shop")
@project.add_access(@user, :admin)
end
diff --git a/features/support/env.rb b/features/support/env.rb
index 6d49c25a8ba..1a72d765197 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -11,14 +11,33 @@ end
Dir["#{Rails.root}/features/steps/shared/*.rb"].each {|file| require file}
+#
+# Stub gitolite
+#
include GitoliteStub
WebMock.allow_net_connect!
-Capybara.javascript_driver = :webkit
+
+#
+# JS driver
+#
+require 'capybara/poltergeist'
+Capybara.javascript_driver = :poltergeist
+Spinach.hooks.on_tag("javascript") do
+ ::Capybara.current_driver = ::Capybara.javascript_driver
+ ::Capybara.default_wait_time = 5
+end
+
DatabaseCleaner.strategy = :truncation
-Spinach.hooks.before_scenario { DatabaseCleaner.start }
-Spinach.hooks.after_scenario { DatabaseCleaner.clean }
+
+Spinach.hooks.before_scenario do
+ DatabaseCleaner.start
+end
+
+Spinach.hooks.after_scenario do
+ DatabaseCleaner.clean
+end
Spinach.hooks.before_run do
RSpec::Mocks::setup self
diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
index 1bef19a2a79..7ae34de66bc 100644
--- a/lib/gitlab/backend/gitolite_config.rb
+++ b/lib/gitlab/backend/gitolite_config.rb
@@ -194,8 +194,10 @@ module Gitlab
def push tmp_dir
Dir.chdir(File.join(tmp_dir, "gitolite"))
- system('git add -A')
- system('git commit -am "GitLab"')
+ raise "Git add failed." unless system('git add -A')
+ system('git commit -m "GitLab"') # git commit returns 0 on success, and 1 if there is nothing to commit
+ raise "Git commit failed." unless [0,1].include? $?.exitstatus
+
if system('git push')
Dir.chdir(Rails.root)
else
diff --git a/lib/gitlab/git_stats.rb b/lib/gitlab/git_stats.rb
new file mode 100644
index 00000000000..855bffb5dde
--- /dev/null
+++ b/lib/gitlab/git_stats.rb
@@ -0,0 +1,73 @@
+module Gitlab
+ class GitStats
+ attr_accessor :repo, :ref
+
+ def initialize repo, ref
+ @repo, @ref = repo, ref
+ end
+
+ def authors
+ @authors ||= collect_authors
+ end
+
+ def commits_count
+ @commits_count ||= repo.commit_count(ref)
+ end
+
+ def files_count
+ args = [ref, '-r', '--name-only' ]
+ repo.git.run(nil, 'ls-tree', nil, {}, args).split("\n").count
+ end
+
+ def authors_count
+ authors.size
+ end
+
+ def graph
+ @graph ||= build_graph
+ end
+
+ protected
+
+ def collect_authors
+ shortlog = repo.git.shortlog({e: true, s: true }, ref)
+
+ authors = []
+
+ lines = shortlog.split("\n")
+
+ lines.each do |line|
+ data = line.split("\t")
+ commits = data.first
+ author = Grit::Actor.from_string(data.last)
+
+ authors << OpenStruct.new(
+ name: author.name,
+ email: author.email,
+ commits: commits.to_i
+ )
+ end
+
+ authors.sort_by(&:commits).reverse
+ end
+
+ def build_graph n = 4
+ from, to = (Date.today - n.weeks), Date.today
+ args = ['--all', "--since=#{from.to_s(:date)}", '--format=%ad' ]
+ rev_list = repo.git.run(nil, 'rev-list', nil, {}, args).split("\n")
+
+ commits_dates = rev_list.values_at(* rev_list.each_index.select {|i| i.odd?})
+ commits_dates = commits_dates.map { |date_str| Time.parse(date_str).to_date.to_s(:date) }
+
+ commits_per_day = from.upto(to).map do |day|
+ commits_dates.count(day.to_date.to_s(:date))
+ end
+
+ OpenStruct.new(
+ labels: from.upto(to).map { |day| day.stamp('Aug 23') },
+ commits: commits_per_day,
+ weeks: n
+ )
+ end
+ end
+end
diff --git a/lib/gitlab/seeder.rb b/lib/gitlab/seeder.rb
new file mode 100644
index 00000000000..3aa3b2ba1e9
--- /dev/null
+++ b/lib/gitlab/seeder.rb
@@ -0,0 +1,10 @@
+module Gitlab
+ class Seeder
+ def self.quiet
+ SeedFu.quiet = true
+ yield
+ SeedFu.quiet = false
+ puts "\nOK".green
+ end
+ end
+end
diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb
index 30a807145ea..48b4da9d339 100644
--- a/lib/redcarpet/render/gitlab_html.rb
+++ b/lib/redcarpet/render/gitlab_html.rb
@@ -10,10 +10,12 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
end
def block_code(code, language)
+ options = { options: {encoding: 'utf-8'} }
+
if Pygments::Lexer.find(language)
- Pygments.highlight(code, lexer: language, options: {encoding: 'utf-8'})
+ Pygments.highlight(code, options.merge(lexer: language.downcase))
else
- Pygments.highlight(code, options: {encoding: 'utf-8'})
+ Pygments.highlight(code, options)
end
end
diff --git a/lib/tasks/gitlab/status.rake b/lib/tasks/gitlab/status.rake
index 3878823cc94..508c41a23a3 100644
--- a/lib/tasks/gitlab/status.rake
+++ b/lib/tasks/gitlab/status.rake
@@ -37,9 +37,10 @@ namespace :gitlab do
return
end
+ FileUtils.rm_rf("/tmp/gitolite_gitlab_test")
begin
- `git clone #{Gitlab.config.gitolite_admin_uri} /tmp/gitolite_gitlab_test`
- FileUtils.rm_rf("/tmp/gitolite_gitlab_test")
+ `git clone -q #{Gitlab.config.gitolite_admin_uri} /tmp/gitolite_gitlab_test`
+ raise unless $?.success?
print "Can clone gitolite-admin?............"
puts "YES".green
rescue
@@ -48,6 +49,21 @@ namespace :gitlab do
return
end
+ begin
+ Dir.chdir("/tmp/gitolite_gitlab_test") do
+ `touch blah && git add blah && git commit -qm blah -- blah`
+ raise unless $?.success?
+ end
+ print "Can git commit?............"
+ puts "YES".green
+ rescue
+ print "Can git commit?............"
+ puts "NO".red
+ return
+ ensure
+ FileUtils.rm_rf("/tmp/gitolite_gitlab_test")
+ end
+
print "UMASK for .gitolite.rc is 0007? ............"
if open(File.absolute_path("#{git_base_path}/../.gitolite.rc")).grep(/UMASK([ \t]*)=([ \t>]*)0007/).any?
puts "YES".green
diff --git a/spec/factories.rb b/spec/factories.rb
index 0258f8920e9..7b2a2efab23 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -1,21 +1,3 @@
-# Backwards compatibility with the old method
-def Factory(type, *args)
- FactoryGirl.create(type, *args)
-end
-
-module Factory
- def self.create(type, *args)
- FactoryGirl.create(type, *args)
- end
-
- def self.new(type, *args)
- FactoryGirl.build(type, *args)
- end
- def self.attributes(type, *args)
- FactoryGirl.attributes_for(type, *args)
- end
-end
-
FactoryGirl.define do
sequence :sentence, aliases: [:title, :content] do
Faker::Lorem.sentence
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 874864a3894..b6b1769fc80 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -4,8 +4,8 @@ describe Notify do
include EmailSpec::Helpers
include EmailSpec::Matchers
- let(:recipient) { Factory.create(:user, email: 'recipient@example.com') }
- let(:project) { Factory.create(:project) }
+ let(:recipient) { create(:user, email: 'recipient@example.com') }
+ let(:project) { create(:project) }
shared_examples 'a multiple recipients email' do
it 'is sent to the given recipient' do
@@ -15,7 +15,7 @@ describe Notify do
describe 'for new users, the email' do
let(:example_site_path) { root_path }
- let(:new_user) { Factory.create(:user, email: 'newguy@example.com') }
+ let(:new_user) { create(:user, email: 'newguy@example.com') }
subject { Notify.new_user_email(new_user.id, new_user.password) }
@@ -42,8 +42,8 @@ describe Notify do
context 'for a project' do
describe 'items that are assignable, the email' do
- let(:assignee) { Factory.create(:user, email: 'assignee@example.com') }
- let(:previous_assignee) { Factory.create(:user, name: 'Previous Assignee') }
+ let(:assignee) { create(:user, email: 'assignee@example.com') }
+ let(:previous_assignee) { create(:user, name: 'Previous Assignee') }
shared_examples 'an assignee email' do
it 'is sent to the assignee' do
@@ -52,7 +52,7 @@ describe Notify do
end
context 'for issues' do
- let(:issue) { Factory.create(:issue, assignee: assignee, project: project ) }
+ let(:issue) { create(:issue, assignee: assignee, project: project ) }
describe 'that are new' do
subject { Notify.new_issue_email(issue.id) }
@@ -93,10 +93,10 @@ describe Notify do
end
describe 'status changed' do
- let(:current_user) { Factory.create :user, email: "current@email.com" }
+ let(:current_user) { create(:user, email: "current@email.com") }
let(:status) { 'closed' }
subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) }
-
+
it 'has the correct subject' do
should have_subject /changed issue ##{issue.id} \| #{issue.title}/i
end
@@ -117,7 +117,7 @@ describe Notify do
end
context 'for merge requests' do
- let(:merge_request) { Factory.create(:merge_request, assignee: assignee, project: project) }
+ let(:merge_request) { create(:merge_request, assignee: assignee, project: project) }
describe 'that are new' do
subject { Notify.new_merge_request_email(merge_request.id) }
@@ -169,13 +169,13 @@ describe Notify do
end
describe 'project access changed' do
- let(:project) { Factory.create(:project,
- path: "Fuu",
- code: "Fuu") }
- let(:user) { Factory.create :user }
- let(:users_project) { Factory.create(:users_project,
- project: project,
- user: user) }
+ let(:project) { create(:project,
+ path: "Fuu",
+ code: "Fuu") }
+ let(:user) { create(:user) }
+ let(:users_project) { create(:users_project,
+ project: project,
+ user: user) }
subject { Notify.project_access_granted_email(users_project.id) }
it 'has the correct subject' do
should have_subject /access to project was granted/
@@ -189,8 +189,8 @@ describe Notify do
end
context 'items that are noteable, the email for a note' do
- let(:note_author) { Factory.create(:user, name: 'author_name') }
- let(:note) { Factory.create(:note, project: project, author: note_author) }
+ let(:note_author) { create(:user, name: 'author_name') }
+ let(:note) { create(:note, project: project, author: note_author) }
before :each do
Note.stub(:find).with(note.id).and_return(note)
@@ -251,7 +251,7 @@ describe Notify do
end
describe 'on a merge request' do
- let(:merge_request) { Factory.create(:merge_request, project: project) }
+ let(:merge_request) { create(:merge_request, project: project) }
let(:note_on_merge_request_path) { project_merge_request_path(project, merge_request, anchor: "note_#{note.id}") }
before(:each) { note.stub(:noteable).and_return(merge_request) }
@@ -269,7 +269,7 @@ describe Notify do
end
describe 'on an issue' do
- let(:issue) { Factory.create(:issue, project: project) }
+ let(:issue) { create(:issue, project: project) }
let(:note_on_issue_path) { project_issue_path(project, issue, anchor: "note_#{note.id}") }
before(:each) { note.stub(:noteable).and_return(issue) }
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 77b49246c46..d68ebb8614b 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -32,7 +32,7 @@ describe Event do
describe "Push event" do
before do
- project = Factory :project
+ project = create(:project)
@user = project.owner
data = {
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 7c98b9ea58d..9c69f8689c8 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -30,7 +30,6 @@ describe Issue do
describe "Validation" do
it { should ensure_length_of(:description).is_within(0..2000) }
- it { should ensure_inclusion_of(:closed).in_array([true, false]) }
end
describe 'modules' do
@@ -38,11 +37,11 @@ describe Issue do
it { should include_module(Votes) }
end
- subject { Factory.create(:issue) }
+ subject { create(:issue) }
describe '#is_being_reassigned?' do
it 'returns true if the issue assignee has changed' do
- subject.assignee = Factory(:user)
+ subject.assignee = create(:user)
subject.is_being_reassigned?.should be_true
end
it 'returns false if the issue assignee has not changed' do
@@ -56,7 +55,7 @@ describe Issue do
subject.is_being_closed?.should be_true
end
it 'returns false if the closed attribute has changed and is now false' do
- issue = Factory.create(:closed_issue)
+ issue = create(:closed_issue)
issue.closed = false
issue.is_being_closed?.should be_false
end
@@ -68,7 +67,7 @@ describe Issue do
describe '#is_being_reopened?' do
it 'returns true if the closed attribute has changed and is now false' do
- issue = Factory.create(:closed_issue)
+ issue = create(:closed_issue)
issue.closed = false
issue.is_being_reopened?.should be_true
end
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index d3231af88bc..80dfff08397 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -53,7 +53,7 @@ describe Key do
end
context "as a personal key" do
- let(:user) { Factory.create(:user) }
+ let(:user) { create(:user) }
it "accepts the key once" do
build(:key, user: user).should be_valid
@@ -67,7 +67,7 @@ describe Key do
end
context "validate it is a fingerprintable key" do
- let(:user) { Factory.create(:user) }
+ let(:user) { create(:user) }
it "accepts the fingerprintable key" do
build(:key, user: user).should be_valid
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 0faca7668dd..4bf42ef99aa 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -38,12 +38,12 @@ describe MergeRequest do
end
describe "#mr_and_commit_notes" do
- let!(:merge_request) { Factory.create(:merge_request) }
+ let!(:merge_request) { create(:merge_request) }
before do
merge_request.stub(:commits) { [merge_request.project.commit] }
- Factory.create(:note, noteable: merge_request.commits.first)
- Factory.create(:note, noteable: merge_request)
+ create(:note, noteable: merge_request.commits.first)
+ create(:note, noteable: merge_request)
end
it "should include notes for commits" do
@@ -52,11 +52,11 @@ describe MergeRequest do
end
end
- subject { Factory.create(:merge_request) }
+ subject { create(:merge_request) }
describe '#is_being_reassigned?' do
it 'returns true if the merge_request assignee has changed' do
- subject.assignee = Factory(:user)
+ subject.assignee = create(:user)
subject.is_being_reassigned?.should be_true
end
it 'returns false if the merge request assignee has not changed' do
@@ -70,7 +70,7 @@ describe MergeRequest do
subject.is_being_closed?.should be_true
end
it 'returns false if the closed attribute has changed and is now false' do
- merge_request = Factory.create(:closed_merge_request)
+ merge_request = create(:closed_merge_request)
merge_request.closed = false
merge_request.is_being_closed?.should be_false
end
@@ -82,7 +82,7 @@ describe MergeRequest do
describe '#is_being_reopened?' do
it 'returns true if the closed attribute has changed and is now false' do
- merge_request = Factory.create(:closed_merge_request)
+ merge_request = create(:closed_merge_request)
merge_request.closed = false
merge_request.is_being_reopened?.should be_true
end
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 1aba20c651d..0e5cf7dd665 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -30,8 +30,8 @@ describe Milestone do
it { should ensure_inclusion_of(:closed).in_array([true, false]) }
end
- let(:milestone) { Factory :milestone }
- let(:issue) { Factory :issue }
+ let(:milestone) { create(:milestone) }
+ let(:issue) { create(:issue) }
describe "#percent_complete" do
it "should not count open issues" do
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 514b6202b74..d739053748f 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -40,10 +40,10 @@ describe Note do
end
describe "Voting score" do
- let(:project) { Factory(:project) }
+ let(:project) { create(:project) }
it "recognizes a neutral note" do
- note = Factory(:note, note: "This is not a +1 note")
+ note = create(:note, note: "This is not a +1 note")
note.should_not be_upvote
note.should_not be_downvote
end
@@ -55,7 +55,7 @@ describe Note do
end
it "recognizes a +1 note" do
- note = Factory(:note, note: "+1 for this")
+ note = create(:note, note: "+1 for this")
note.should be_upvote
end
@@ -65,7 +65,7 @@ describe Note do
end
it "recognizes a -1 note" do
- note = Factory(:note, note: "-1 for this")
+ note = create(:note, note: "-1 for this")
note.should be_downvote
end
@@ -80,9 +80,9 @@ describe Note do
describe "Commit notes" do
before do
- @note = Factory :note,
- noteable_id: commit.id,
- noteable_type: "Commit"
+ @note = create(:note,
+ noteable_id: commit.id,
+ noteable_type: "Commit")
end
it "should be accessible through #noteable" do
@@ -103,10 +103,10 @@ describe Note do
describe "Pre-line commit notes" do
before do
- @note = Factory :note,
- noteable_id: commit.id,
- noteable_type: "Commit",
- line_code: "0_16_1"
+ @note = create(:note,
+ noteable_id: commit.id,
+ noteable_type: "Commit",
+ line_code: "0_16_1")
end
it "should save a valid note" do
@@ -120,9 +120,9 @@ describe Note do
end
describe '#create_status_change_note' do
- let(:project) { Factory.create(:project) }
- let(:thing) { Factory.create(:issue, project: project) }
- let(:author) { Factory(:user) }
+ let(:project) { create(:project) }
+ let(:thing) { create(:issue, project: project) }
+ let(:author) { create(:user) }
let(:status) { 'new_status' }
subject { Note.create_status_change_note(thing, author, status) }
@@ -141,10 +141,10 @@ describe Note do
describe :authorization do
before do
@p1 = create(:project)
- @p2 = Factory :project
- @u1 = Factory :user
- @u2 = Factory :user
- @u3 = Factory :user
+ @p2 = create(:project)
+ @u1 = create(:user)
+ @u2 = create(:user)
+ @u3 = create(:user)
@abilities = Six.new
@abilities << Ability
end
diff --git a/spec/models/project_hooks_spec.rb b/spec/models/project_hooks_spec.rb
index 129e3d61030..ee441ec4ec5 100644
--- a/spec/models/project_hooks_spec.rb
+++ b/spec/models/project_hooks_spec.rb
@@ -1,15 +1,15 @@
require 'spec_helper'
describe Project, "Hooks" do
- let(:project) { Factory :project }
- before do
- @key = Factory :key, user: project.owner
+ let(:project) { create(:project) }
+ before do
+ @key = create(:key, user: project.owner)
@user = @key.user
@key_id = @key.identifier
end
- describe "Post Receive Event" do
- it "should create push event" do
+ describe "Post Receive Event" do
+ it "should create push event" do
oldrev, newrev, ref = '00000000000000000000000000000000', 'newrev', 'refs/heads/master'
project.observe_push(oldrev, newrev, ref, @user)
event = Event.last
@@ -32,8 +32,8 @@ describe Project, "Hooks" do
context "with web hooks" do
before do
- @project_hook = Factory(:project_hook)
- @project_hook_2 = Factory(:project_hook)
+ @project_hook = create(:project_hook)
+ @project_hook_2 = create(:project_hook)
project.hooks << [@project_hook, @project_hook_2]
end
@@ -47,7 +47,7 @@ describe Project, "Hooks" do
context "does not execute web hooks" do
before do
- @project_hook = Factory(:project_hook)
+ @project_hook = create(:project_hook)
project.hooks << [@project_hook]
end
diff --git a/spec/models/project_security_spec.rb b/spec/models/project_security_spec.rb
index baf6d4b68ea..60f8d45c9c8 100644
--- a/spec/models/project_security_spec.rb
+++ b/spec/models/project_security_spec.rb
@@ -3,9 +3,9 @@ require 'spec_helper'
describe Project do
describe :authorization do
before do
- @p1 = Factory :project
- @u1 = Factory :user
- @u2 = Factory :user
+ @p1 = create(:project)
+ @u1 = create(:user)
+ @u2 = create(:user)
@abilities = Six.new
@abilities << Ability
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 6fe46446262..1cf4f586192 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -157,7 +157,7 @@ describe Project do
describe :valid_repo? do
it "should be valid repo" do
- project = Factory :project
+ project = create(:project)
project.valid_repo?.should be_true
end
@@ -168,7 +168,7 @@ describe Project do
end
describe "last_activity methods" do
- let(:project) { Factory :project }
+ let(:project) { create(:project) }
let(:last_event) { double(created_at: Time.now) }
describe "last_activity" do
@@ -191,7 +191,7 @@ describe Project do
end
describe "fresh commits" do
- let(:project) { Factory :project }
+ let(:project) { create(:project) }
it { project.fresh_commits(3).count.should == 3 }
it { project.fresh_commits.first.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" }
@@ -199,7 +199,7 @@ describe Project do
end
describe "commits_between" do
- let(:project) { Factory :project }
+ let(:project) { create(:project) }
subject do
commits = project.commits_between("3a4b4fb4cde7809f033822a171b9feae19d41fff",
@@ -213,7 +213,7 @@ describe Project do
end
describe "Git methods" do
- let(:project) { Factory :project }
+ let(:project) { create(:project) }
describe :repo do
it "should return valid repo" do
@@ -270,14 +270,14 @@ describe Project do
end
describe :update_merge_requests do
- let(:project) { Factory :project }
+ let(:project) { create(:project) }
before do
- @merge_request = Factory :merge_request,
- project: project,
- merged: false,
- closed: false
- @key = Factory :key, user_id: project.owner.id
+ @merge_request = create(:merge_request,
+ project: project,
+ merged: false,
+ closed: false)
+ @key = create(:key, user_id: project.owner.id)
end
it "should close merge request if last commit from source branch was pushed to target branch" do
diff --git a/spec/models/system_hook_spec.rb b/spec/models/system_hook_spec.rb
index b5d338a8c55..5f9239119b0 100644
--- a/spec/models/system_hook_spec.rb
+++ b/spec/models/system_hook_spec.rb
@@ -17,19 +17,19 @@ describe SystemHook do
before(:each) { ActiveRecord::Base.observers.enable(:all) }
before(:each) do
- @system_hook = Factory :system_hook
+ @system_hook = create(:system_hook)
WebMock.stub_request(:post, @system_hook.url)
end
it "project_create hook" do
with_resque do
- project = Factory :project
+ project = create(:project)
end
WebMock.should have_requested(:post, @system_hook.url).with(body: /project_create/).once
end
it "project_destroy hook" do
- project = Factory :project
+ project = create(:project)
with_resque do
project.destroy
end
@@ -38,13 +38,13 @@ describe SystemHook do
it "user_create hook" do
with_resque do
- Factory :user
+ create(:user)
end
WebMock.should have_requested(:post, @system_hook.url).with(body: /user_create/).once
end
it "user_destroy hook" do
- user = Factory :user
+ user = create(:user)
with_resque do
user.destroy
end
@@ -52,8 +52,8 @@ describe SystemHook do
end
it "project_create hook" do
- user = Factory :user
- project = Factory :project
+ user = create(:user)
+ project = create(:project)
with_resque do
project.users << user
end
@@ -61,8 +61,8 @@ describe SystemHook do
end
it "project_destroy hook" do
- user = Factory :user
- project = Factory :project
+ user = create(:user)
+ project = create(:project)
project.users << user
with_resque do
project.users_projects.clear
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 5f41fb05ed1..b9654d7002c 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -108,7 +108,7 @@ describe User do
describe 'authentication token' do
it "should have authentication token" do
- user = Factory(:user)
+ user = create(:user)
user.authentication_token.should_not be_blank
end
end
diff --git a/spec/models/web_hook_spec.rb b/spec/models/web_hook_spec.rb
index d71fec811f0..8f8decb81c6 100644
--- a/spec/models/web_hook_spec.rb
+++ b/spec/models/web_hook_spec.rb
@@ -39,8 +39,8 @@ describe ProjectHook do
describe "execute" do
before(:each) do
- @project_hook = Factory :project_hook
- @project = Factory :project
+ @project_hook = create(:project_hook)
+ @project = create(:project)
@project.hooks << [@project_hook]
@data = { before: 'oldrev', after: 'newrev', ref: 'ref'}
diff --git a/spec/observers/activity_observer_spec.rb b/spec/observers/activity_observer_spec.rb
index 0db4a9985be..0eec41f44e9 100644
--- a/spec/observers/activity_observer_spec.rb
+++ b/spec/observers/activity_observer_spec.rb
@@ -1,17 +1,17 @@
require 'spec_helper'
describe ActivityObserver do
- let(:project) { Factory :project }
+ let(:project) { create(:project) }
def self.it_should_be_valid_event
it { @event.should_not be_nil }
it { @event.project.should == project }
end
- describe "Merge Request created" do
+ describe "Merge Request created" do
before do
MergeRequest.observers.enable :activity_observer do
- @merge_request = Factory :merge_request, project: project
+ @merge_request = create(:merge_request, project: project)
@event = Event.last
end
end
@@ -21,10 +21,10 @@ describe ActivityObserver do
it { @event.target.should == @merge_request }
end
- describe "Issue created" do
+ describe "Issue created" do
before do
Issue.observers.enable :activity_observer do
- @issue = Factory :issue, project: project
+ @issue = create(:issue, project: project)
@event = Event.last
end
end
@@ -34,10 +34,10 @@ describe ActivityObserver do
it { @event.target.should == @issue }
end
- #describe "Issue commented" do
- #before do
- #@issue = Factory :issue, project: project
- #@note = Factory :note, noteable: @issue, project: project
+ #describe "Issue commented" do
+ #before do
+ #@issue = create(:issue, project: project)
+ #@note = create(:note, noteable: @issue, project: project)
#@event = Event.last
#end
diff --git a/spec/observers/issue_observer_spec.rb b/spec/observers/issue_observer_spec.rb
index b5943f2c539..509c1d02b49 100644
--- a/spec/observers/issue_observer_spec.rb
+++ b/spec/observers/issue_observer_spec.rb
@@ -16,7 +16,7 @@ describe IssueObserver do
subject.should_receive(:after_create)
Issue.observers.enable :issue_observer do
- Factory.create(:issue, project: Factory.create(:project))
+ create(:issue, project: create(:project))
end
end
@@ -43,7 +43,7 @@ describe IssueObserver do
end
it 'is called when an issue is changed' do
- changed = Factory.create(:issue, project: Factory.create(:project))
+ changed = create(:issue, project: create(:project))
subject.should_receive(:after_update)
Issue.observers.enable :issue_observer do
diff --git a/spec/observers/merge_request_observer_spec.rb b/spec/observers/merge_request_observer_spec.rb
index a9ba79271e3..6b15be96630 100644
--- a/spec/observers/merge_request_observer_spec.rb
+++ b/spec/observers/merge_request_observer_spec.rb
@@ -16,7 +16,7 @@ describe MergeRequestObserver do
subject.should_receive(:after_create)
MergeRequest.observers.enable :merge_request_observer do
- Factory.create(:merge_request, project: Factory.create(:project))
+ create(:merge_request, project: create(:project))
end
end
@@ -43,7 +43,7 @@ describe MergeRequestObserver do
end
it 'is called when a merge request is changed' do
- changed = Factory.create(:merge_request, project: Factory.create(:project))
+ changed = create(:merge_request, project: create(:project))
subject.should_receive(:after_update)
MergeRequest.observers.enable :merge_request_observer do
diff --git a/spec/observers/note_observer_spec.rb b/spec/observers/note_observer_spec.rb
index 203a58a4950..7dfa9f772e9 100644
--- a/spec/observers/note_observer_spec.rb
+++ b/spec/observers/note_observer_spec.rb
@@ -13,7 +13,7 @@ describe NoteObserver do
subject.should_receive :after_create
Note.observers.enable :note_observer do
- Factory.create(:note)
+ create(:note)
end
end
diff --git a/spec/observers/user_observer_spec.rb b/spec/observers/user_observer_spec.rb
index 0420a250c8a..08254f44026 100644
--- a/spec/observers/user_observer_spec.rb
+++ b/spec/observers/user_observer_spec.rb
@@ -4,7 +4,7 @@ describe UserObserver do
subject { UserObserver.instance }
it 'calls #after_create when new users are created' do
- new_user = Factory.new(:user)
+ new_user = build(:user)
subject.should_receive(:after_create).with(new_user)
User.observers.enable :user_observer do
diff --git a/spec/observers/users_project_observer_spec.rb b/spec/observers/users_project_observer_spec.rb
index a8e0834bc99..cbe42248033 100644
--- a/spec/observers/users_project_observer_spec.rb
+++ b/spec/observers/users_project_observer_spec.rb
@@ -1,13 +1,13 @@
require 'spec_helper'
describe UsersProjectObserver do
- let(:user) { Factory.create :user }
- let(:project) { Factory.create(:project,
- code: "Fuu",
- path: "Fuu" ) }
- let(:users_project) { Factory.create(:users_project,
- project: project,
- user: user )}
+ let(:user) { create(:user) }
+ let(:project) { create(:project,
+ code: "Fuu",
+ path: "Fuu" ) }
+ let(:users_project) { create(:users_project,
+ project: project,
+ user: user )}
subject { UsersProjectObserver.instance }
describe "#after_commit" do
diff --git a/spec/requests/admin/admin_hooks_spec.rb b/spec/requests/admin/admin_hooks_spec.rb
index 2f026aabab8..3f35b2fd37d 100644
--- a/spec/requests/admin/admin_hooks_spec.rb
+++ b/spec/requests/admin/admin_hooks_spec.rb
@@ -2,12 +2,12 @@ require 'spec_helper'
describe "Admin::Hooks" do
before do
- @project = Factory :project,
- name: "LeGiT",
- code: "LGT"
+ @project = create(:project,
+ name: "LeGiT",
+ code: "LGT")
login_as :admin
- @system_hook = Factory :system_hook
+ @system_hook = create(:system_hook)
end
diff --git a/spec/requests/admin/admin_projects_spec.rb b/spec/requests/admin/admin_projects_spec.rb
index 61e66eec08b..43e39d7cbcd 100644
--- a/spec/requests/admin/admin_projects_spec.rb
+++ b/spec/requests/admin/admin_projects_spec.rb
@@ -2,9 +2,9 @@ require 'spec_helper'
describe "Admin::Projects" do
before do
- @project = Factory :project,
- name: "LeGiT",
- code: "LGT"
+ @project = create(:project,
+ name: "LeGiT",
+ code: "LGT")
login_as :admin
end
@@ -104,7 +104,7 @@ describe "Admin::Projects" do
describe "Add new team member" do
before do
- @new_user = Factory :user
+ @new_user = create(:user)
visit admin_project_path(@project)
end
diff --git a/spec/requests/admin/admin_users_spec.rb b/spec/requests/admin/admin_users_spec.rb
index 68358bf0a0f..9f43f07a476 100644
--- a/spec/requests/admin/admin_users_spec.rb
+++ b/spec/requests/admin/admin_users_spec.rb
@@ -76,7 +76,7 @@ describe "Admin::Users" do
describe "GET /admin/users/:id/edit" do
before do
- @simple_user = Factory :user
+ @simple_user = create(:user)
visit admin_users_path
click_link "edit_user_#{@simple_user.id}"
end
@@ -107,13 +107,13 @@ describe "Admin::Users" do
end
end
- describe "Add new project" do
- before do
- @new_project = Factory :project
+ describe "Add new project" do
+ before do
+ @new_project = create(:project)
visit admin_user_path(@user)
end
- it "should create new user" do
+ it "should create new user" do
select @new_project.name, from: "project_ids"
expect { click_button "Add" }.to change { UsersProject.count }.by(1)
page.should have_content @new_project.name
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 442e9c730dc..6ea7e9b5579 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -3,9 +3,9 @@ require 'spec_helper'
describe Gitlab::API do
include ApiHelpers
- let(:user) { Factory :user }
- let!(:project) { Factory :project, owner: user }
- let!(:issue) { Factory :issue, author: user, assignee: user, project: project }
+ let(:user) { create(:user) }
+ let!(:project) { create(:project, owner: user) }
+ let!(:issue) { create(:issue, author: user, assignee: user, project: project) }
before { project.add_access(user, :read) }
describe "GET /issues" do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index e1c7949f70c..e83f24671ed 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -1,11 +1,11 @@
require "spec_helper"
-describe Gitlab::API do
+describe Gitlab::API do
include ApiHelpers
-
- let(:user) { Factory :user }
- let!(:project) { Factory :project, owner: user }
- let!(:merge_request) { Factory :merge_request, author: user, assignee: user, project: project, title: "Test" }
+
+ let(:user) { create(:user ) }
+ let!(:project) { create(:project, owner: user) }
+ let!(:merge_request) { create(:merge_request, author: user, assignee: user, project: project, title: "Test") }
before { project.add_access(user, :read) }
describe "GET /projects/:id/merge_requests" do
@@ -39,7 +39,7 @@ describe Gitlab::API do
post api("/projects/#{project.code}/merge_requests", user),
title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user
response.status.should == 201
- json_response['title'].should == 'Test merge_request'
+ json_response['title'].should == 'Test merge_request'
end
end
@@ -47,7 +47,7 @@ describe Gitlab::API do
it "should return merge_request" do
put api("/projects/#{project.code}/merge_request/#{merge_request.id}", user), title: "New title"
response.status.should == 200
- json_response['title'].should == 'New title'
+ json_response['title'].should == 'New title'
end
end
@@ -55,7 +55,7 @@ describe Gitlab::API do
it "should return comment" do
post api("/projects/#{project.code}/merge_request/#{merge_request.id}/comments", user), note: "My comment"
response.status.should == 201
- json_response['note'].should == 'My comment'
+ json_response['note'].should == 'My comment'
end
end
diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb
index cf5f65f068c..860825ab2db 100644
--- a/spec/requests/api/milestones_spec.rb
+++ b/spec/requests/api/milestones_spec.rb
@@ -3,9 +3,9 @@ require 'spec_helper'
describe Gitlab::API do
include ApiHelpers
- let(:user) { Factory :user }
- let!(:project) { Factory :project, owner: user }
- let!(:milestone) { Factory :milestone, project: project }
+ let(:user) { create(:user) }
+ let!(:project) { create(:project, owner: user) }
+ let!(:milestone) { create(:milestone, project: project) }
before { project.add_access(user, :read) }
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 5f9a587d57a..d24ce43d3f2 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -3,14 +3,14 @@ require 'spec_helper'
describe Gitlab::API do
include ApiHelpers
- let(:user) { Factory :user }
- let(:user2) { Factory.create(:user) }
- let(:user3) { Factory.create(:user) }
- let!(:hook) { Factory :project_hook, project: project, url: "http://example.com" }
- let!(:project) { Factory :project, owner: user }
- let!(:snippet) { Factory :snippet, author: user, project: project, title: 'example' }
- let!(:users_project) { Factory :users_project, user: user, project: project, project_access: UsersProject::MASTER }
- let!(:users_project2) { Factory :users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER }
+ let(:user) { create(:user) }
+ let(:user2) { create(:user) }
+ let(:user3) { create(:user) }
+ let!(:hook) { create(:project_hook, project: project, url: "http://example.com") }
+ let!(:project) { create(:project, owner: user ) }
+ let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') }
+ let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
+ let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) }
before { project.add_access(user, :read) }
describe "GET /projects" do
@@ -52,7 +52,7 @@ describe Gitlab::API do
end
it "should assign attributes to project" do
- project = Factory.attributes(:project, {
+ project = attributes_for(:project, {
path: 'path',
code: 'code',
description: Faker::Lorem.sentence,
diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb
index f251f3921ac..afae8be8cbc 100644
--- a/spec/requests/api/session_spec.rb
+++ b/spec/requests/api/session_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Gitlab::API do
include ApiHelpers
- let(:user) { Factory :user }
+ let(:user) { create(:user) }
describe "POST /session" do
context "when valid password" do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 4c2e6adaf7f..4cfb4884e7c 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -3,9 +3,9 @@ require 'spec_helper'
describe Gitlab::API do
include ApiHelpers
- let(:user) { Factory :user }
- let(:admin) { Factory :admin }
- let(:key) { Factory :key, user: user }
+ let(:user) { create(:user) }
+ let(:admin) { create(:admin) }
+ let(:key) { create(:key, user: user) }
describe "GET /users" do
context "when unauthenticated" do
@@ -43,12 +43,12 @@ describe Gitlab::API do
it "should create user" do
expect {
- post api("/users", admin), Factory.attributes(:user, projects_limit: 3)
+ post api("/users", admin), attributes_for(:user, projects_limit: 3)
}.to change { User.count }.by(1)
end
it "shouldn't available for non admin users" do
- post api("/users", user), Factory.attributes(:user)
+ post api("/users", user), attributes_for(:user)
response.status.should == 403
end
end
@@ -103,7 +103,7 @@ describe Gitlab::API do
end
it "should create ssh key" do
- key_attrs = Factory.attributes :key
+ key_attrs = attributes_for :key
expect {
post api("/user/keys", user), key_attrs
}.to change{ user.keys.count }.by(1)
diff --git a/spec/requests/atom/dashboard_issues_spec.rb b/spec/requests/atom/dashboard_issues_spec.rb
index 8d1111fc770..8ce64cd4c14 100644
--- a/spec/requests/atom/dashboard_issues_spec.rb
+++ b/spec/requests/atom/dashboard_issues_spec.rb
@@ -2,11 +2,11 @@ require 'spec_helper'
describe "Dashboard Issues Feed" do
describe "GET /issues" do
- let!(:user) { Factory :user }
- let!(:project1) { Factory :project }
- let!(:project2) { Factory :project }
- let!(:issue1) { Factory :issue, author: user, assignee: user, project: project1 }
- let!(:issue2) { Factory :issue, author: user, assignee: user, project: project2 }
+ let!(:user) { create(:user) }
+ let!(:project1) { create(:project) }
+ let!(:project2) { create(:project) }
+ let!(:issue1) { create(:issue, author: user, assignee: user, project: project1) }
+ let!(:issue2) { create(:issue, author: user, assignee: user, project: project2) }
describe "atom feed" do
it "should render atom feed via private token" do
diff --git a/spec/requests/atom/dashboard_spec.rb b/spec/requests/atom/dashboard_spec.rb
index c160d24ac20..6257ad5c895 100644
--- a/spec/requests/atom/dashboard_spec.rb
+++ b/spec/requests/atom/dashboard_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe "Dashboard Feed" do
describe "GET /" do
- let!(:user) { Factory :user }
+ let!(:user) { create(:user) }
context "projects atom feed via private token" do
it "should render projects atom feed" do
diff --git a/spec/requests/atom/issues_spec.rb b/spec/requests/atom/issues_spec.rb
index c8671979870..29f88f3f1c3 100644
--- a/spec/requests/atom/issues_spec.rb
+++ b/spec/requests/atom/issues_spec.rb
@@ -2,9 +2,9 @@ require 'spec_helper'
describe "Issues Feed" do
describe "GET /issues" do
- let!(:user) { Factory :user }
- let!(:project) { Factory :project, owner: user }
- let!(:issue) { Factory :issue, author: user, project: project }
+ let!(:user) { create(:user) }
+ let!(:project) { create(:project, owner: user) }
+ let!(:issue) { create(:issue, author: user, project: project) }
before { project.add_access(user, :read, :write) }
diff --git a/spec/requests/gitlab_flavored_markdown_spec.rb b/spec/requests/gitlab_flavored_markdown_spec.rb
index 014f99ebb0e..aedd435e617 100644
--- a/spec/requests/gitlab_flavored_markdown_spec.rb
+++ b/spec/requests/gitlab_flavored_markdown_spec.rb
@@ -1,11 +1,11 @@
require 'spec_helper'
describe "Gitlab Flavored Markdown" do
- let(:project) { Factory :project }
- let(:issue) { Factory :issue, project: project }
- let(:merge_request) { Factory :merge_request, project: project }
+ let(:project) { create(:project) }
+ let(:issue) { create(:issue, project: project) }
+ let(:merge_request) { create(:merge_request, project: project) }
let(:fred) do
- u = Factory :user, name: "fred"
+ u = create(:user, name: "fred")
project.users << u
u
end
@@ -84,16 +84,16 @@ describe "Gitlab Flavored Markdown" do
describe "for issues" do
before do
- @other_issue = Factory :issue,
+ @other_issue = create(:issue,
+ author: @user,
+ assignee: @user,
+ project: project)
+ @issue = create(:issue,
author: @user,
assignee: @user,
- project: project
- @issue = Factory :issue,
- author: @user,
- assignee: @user,
- project: project,
- title: "fix ##{@other_issue.id}",
- description: "ask @#{fred.name} for details"
+ project: project,
+ title: "fix ##{@other_issue.id}",
+ description: "ask @#{fred.name} for details")
end
it "should render subject in issues#index" do
@@ -118,9 +118,9 @@ describe "Gitlab Flavored Markdown" do
describe "for merge requests" do
before do
- @merge_request = Factory :merge_request,
- project: project,
- title: "fix ##{issue.id}"
+ @merge_request = create(:merge_request,
+ project: project,
+ title: "fix ##{issue.id}")
end
it "should render title in merge_requests#index" do
@@ -139,10 +139,10 @@ describe "Gitlab Flavored Markdown" do
describe "for milestones" do
before do
- @milestone = Factory :milestone,
- project: project,
- title: "fix ##{issue.id}",
- description: "ask @#{fred.name} for details"
+ @milestone = create(:milestone,
+ project: project,
+ title: "fix ##{issue.id}",
+ description: "ask @#{fred.name} for details")
end
it "should render title in milestones#index" do
diff --git a/spec/requests/issues_spec.rb b/spec/requests/issues_spec.rb
index 15ee5d174a0..ff4d4c8b8ae 100644
--- a/spec/requests/issues_spec.rb
+++ b/spec/requests/issues_spec.rb
@@ -1,28 +1,31 @@
require 'spec_helper'
describe "Issues" do
- let(:project) { Factory :project }
+ let(:project) { create(:project) }
before do
login_as :user
- @user2 = Factory :user
+ user2 = create(:user)
project.add_access(@user, :read, :write)
- project.add_access(@user2, :read, :write)
+ project.add_access(user2, :read, :write)
end
describe "Edit issue", js: true do
+ let!(:issue) do
+ create(:issue,
+ author: @user,
+ assignee: @user,
+ project: project)
+ end
+
before do
- @issue = Factory :issue,
- author: @user,
- assignee: @user,
- project: project
visit project_issues_path(project)
click_link "Edit"
end
it "should open new issue popup" do
- page.should have_content("Issue ##{@issue.id}")
+ page.should have_content("Issue ##{issue.id}")
end
describe "fill in" do
@@ -46,19 +49,18 @@ describe "Issues" do
describe "Search issue", js: true do
before do
['foobar', 'foobar2', 'gitlab'].each do |title|
- @issue = Factory :issue,
- author: @user,
- assignee: @user,
- project: project,
- title: title
- @issue.save
+ create(:issue,
+ author: @user,
+ assignee: @user,
+ project: project,
+ title: title)
end
end
it "should be able to search on different statuses" do
- @issue = Issue.first
- @issue.closed = true
- @issue.save
+ issue = Issue.first # with title 'foobar'
+ issue.closed = true
+ issue.save
visit project_issues_path(project)
click_link 'Closed'
@@ -81,8 +83,9 @@ describe "Issues" do
it "should return all results if term has been cleared" do
visit project_issues_path(project)
fill_in "issue_search", with: "foobar"
- # Because fill_in, with: "" triggers nothing we need to trigger a keyup event
- page.execute_script("$('.issue_search').val('').keyup();");
+ # Reset the search field and trigger loading the issues
+ fill_in "issue_search", with: ""
+ page.execute_script("$('#issue_search').keyup();");
page.should have_content 'foobar'
page.should have_content 'foobar2'
@@ -93,19 +96,21 @@ describe "Issues" do
describe "Filter issue" do
before do
['foobar', 'barbaz', 'gitlab'].each do |title|
- @issue = Factory :issue,
- author: @user,
- assignee: @user,
- project: project,
- title: title
+ create(:issue,
+ author: @user,
+ assignee: @user,
+ project: project,
+ title: title)
end
- @issue = Issue.first
- @issue.milestone = Factory(:milestone, project: project)
- @issue.assignee = nil
- @issue.save
+ issue = Issue.first # with title 'foobar'
+ issue.milestone = create(:milestone, project: project)
+ issue.assignee = nil
+ issue.save
end
+ let(:issue) { Issue.first }
+
it "should allow filtering by issues with no specified milestone" do
visit project_issues_path(project, milestone_id: '0')
@@ -115,7 +120,7 @@ describe "Issues" do
end
it "should allow filtering by a specified milestone" do
- visit project_issues_path(project, milestone_id: @issue.milestone.id)
+ visit project_issues_path(project, milestone_id: issue.milestone.id)
page.should have_content 'foobar'
page.should_not have_content 'barbaz'
diff --git a/spec/requests/projects_deploy_keys_spec.rb b/spec/requests/projects_deploy_keys_spec.rb
index df1be79d2f5..35323f556f9 100644
--- a/spec/requests/projects_deploy_keys_spec.rb
+++ b/spec/requests/projects_deploy_keys_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe "Projects", "DeployKeys" do
- let(:project) { Factory :project }
+ let(:project) { create(:project) }
before do
login_as :user
@@ -10,7 +10,7 @@ describe "Projects", "DeployKeys" do
describe "GET /keys" do
before do
- @key = Factory :key, project: project
+ @key = create(:key, project: project)
visit project_deploy_keys_path(project)
end
@@ -57,7 +57,7 @@ describe "Projects", "DeployKeys" do
describe "Show page" do
before do
- @key = Factory :key, project: project
+ @key = create(:key, project: project)
visit project_deploy_key_path(project, @key)
end
diff --git a/spec/requests/projects_spec.rb b/spec/requests/projects_spec.rb
index 92e89a162af..c44bea89f96 100644
--- a/spec/requests/projects_spec.rb
+++ b/spec/requests/projects_spec.rb
@@ -6,7 +6,7 @@ describe "Projects" do
describe 'GET /project/new' do
it "should work autocomplete", :js => true do
visit new_project_path
-
+
fill_in 'project_name', with: 'Awesome'
find("#project_path").value.should == 'awesome'
find("#project_code").value.should == 'awesome'
@@ -15,7 +15,7 @@ describe "Projects" do
describe "GET /projects/show" do
before do
- @project = Factory :project, owner: @user
+ @project = create(:project, owner: @user)
@project.add_access(@user, :read)
visit project_path(@project)
@@ -28,7 +28,7 @@ describe "Projects" do
describe "GET /projects/:id/edit" do
before do
- @project = Factory :project
+ @project = create(:project)
@project.add_access(@user, :admin, :read)
visit edit_project_path(@project)
@@ -47,7 +47,7 @@ describe "Projects" do
describe "PUT /projects/:id" do
before do
- @project = Factory :project, owner: @user
+ @project = create(:project, owner: @user)
@project.add_access(@user, :admin, :read)
visit edit_project_path(@project)
@@ -69,7 +69,7 @@ describe "Projects" do
describe "DELETE /projects/:id" do
before do
- @project = Factory :project
+ @project = create(:project)
@project.add_access(@user, :read, :admin)
visit edit_project_path(@project)
end
diff --git a/spec/requests/search_spec.rb b/spec/requests/search_spec.rb
index 537c4d0c64c..17cc0d39946 100644
--- a/spec/requests/search_spec.rb
+++ b/spec/requests/search_spec.rb
@@ -3,14 +3,14 @@ require 'spec_helper'
describe "Search" do
before do
login_as :user
- @project = Factory :project
+ @project = create(:project)
@project.add_access(@user, :read)
visit search_path
fill_in "search", with: @project.name[0..3]
click_button "Search"
end
- it "should show project in search results" do
+ it "should show project in search results" do
page.should have_content @project.name
end
end
diff --git a/spec/requests/security/profile_access_spec.rb b/spec/requests/security/profile_access_spec.rb
index 69c1c29cf12..8562b8e78af 100644
--- a/spec/requests/security/profile_access_spec.rb
+++ b/spec/requests/security/profile_access_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe "Users Security" do
describe "Project" do
before do
- @u1 = Factory :user
+ @u1 = create(:user)
end
describe "GET /login" do
diff --git a/spec/requests/snippets_spec.rb b/spec/requests/snippets_spec.rb
index 6b993660507..9ef217ba62c 100644
--- a/spec/requests/snippets_spec.rb
+++ b/spec/requests/snippets_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe "Snippets" do
- let(:project) { Factory :project }
+ let(:project) { create(:project) }
before do
login_as :user
@@ -10,9 +10,9 @@ describe "Snippets" do
describe "GET /snippets" do
before do
- @snippet = Factory :snippet,
- author: @user,
- project: project
+ @snippet = create(:snippet,
+ author: @user,
+ project: project)
visit project_snippets_path(project)
end
@@ -68,9 +68,9 @@ describe "Snippets" do
describe "Edit snippet" do
before do
- @snippet = Factory :snippet,
- author: @user,
- project: project
+ @snippet = create(:snippet,
+ author: @user,
+ project: project)
visit project_snippet_path(project, @snippet)
click_link "Edit"
end
diff --git a/spec/roles/issue_commonality_spec.rb b/spec/roles/issue_commonality_spec.rb
index fc4114e3a77..11f278dea10 100644
--- a/spec/roles/issue_commonality_spec.rb
+++ b/spec/roles/issue_commonality_spec.rb
@@ -15,6 +15,7 @@ describe Issue, "IssueCommonality" do
it { should validate_presence_of(:author) }
it { should validate_presence_of(:title) }
it { should ensure_length_of(:title).is_at_least(0).is_at_most(255) }
+ it { should ensure_inclusion_of(:closed).in_array([true, false]) }
end
describe "Scope" do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 4700c3fe9af..ace5ca00cc1 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -11,14 +11,13 @@ require 'capybara/rails'
require 'capybara/rspec'
require 'webmock/rspec'
require 'email_spec'
-require 'headless'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
-# Use capybara-webkit
-Capybara.javascript_driver = :webkit
+require 'capybara/poltergeist'
+Capybara.javascript_driver = :poltergeist
WebMock.disable_net_connect!(allow_localhost: true)
@@ -35,11 +34,6 @@ RSpec.configure do |config|
# instead of true.
config.use_transactional_fixtures = false
- config.before :all do
- headless = Headless.new
- headless.start
- end
-
config.before do
stub_gitolite!
diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb
index 769034e2286..4579c971d47 100644
--- a/spec/support/login_helpers.rb
+++ b/spec/support/login_helpers.rb
@@ -3,7 +3,7 @@ module LoginHelpers
#
# role - User role (e.g., :admin, :user)
def login_as(role)
- @user = Factory(role)
+ @user = create(role)
login_with(@user)
end
diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb
index 809453c4a3b..29d16ecbac7 100644
--- a/spec/support/matchers.rb
+++ b/spec/support/matchers.rb
@@ -59,9 +59,9 @@ module UrlAccess
def emulate_user(user)
user = case user
- when :user then Factory(:user)
+ when :user then create(:user)
when :visitor then nil
- when :admin then Factory(:admin)
+ when :admin then create(:admin)
else user
end
login_with(user) if user
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index 6f4bcca2bf2..22e3e0d0fe5 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -9,8 +9,8 @@ describe PostReceive do
end
context "web hook" do
- let(:project) { Factory.create(:project) }
- let(:key) { Factory.create(:key, user: project.owner) }
+ let(:project) { create(:project) }
+ let(:key) { create(:key, user: project.owner) }
let(:key_id) { key.identifier }
it "fetches the correct project" do
diff --git a/vendor/assets/javascripts/g.bar-min.js b/vendor/assets/javascripts/g.bar-min.js
new file mode 100644
index 00000000000..42f452af350
--- /dev/null
+++ b/vendor/assets/javascripts/g.bar-min.js
@@ -0,0 +1,7 @@
+/*!
+ * g.Raphael 0.5 - Charting library, based on Raphaël
+ *
+ * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com)
+ * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
+ */
+(function(){var f=Math.min,a=Math.max;function e(o,m,h,p,j,k,l,i){var s,n={round:"round",sharp:"sharp",soft:"soft",square:"square"};if((j&&!p)||(!j&&!h)){return l?"":i.path()}k=n[k]||"square";p=Math.round(p);h=Math.round(h);o=Math.round(o);m=Math.round(m);switch(k){case"round":if(!j){var g=~~(p/2);if(h<g){g=h;s=["M",o+0.5,m+0.5-~~(p/2),"l",0,0,"a",g,~~(p/2),0,0,1,0,p,"l",0,0,"z"]}else{s=["M",o+0.5,m+0.5-g,"l",h-g,0,"a",g,g,0,1,1,0,p,"l",g-h,0,"z"]}}else{g=~~(h/2);if(p<g){g=p;s=["M",o-~~(h/2),m,"l",0,0,"a",~~(h/2),g,0,0,1,h,0,"l",0,0,"z"]}else{s=["M",o-g,m,"l",0,g-p,"a",g,g,0,1,1,h,0,"l",0,p-g,"z"]}}break;case"sharp":if(!j){var q=~~(p/2);s=["M",o,m+q,"l",0,-p,a(h-q,0),0,f(q,h),q,-f(q,h),q+(q*2<p),"z"]}else{q=~~(h/2);s=["M",o+q,m,"l",-h,0,0,-a(p-q,0),q,-f(q,p),q,f(q,p),q,"z"]}break;case"square":if(!j){s=["M",o,m+~~(p/2),"l",0,-p,h,0,0,p,"z"]}else{s=["M",o+~~(h/2),m,"l",1-h,0,0,-p,h-1,0,"z"]}break;case"soft":if(!j){g=f(h,Math.round(p/5));s=["M",o+0.5,m+0.5-~~(p/2),"l",h-g,0,"a",g,g,0,0,1,g,g,"l",0,p-g*2,"a",g,g,0,0,1,-g,g,"l",g-h,0,"z"]}else{g=f(Math.round(h/5),p);s=["M",o-~~(h/2),m,"l",0,g-p,"a",g,g,0,0,1,g,-g,"l",h-2*g,0,"a",g,g,0,0,1,g,g,"l",0,p-g,"z"]}}if(l){return s.join(",")}else{return i.path(s)}}function d(l,J,H,g,m,V,D){D=D||{};var z=this,W=D.type||"square",u=parseFloat(D.gutter||"20%"),T=l.set(),E=l.set(),n=l.set(),B=l.set(),F=Math.max.apply(Math,V),U=[],I=0,M=D.colors||z.colors,A=V.length;if(Raphael.is(V[0],"array")){F=[];I=A;A=0;for(var R=V.length;R--;){E.push(l.set());F.push(Math.max.apply(Math,V[R]));A=Math.max(A,V[R].length)}if(D.stacked){for(var R=A;R--;){var r=0;for(var Q=V.length;Q--;){r+=+V[Q][R]||0}U.push(r)}}for(var R=V.length;R--;){if(V[R].length<A){for(var Q=A;Q--;){V[R].push(0)}}}F=Math.max.apply(Math,D.stacked?U:F)}F=(D.to)||F;var K=g/(A*(100+u)+u)*100,k=K*u/100,p=D.vgutter==null?20:D.vgutter,C=[],q=J+k,o=(m-2*p)/F;if(!D.stretch){k=Math.round(k);K=Math.floor(K)}!D.stacked&&(K/=I||1);for(var R=0;R<A;R++){C=[];for(var Q=0;Q<(I||1);Q++){var S=Math.round((I?V[Q][R]:V[R])*o),t=H+m-p-S,O=e(Math.round(q+K/2),t+S,K,S,true,W,null,l).attr({stroke:"none",fill:M[I?Q:R]});if(I){E[Q].push(O)}else{E.push(O)}O.y=t;O.x=Math.round(q+K/2);O.w=K;O.h=S;O.value=I?V[Q][R]:V[R];if(!D.stacked){q+=K}else{C.push(O)}}if(D.stacked){var P;B.push(P=l.rect(C[0].x-C[0].w/2,H,K,m).attr(z.shim));P.bars=l.set();var v=0;for(var L=C.length;L--;){C[L].toFront()}for(var L=0,w=C.length;L<w;L++){var O=C[L],G,S=(v+O.value)*o,N=e(O.x,H+m-p-!!v*0.5,K,S,true,W,1,l);P.bars.push(O);v&&O.attr({path:N});O.h=S;O.y=H+m-p-!!v*0.5-S;n.push(G=l.rect(O.x-O.w/2,O.y,K,O.value*o).attr(z.shim));G.bar=O;G.value=O.value;v+=O.value}q+=K}q+=k}B.toFront();q=J+k;if(!D.stacked){for(var R=0;R<A;R++){for(var Q=0;Q<(I||1);Q++){var G;n.push(G=l.rect(Math.round(q),H+p,K,m-p).attr(z.shim));G.bar=I?E[Q][R]:E[R];G.value=G.bar.value;q+=K}q+=k}}T.label=function(y,Z){y=y||[];this.labels=l.set();var aa,h=-Infinity;if(D.stacked){for(var x=0;x<A;x++){var X=0;for(var s=0;s<(I||1);s++){X+=I?V[s][x]:V[x];if(s==I-1){var ab=z.labelise(y[x],X,F);aa=l.text(E[s][x].x,H+m-p/2,ab).attr(z.txtattr).attr({fill:D.legendcolor||"#000","text-anchor":"start"}).insertBefore(n[x*(I||1)+s]);var Y=aa.getBBox();if(Y.x-7<h){aa.remove()}else{this.labels.push(aa);h=Y.x+Y.width}}}}}else{for(var x=0;x<A;x++){for(var s=0;s<(I||1);s++){var ab=z.labelise(I?y[s]&&y[s][x]:y[x],I?V[s][x]:V[x],F);aa=l.text(E[s][x].x-k/2,Z?H+m-p/2:E[s][x].y-10,ab).attr(z.txtattr).attr({fill:D.legendcolor||"#000","text-anchor":"start"}).insertBefore(n[x*(I||1)+s]);var Y=aa.getBBox();if(Y.x-7<h){aa.remove()}else{this.labels.push(aa);h=Y.x+Y.width}}}}return this};T.hover=function(i,h){B.hide();n.show();n.mouseover(i).mouseout(h);return this};T.hoverColumn=function(i,h){n.hide();B.show();h=h||function(){};B.mouseover(i).mouseout(h);return this};T.click=function(h){B.hide();n.show();n.click(h);return this};T.each=function(j){if(!Raphael.is(j,"function")){return this}for(var h=n.length;h--;){j.call(n[h])}return this};T.eachColumn=function(j){if(!Raphael.is(j,"function")){return this}for(var h=B.length;h--;){j.call(B[h])}return this};T.clickColumn=function(h){n.hide();B.show();B.click(h);return this};T.push(E,n,B);T.bars=E;T.covers=n;return T}function b(w,v,u,I,F,l,B){B=B||{};var h=this,n=B.type||"square",o=parseFloat(B.gutter||"20%"),D=w.set(),H=w.set(),q=w.set(),L=w.set(),T=Math.max.apply(Math,l),g=[],J=0,t=B.colors||h.colors,O=l.length;if(Raphael.is(l[0],"array")){T=[];J=O;O=0;for(var N=l.length;N--;){H.push(w.set());T.push(Math.max.apply(Math,l[N]));O=Math.max(O,l[N].length)}if(B.stacked){for(var N=O;N--;){var z=0;for(var M=l.length;M--;){z+=+l[M][N]||0}g.push(z)}}for(var N=l.length;N--;){if(l[N].length<O){for(var M=O;M--;){l[N].push(0)}}}T=Math.max.apply(Math,B.stacked?g:T)}T=(B.to)||T;var Q=Math.floor(F/(O*(100+o)+o)*100),r=Math.floor(Q*o/100),p=[],k=u+r,m=(I-1)/T;!B.stacked&&(Q/=J||1);for(var N=0;N<O;N++){p=[];for(var M=0;M<(J||1);M++){var S=J?l[M][N]:l[N],P=e(v,k+Q/2,Math.round(S*m),Q-1,false,n,null,w).attr({stroke:"none",fill:t[J?M:N]});if(J){H[M].push(P)}else{H.push(P)}P.x=v+Math.round(S*m);P.y=k+Q/2;P.w=Math.round(S*m);P.h=Q;P.value=+S;if(!B.stacked){k+=Q}else{p.push(P)}}if(B.stacked){var A=w.rect(v,p[0].y-p[0].h/2,I,Q).attr(h.shim);L.push(A);A.bars=w.set();var E=0;for(var C=p.length;C--;){p[C].toFront()}for(var C=0,K=p.length;C<K;C++){var P=p[C],R,S=Math.round((E+P.value)*m),G=e(v,P.y,S,Q-1,false,n,1,w);A.bars.push(P);E&&P.attr({path:G});P.w=S;P.x=v+S;q.push(R=w.rect(v+E*m,P.y-P.h/2,P.value*m,Q).attr(h.shim));R.bar=P;E+=P.value}k+=Q}k+=r}L.toFront();k=u+r;if(!B.stacked){for(var N=0;N<O;N++){for(var M=0;M<(J||1);M++){var R=w.rect(v,k,I,Q).attr(h.shim);q.push(R);R.bar=J?H[M][N]:H[N];R.value=R.bar.value;k+=Q}k+=r}}D.label=function(Z,W){Z=Z||[];this.labels=w.set();for(var V=0;V<O;V++){for(var U=0;U<J;U++){var y=h.labelise(J?Z[U]&&Z[U][V]:Z[V],J?l[U][V]:l[V],T),Y=W?H[U][V].x-Q/2+3:v+5,x=W?"end":"start",s;this.labels.push(s=w.text(Y,H[U][V].y,y).attr(h.txtattr).attr({fill:B.legendcolor||"#000","text-anchor":"start"}).insertBefore(q[0]));if(s.getBBox().x<v+5){s.attr({x:v+5,"text-anchor":"start"})}else{H[U][V].label=s}}}return this};D.hover=function(j,i){L.hide();q.show();i=i||function(){};q.mouseover(j).mouseout(i);return this};D.hoverColumn=function(j,i){q.hide();L.show();i=i||function(){};L.mouseover(j).mouseout(i);return this};D.each=function(s){if(!Raphael.is(s,"function")){return this}for(var j=q.length;j--;){s.call(q[j])}return this};D.eachColumn=function(s){if(!Raphael.is(s,"function")){return this}for(var j=L.length;j--;){s.call(L[j])}return this};D.click=function(i){L.hide();q.show();q.click(i);return this};D.clickColumn=function(i){q.hide();L.show();L.click(i);return this};D.push(H,q,L);D.bars=H;D.covers=q;return D}var c=function(){};c.prototype=Raphael.g;b.prototype=d.prototype=new c;Raphael.fn.hbarchart=function(h,l,j,g,i,k){return new b(this,h,l,j,g,i,k)};Raphael.fn.barchart=function(h,l,j,g,i,k){return new d(this,h,l,j,g,i,k)}})(); \ No newline at end of file
diff --git a/vendor/assets/javascripts/g.raphael-min.js b/vendor/assets/javascripts/g.raphael-min.js
new file mode 100644
index 00000000000..932904f9acf
--- /dev/null
+++ b/vendor/assets/javascripts/g.raphael-min.js
@@ -0,0 +1,28 @@
+/*!
+ * g.Raphael 0.51 - Charting library, based on Raphaël
+ *
+ * Copyright (c) 2009-2012 Dmitry Baranovskiy (http://g.raphaeljs.com)
+ * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
+ */
+Raphael.el.popup=function(d,a,b,f){var e=this.paper||this[0].paper,c,g,i,h;if(e){switch(this.type){case "text":case "circle":case "ellipse":g=!0;break;default:g=!1}d=null==d?"up":d;a=a||5;c=this.getBBox();b="number"==typeof b?b:g?c.x+c.width/2:c.x;f="number"==typeof f?f:g?c.y+c.height/2:c.y;i=Math.max(c.width/2-a,0);h=Math.max(c.height/2-a,0);this.translate(b-c.x-(g?c.width/2:0),f-c.y-(g?c.height/2:0));c=this.getBBox();b={up:["M",b,f,"l",-a,-a,-i,0,"a",a,a,0,0,1,-a,-a,"l",0,-c.height,"a",a,a,0,0,
+1,a,-a,"l",2*a+2*i,0,"a",a,a,0,0,1,a,a,"l",0,c.height,"a",a,a,0,0,1,-a,a,"l",-i,0,"z"].join(),down:["M",b,f,"l",a,a,i,0,"a",a,a,0,0,1,a,a,"l",0,c.height,"a",a,a,0,0,1,-a,a,"l",-(2*a+2*i),0,"a",a,a,0,0,1,-a,-a,"l",0,-c.height,"a",a,a,0,0,1,a,-a,"l",i,0,"z"].join(),left:["M",b,f,"l",-a,a,0,h,"a",a,a,0,0,1,-a,a,"l",-c.width,0,"a",a,a,0,0,1,-a,-a,"l",0,-(2*a+2*h),"a",a,a,0,0,1,a,-a,"l",c.width,0,"a",a,a,0,0,1,a,a,"l",0,h,"z"].join(),right:["M",b,f,"l",a,-a,0,-h,"a",a,a,0,0,1,a,-a,"l",c.width,0,"a",a,
+a,0,0,1,a,a,"l",0,2*a+2*h,"a",a,a,0,0,1,-a,a,"l",-c.width,0,"a",a,a,0,0,1,-a,-a,"l",0,-h,"z"].join()};a={up:{x:-!g*(c.width/2),y:2*-a-(g?c.height/2:c.height)},down:{x:-!g*(c.width/2),y:2*a+(g?c.height/2:c.height)},left:{x:2*-a-(g?c.width/2:c.width),y:-!g*(c.height/2)},right:{x:2*a+(g?c.width/2:c.width),y:-!g*(c.height/2)}}[d];this.translate(a.x,a.y);return e.path(b[d]).attr({fill:"#000",stroke:"none"}).insertBefore(this.node?this:this[0])}};
+Raphael.el.tag=function(d,a,b,f){var e=this.paper||this[0].paper;if(e){var e=e.path().attr({fill:"#000",stroke:"#000"}),c=this.getBBox(),g,i,h;switch(this.type){case "text":case "circle":case "ellipse":h=!0;break;default:h=!1}d=d||0;b="number"==typeof b?b:h?c.x+c.width/2:c.x;f="number"==typeof f?f:h?c.y+c.height/2:c.y;a=null==a?5:a;i=0.5522*a;c.height>=2*a?e.attr({path:["M",b,f+a,"a",a,a,0,1,1,0,2*-a,a,a,0,1,1,0,2*a,"m",0,2*-a-3,"a",a+3,a+3,0,1,0,0,2*(a+3),"L",b+a+3,f+c.height/2+3,"l",c.width+6,0,
+0,-c.height-6,-c.width-6,0,"L",b,f-a-3].join()}):(g=Math.sqrt(Math.pow(a+3,2)-Math.pow(c.height/2+3,2)),e.attr({path:["M",b,f+a,"c",-i,0,-a,i-a,-a,-a,0,-i,a-i,-a,a,-a,i,0,a,a-i,a,a,0,i,i-a,a,-a,a,"M",b+g,f-c.height/2-3,"a",a+3,a+3,0,1,0,0,c.height+6,"l",a+3-g+c.width+6,0,0,-c.height-6,"L",b+g,f-c.height/2-3].join()}));d=360-d;e.rotate(d,b,f);this.attrs?(this.attr(this.attrs.x?"x":"cx",b+a+3+(!h?"text"==this.type?c.width:0:c.width/2)).attr("y",h?f:f-c.height/2),this.rotate(d,b,f),90<d&&270>d&&this.attr(this.attrs.x?
+"x":"cx",b-a-3-(!h?c.width:c.width/2)).rotate(180,b,f)):90<d&&270>d?(this.translate(b-c.x-c.width-a-3,f-c.y-c.height/2),this.rotate(d-180,c.x+c.width+a+3,c.y+c.height/2)):(this.translate(b-c.x+a+3,f-c.y-c.height/2),this.rotate(d,c.x-a-3,c.y+c.height/2));return e.insertBefore(this.node?this:this[0])}};
+Raphael.el.drop=function(d,a,b){var f=this.getBBox(),e=this.paper||this[0].paper,c,g;if(e){switch(this.type){case "text":case "circle":case "ellipse":c=!0;break;default:c=!1}d=d||0;a="number"==typeof a?a:c?f.x+f.width/2:f.x;b="number"==typeof b?b:c?f.y+f.height/2:f.y;g=Math.max(f.width,f.height)+Math.min(f.width,f.height);e=e.path(["M",a,b,"l",g,0,"A",0.4*g,0.4*g,0,1,0,a+0.7*g,b-0.7*g,"z"]).attr({fill:"#000",stroke:"none"}).rotate(22.5-d,a,b);d=(d+90)*Math.PI/180;a=a+g*Math.sin(d)-(c?0:f.width/2);
+d=b+g*Math.cos(d)-(c?0:f.height/2);this.attrs?this.attr(this.attrs.x?"x":"cx",a).attr(this.attrs.y?"y":"cy",d):this.translate(a-f.x,d-f.y);return e.insertBefore(this.node?this:this[0])}};
+Raphael.el.flag=function(d,a,b){var f=this.paper||this[0].paper;if(f){var f=f.path().attr({fill:"#000",stroke:"#000"}),e=this.getBBox(),c=e.height/2,g;switch(this.type){case "text":case "circle":case "ellipse":g=!0;break;default:g=!1}d=d||0;a="number"==typeof a?a:g?e.x+e.width/2:e.x;b="number"==typeof b?b:g?e.y+e.height/2:e.y;f.attr({path:["M",a,b,"l",c+3,-c-3,e.width+6,0,0,e.height+6,-e.width-6,0,"z"].join()});d=360-d;f.rotate(d,a,b);this.attrs?(this.attr(this.attrs.x?"x":"cx",a+c+3+(!g?"text"==
+this.type?e.width:0:e.width/2)).attr("y",g?b:b-e.height/2),this.rotate(d,a,b),90<d&&270>d&&this.attr(this.attrs.x?"x":"cx",a-c-3-(!g?e.width:e.width/2)).rotate(180,a,b)):90<d&&270>d?(this.translate(a-e.x-e.width-c-3,b-e.y-e.height/2),this.rotate(d-180,e.x+e.width+c+3,e.y+e.height/2)):(this.translate(a-e.x+c+3,b-e.y-e.height/2),this.rotate(d,e.x-c-3,e.y+e.height/2));return f.insertBefore(this.node?this:this[0])}};
+Raphael.el.label=function(){var d=this.getBBox(),a=this.paper||this[0].paper,b=Math.min(20,d.width+10,d.height+10)/2;if(a)return a.rect(d.x-b/2,d.y-b/2,d.width+b,d.height+b,b).attr({stroke:"none",fill:"#000"}).insertBefore(this.node?this:this[0])};
+Raphael.el.blob=function(d,a,b){var f=this.getBBox(),e=Math.PI/180,c=this.paper||this[0].paper,g,i;if(c){switch(this.type){case "text":case "circle":case "ellipse":g=!0;break;default:g=!1}c=c.path().attr({fill:"#000",stroke:"none"});d=(+d+1?d:45)+90;i=Math.min(f.height,f.width);var a="number"==typeof a?a:g?f.x+f.width/2:f.x,b="number"==typeof b?b:g?f.y+f.height/2:f.y,h=Math.max(f.width+i,25*i/12),j=Math.max(f.height+i,25*i/12);g=a+i*Math.sin((d-22.5)*e);var o=b+i*Math.cos((d-22.5)*e),l=a+i*Math.sin((d+
+22.5)*e),d=b+i*Math.cos((d+22.5)*e),e=(l-g)/2;i=(d-o)/2;var h=h/2,j=j/2,n=-Math.sqrt(Math.abs(h*h*j*j-h*h*i*i-j*j*e*e)/(h*h*i*i+j*j*e*e));i=n*h*i/j+(l+g)/2;e=n*-j*e/h+(d+o)/2;c.attr({x:i,y:e,path:["M",a,b,"L",l,d,"A",h,j,0,1,1,g,o,"z"].join()});this.translate(i-f.x-f.width/2,e-f.y-f.height/2);return c.insertBefore(this.node?this:this[0])}};Raphael.fn.label=function(d,a,b){var f=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return f.push(b.label(),b)};
+Raphael.fn.popup=function(d,a,b,f,e){var c=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return c.push(b.popup(f,e),b)};Raphael.fn.tag=function(d,a,b,f,e){var c=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return c.push(b.tag(f,e),b)};Raphael.fn.flag=function(d,a,b,f){var e=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return e.push(b.flag(f),b)};Raphael.fn.drop=function(d,a,b,f){var e=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return e.push(b.drop(f),b)};
+Raphael.fn.blob=function(d,a,b,f){var e=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return e.push(b.blob(f),b)};Raphael.el.lighter=function(d){var d=d||2,a=[this.attrs.fill,this.attrs.stroke];this.fs=this.fs||[a[0],a[1]];a[0]=Raphael.rgb2hsb(Raphael.getRGB(a[0]).hex);a[1]=Raphael.rgb2hsb(Raphael.getRGB(a[1]).hex);a[0].b=Math.min(a[0].b*d,1);a[0].s/=d;a[1].b=Math.min(a[1].b*d,1);a[1].s/=d;this.attr({fill:"hsb("+[a[0].h,a[0].s,a[0].b]+")",stroke:"hsb("+[a[1].h,a[1].s,a[1].b]+")"});return this};
+Raphael.el.darker=function(d){var d=d||2,a=[this.attrs.fill,this.attrs.stroke];this.fs=this.fs||[a[0],a[1]];a[0]=Raphael.rgb2hsb(Raphael.getRGB(a[0]).hex);a[1]=Raphael.rgb2hsb(Raphael.getRGB(a[1]).hex);a[0].s=Math.min(a[0].s*d,1);a[0].b/=d;a[1].s=Math.min(a[1].s*d,1);a[1].b/=d;this.attr({fill:"hsb("+[a[0].h,a[0].s,a[0].b]+")",stroke:"hsb("+[a[1].h,a[1].s,a[1].b]+")"});return this};Raphael.el.resetBrightness=function(){this.fs&&(this.attr({fill:this.fs[0],stroke:this.fs[1]}),delete this.fs);return this};
+(function(){var d=["lighter","darker","resetBrightness"],a="popup tag flag label drop blob".split(" "),b;for(b in a)(function(a){Raphael.st[a]=function(){return Raphael.el[a].apply(this,arguments)}})(a[b]);for(b in d)(function(a){Raphael.st[a]=function(){for(var b=0;b<this.length;b++)this[b][a].apply(this[b],arguments);return this}})(d[b])})();
+Raphael.g={shim:{stroke:"none",fill:"#000","fill-opacity":0},txtattr:{font:"12px Arial, sans-serif",fill:"#fff"},colors:function(){for(var d=[0.6,0.2,0.05,0.1333,0.75,0],a=[],b=0;10>b;b++)b<d.length?a.push("hsb("+d[b]+",.75, .75)"):a.push("hsb("+d[b-d.length]+", 1, .5)");return a}(),snapEnds:function(d,a,b){function f(a){return 0.25>Math.abs(a-0.5)?~~a+0.5:Math.round(a)}var e=d,c=a;if(e==c)return{from:e,to:c,power:0};var e=(c-e)/b,g=c=~~e,b=0;if(c){for(;g;)b--,g=~~(e*Math.pow(10,b))/Math.pow(10,b);
+b++}else{if(0==e||!isFinite(e))b=1;else for(;!c;)b=b||1,c=~~(e*Math.pow(10,b))/Math.pow(10,b),b++;b&&b--}c=f(a*Math.pow(10,b))/Math.pow(10,b);c<a&&(c=f((a+0.5)*Math.pow(10,b))/Math.pow(10,b));e=f((d-(0<b?0:0.5))*Math.pow(10,b))/Math.pow(10,b);return{from:e,to:c,power:b}},axis:function(d,a,b,f,e,c,g,i,h,j,o){var j=null==j?2:j,h=h||"t",c=c||10,o=arguments[arguments.length-1],l="|"==h||" "==h?["M",d+0.5,a,"l",0,0.001]:1==g||3==g?["M",d+0.5,a,"l",0,-b]:["M",d,a+0.5,"l",b,0],n=this.snapEnds(f,e,c),p=n.from,
+t=n.to,m=n.power,u=0,v={font:"11px 'Fontin Sans', Fontin-Sans, sans-serif"},n=o.set(),t=(t-p)/c,k=p,r=0<m?m:0,s=b/c;if(1==+g||3==+g){m=a;for(p=(g-1?1:-1)*(j+3+!!(g-1));m>=a-b;)"-"!=h&&" "!=h&&(l=l.concat(["M",d-("+"==h||"|"==h?j:2*!(g-1)*j),m+0.5,"l",2*j+1,0])),n.push(o.text(d+p,m,i&&i[u++]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v).attr({"text-anchor":g-1?"start":"end"})),k+=t,m-=s;Math.round(m+s-(a-b))&&("-"!=h&&" "!=h&&(l=l.concat(["M",d-("+"==h||"|"==h?j:2*!(g-1)*j),a-b+0.5,"l",2*j+1,0])),n.push(o.text(d+
+p,a-b,i&&i[u]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v).attr({"text-anchor":g-1?"start":"end"})))}else{for(var k=p,r=(0<m)*m,p=(g?-1:1)*(j+9+!g),m=d,s=b/c,q=0,w=0;m<=d+b;)"-"!=h&&" "!=h&&(l=l.concat(["M",m+0.5,a-("+"==h?j:2*!!g*j),"l",0,2*j+1])),n.push(q=o.text(m,a+p,i&&i[u++]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v)),q=q.getBBox(),w>=q.x-5?n.pop(n.length-1).remove():w=q.x+q.width,k+=t,m+=s;Math.round(m-s-d-b)&&("-"!=h&&" "!=h&&(l=l.concat(["M",d+b+0.5,a-("+"==h?j:2*!!g*j),"l",0,2*j+1])),n.push(o.text(d+
+b,a+p,i&&i[u]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v)))}l=o.path(l);l.text=n;l.all=o.set([l,n]);l.remove=function(){this.text.remove();this.constructor.prototype.remove.call(this)};return l},labelise:function(d,a,b){return d?(d+"").replace(/(##+(?:\.#+)?)|(%%+(?:\.%+)?)/g,function(d,e,c){if(e)return(+a).toFixed(e.replace(/^#+\.?/g,"").length);if(c)return(100*a/b).toFixed(c.replace(/^%+\.?/g,"").length)+"%"}):(+a).toFixed(0)}}; \ No newline at end of file