diff options
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: @@ -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 – + = commit.author_link avatar: true, size: 24 + = 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 |