diff --git a/.gitignore b/.gitignore index 93c7eb248..bc936c34c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ .DS_Store public/api_doc/ /.metadata +vendor/cache diff --git a/.metadata/.plugins/com.aptana.index.core/2874248206.index b/.metadata/.plugins/com.aptana.index.core/2874248206.index deleted file mode 100644 index 2200403a8..000000000 Binary files a/.metadata/.plugins/com.aptana.index.core/2874248206.index and /dev/null differ diff --git a/.metadata/.plugins/com.aptana.index.core/2924452064.index b/.metadata/.plugins/com.aptana.index.core/2924452064.index deleted file mode 100644 index 982acfcbc..000000000 Binary files a/.metadata/.plugins/com.aptana.index.core/2924452064.index and /dev/null differ diff --git a/.metadata/.plugins/com.aptana.index.core/4010369919.index b/.metadata/.plugins/com.aptana.index.core/4010369919.index deleted file mode 100644 index e2902378c..000000000 Binary files a/.metadata/.plugins/com.aptana.index.core/4010369919.index and /dev/null differ diff --git a/Gemfile b/Gemfile index 4f2f47682..29b2716a9 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,4 @@ -source 'http://rubygems.org' -#source 'http://ruby.taobao.com' +source 'http://ruby.taobao.org' #source 'http://ruby.sdutlinux.org/' unless RUBY_PLATFORM =~ /w32/ @@ -11,11 +10,11 @@ end gem 'grape', '~> 0.9.0' gem 'grape-entity' -gem 'seems_rateable', path: 'lib/seems_rateable' +gem 'seems_rateable', '~> 1.0.13' gem "rails", "3.2.13" gem "jquery-rails", "~> 2.0.2" gem "i18n", "~> 0.6.0" -gem "coderay", "~> 1.0.6" +gem 'coderay', '~> 1.1.0' gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] gem "builder", "3.0.0" gem 'acts-as-taggable-on', '2.4.1' @@ -28,11 +27,16 @@ gem 'rails_kindeditor' group :development do gem 'grape-swagger' #gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git' - #gem 'puma' + gem 'puma' if RbConfig::CONFIG['host_os'] =~ /linux/ gem 'pry-rails' - gem 'pry-byebug' - gem 'better_errors', path: 'lib/better_errors' - gem 'rack-mini-profiler', path: 'lib/rack-mini-profiler' + if RUBY_VERSION >= '2.0.0' + gem 'pry-byebug' + else + gem 'pry-debugger' + end + gem 'pry-stack_explorer' + gem 'better_errors', '~> 1.1.0' + gem 'rack-mini-profiler', '~> 0.9.3' end group :test do diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 9b66c047f..c055d38ae 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -873,13 +873,15 @@ class CoursesController < ApplicationController "show_course_news" => true, "show_course_messages" => true, "show_bids" => true, - "show_course_journals_for_messages" => true + "show_course_journals_for_messages" => true, + "show_homeworks" => true } @date_to ||= Date.today + 1 # @date_from = (@date_to - @days) > @course.created_at.to_date ? (@date_to - @days) : @course.created_at.to_date #@date_from = @date_to - @days-1.years @author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id])) + @author ||= @course.teacher # 决定显示所用用户或单个用户活动 @activity = Redmine::Activity::Fetcher.new(User.current, :course => @course, :with_subprojects => false, diff --git a/app/controllers/git_callback_controller.rb b/app/controllers/git_callback_controller.rb new file mode 100644 index 000000000..717a22961 --- /dev/null +++ b/app/controllers/git_callback_controller.rb @@ -0,0 +1,9 @@ +class GitCallbackController < ApplicationController + + def post_update + @repository = Repository.find_by_root_url(params[:root_url]) + @repository.fetch_changesets + render :text => 'success' + end + +end \ No newline at end of file diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index da2855582..de9477b8a 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -58,7 +58,7 @@ class IssuesController < ApplicationController def index retrieve_query - sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria) + sort_init(@query.sort_criteria.empty? ? [['updated_on', 'desc']] : @query.sort_criteria) sort_update(@query.sortable_columns) @query.sort_criteria = sort_criteria.to_a @@ -381,7 +381,7 @@ class IssuesController < ApplicationController def retrieve_previous_and_next_issue_ids retrieve_query_from_session if @query - sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria) + sort_init(@query.sort_criteria.empty? ? [['updated_on', 'desc']] : @query.sort_criteria) sort_update(@query.sortable_columns, 'issues_index_sort') limit = 500 issue_ids = @query.issue_ids(:order => sort_clause, :limit => (limit + 1), :include => [:assigned_to, :tracker, :priority, :category, :fixed_version]) diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index ba312c74a..aaaa4484d 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -109,7 +109,7 @@ class MembersController < ApplicationController end if params[:flag] unless members.present? && members.all? {|m| m.valid? } - flash[:error] = members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ') + flash[:error] = members.empty? ? l(:label_user_role_null) :members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ') else flash[:notice] = l(:label_invite_success) end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 44e5fd8a3..e9a27cf44 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -340,6 +340,7 @@ class ProjectsController < ApplicationController @is_zhuce =false flash[:notice] = l(:notice_email_sent, :value => email) else + flash[:error] = l(:notice_registed_success, :value => email) @is_zhuce = true end respond_to do |format| diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 0c1f65317..6c115fc11 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -92,6 +92,22 @@ class RepositoriesController < ApplicationController render :action => 'show', :layout => 'base_projects' end + + HOOK_TEMPLATE = %Q{#!/bin/sh +exec sh -c ' +function update() +{ + CMD_PATH=`dirname $0`; + cd $CMD_PATH; + PY_PATH=$PWD/../../git_refresh_changes.py; + [[ -s "$PY_PATH" ]] && $(which python) $PY_PATH $PWD; + cd -; +} +git update-server-info +update +' + } + def create if params[:repository_scm].to_s == 'Gitlab' # add by nwb @@ -127,7 +143,6 @@ class RepositoriesController < ApplicationController if attrs[:attrs_extra].keys.any? @repository.merge_extra_info(attrs[:attrs_extra]) end - #by xianbo @repository.project = @project if request.post? && @repository.save @@ -145,12 +160,11 @@ class RepositoriesController < ApplicationController " \n ' >> "+ @root_path+"htdocs/"+ @repository_name+"/.htaccess" system "cd "+@project_path+" ;git update-server-info" - # if(create_repo_file&&create_passwd&&create_group&&init_repository&&add_privilege&&init_server_info) - # else - # logger.info "An error occured when authenticating "+"create passwd"+@creat_passwd+"create_group"+ - # crate_group+"create repository file "+create_repo_file+"init repository"+init_repostory+ - # "aad privilege to rpository"+add_privilege+"init server infos"+init_server_info - # end + + File.open(@project_path+"/hooks/post-update", "w+") do |f| + f.write(HOOK_TEMPLATE) + end + @repository.update_attributes(:login => User.current.login.to_s) end redirect_to settings_project_url(@project, :tab => 'repositories') @@ -160,6 +174,8 @@ class RepositoriesController < ApplicationController render :action => 'new', :layout =>'base_projects' end end + + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index d770a4633..4db471ab4 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -445,15 +445,15 @@ class UsersController < ApplicationController else activity = Activity.where(where_condition).where('user_id = ?', @user.id).order('id desc') end - activity = activity.reject { |e| - e.act.nil? || - (!User.current.admin? && !e.act.nil? - (((e.act_type == "Issue") && !e.act.project.visible?(User.current)) || - (e.act_type == "Bid" && !e.act.courses.first.nil? && e.act.courses.first.is_public == 0 && !User.current.member_of_course?(e.act.courses.first)) || - (e.act_type == "Journal" && e.act.respond_to?("Project") && !e.act.project.visible?(User.current)) || - (e.act_type == "News" && ((!e.act.project.nil? && !e.act.project.visible?(User.current)) || (!e.act.course.nil? && e.act.course.is_public == 0 && !User.current.member_of_course?(e.act.course)))) || - (e.act_type == "Message" && !e.act.board.nil? && ((!e.act.board.project.nil? && !e.act.board.project.visible?(User.current)) || (!e.act.board.course.nil? && e.act.board.course.is_public == 0 && !User.current.member_of_course?(e.act.board.course)))))) - } + # activity = activity.reject { |e| + # e.act.nil? || + # (!User.current.admin? && !e.act.nil? + # (((e.act_type == "Issue") && !e.act.project.visible?(User.current)) || + # (e.act_type == "Bid" && !e.act.courses.first.nil? && e.act.courses.first.is_public == 0 && !User.current.member_of_course?(e.act.courses.first)) || + # (e.act_type == "Journal" && e.act.respond_to?("Project") && !e.act.project.visible?(User.current)) || + # (e.act_type == "News" && ((!e.act.project.nil? && !e.act.project.visible?(User.current)) || (!e.act.course.nil? && e.act.course.is_public == 0 && !User.current.member_of_course?(e.act.course)))) || + # (e.act_type == "Message" && !e.act.board.nil? && ((!e.act.board.project.nil? && !e.act.board.project.visible?(User.current)) || (!e.act.board.course.nil? && e.act.board.course.is_public == 0 && !User.current.member_of_course?(e.act.board.course)))))) + # } @activity_count = activity.count @activity_pages = Paginator.new @activity_count, pre_count, params['page'] @activity = activity.slice(@activity_pages.offset,@activity_pages.per_page) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9629ed437..b4f54f075 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1994,4 +1994,10 @@ module ApplicationHelper end technical_title end + + + def ie8? + request.env["HTTP_USER_AGENT"] =~ /MSIE 8.0/ + end + end diff --git a/app/helpers/watchers_helper.rb b/app/helpers/watchers_helper.rb index 221331338..02bc3d8b3 100644 --- a/app/helpers/watchers_helper.rb +++ b/app/helpers/watchers_helper.rb @@ -43,7 +43,7 @@ module WatchersHelper ) method = watched ? 'delete' : 'post' - link_to text, url, :remote => true, :method => method, :style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 22px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES" + link_to text, url, :remote => true, :method => method, :style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 22px; line-height: 21px;padding-top:1px; background: none repeat scroll 0% 0% #64BDD9; TES" end ############## added by linchun @@ -278,11 +278,11 @@ module WatchersHelper ) method = applied ? 'delete' : 'post' - link_to text, url, :remote => true, :method => method ,:style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 22px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES" + link_to text, url, :remote => true, :method => method ,:style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 21px; line-height: 22px;padding-top:1px; background: none repeat scroll 0% 0% #64BDD9; TES" end def exit_project_link(project) link_to(l(:label_exit_project),exit_cur_project_path(project.id), - :remote => true, :confirm => l(:lable_sure_exit_project), :style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 22px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES" ) + :remote => true, :confirm => l(:lable_sure_exit_project), :style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 21px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES;padding-top:1px;" ) end end diff --git a/app/models/bid.rb b/app/models/bid.rb index e5de47b24..10476b4d3 100644 --- a/app/models/bid.rb +++ b/app/models/bid.rb @@ -61,14 +61,21 @@ class Bid < ActiveRecord::Base end } + scope :course_visible, lambda {|*args| + includes(:courses).where(Course.allowed_to_condition(args.shift || User.current, :view_homeworks, *args)) + } + acts_as_watchable acts_as_taggable - acts_as_event :title => Proc.new {|o| "#{l(:label_requirement)} ##{o.id}: #{o.name}" }, + acts_as_event :title => Proc.new {|o| "#{l(:label_course_homework)} ##{o.id}: #{o.name}" }, :description => :description, :author => :author, :url => Proc.new {|o| {:controller => 'bids', :action => 'show', :id => o.id}} + acts_as_activity_provider :type => 'homeworks', + :author_key => :author_id + acts_as_activity_provider :find_options => {:include => [:projects, :author]}, :author_key => :author_id diff --git a/app/models/user.rb b/app/models/user.rb index 860eb56a5..9abe80779 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -778,7 +778,7 @@ class User < Principal (block_given? ? yield(role, self) : true) } #添加课程相关的权限判断 - elsif context && context.is_a?(Course) + elsif context && context.is_a?(Course) return false unless context.allows_to?(action) # Admin users are authorized for anything else return true if admin? diff --git a/app/models/user_extensions.rb b/app/models/user_extensions.rb index 92690d1db..09c88e6df 100644 --- a/app/models/user_extensions.rb +++ b/app/models/user_extensions.rb @@ -32,40 +32,42 @@ class UserExtensions < ActiveRecord::Base def get_brief_introduction return self.brief_introduction end - + + # added by meng def show_identity - if self.identity == 0 - if User.current.language == 'zh' - user_identity = '教师' - else - user_identity = 'Teacher' - end - elsif self.identity == 1 - if User.current.language == 'zh' - user_identity = '学生' - else - user_identity = 'Student' - end - elsif self.identity == 2 - if User.current.language == 'zh' - user_identity = '企业' - else - user_identity = 'Enterprise' - end - elsif self.identity == 3 - if User.current.language == 'zh' - user_identity = '开发者' - else - user_identity = 'Developer' + if User.current.language == 'zh'||User.current.language == '' + case self.identity + when 0 + user_identity = l(:label_account_identity_teacher) + when 1 + user_identity = l(:label_account_identity_student) + when 2 + user_identity = l(:label_account_identity_enterprise) + when 3 + user_identity = l(:label_account_identity_developer) + else + user_identity = '' end else - user_identity = '' + case self.identity + when 0 + user_identity = l(:label_account_identity_teacher) + when 1 + user_identity = l(:label_account_identity_student) + when 2 + user_identity = l(:label_account_identity_enterprise) + when 3 + user_identity = l(:label_account_identity_developer) + else + user_identity = '' + end end return user_identity end -# end - +# end + + def self.introduction(user, message) unless user.user_extensions.nil? info = user.user_extensions diff --git a/app/views/attachments/_form.html.erb b/app/views/attachments/_form.html.erb index 22dc447f2..67ae4ce66 100644 --- a/app/views/attachments/_form.html.erb +++ b/app/views/attachments/_form.html.erb @@ -1,6 +1,6 @@ <% if defined?(container) && container && container.saved_attachments %> - <% container.attachments.each_with_index do |attachment, i| %> + <% container.saved_attachments.each_with_index do |attachment, i| %> <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%> <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") %> @@ -34,7 +34,6 @@ <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %> <% end %> - <% end %> - - <%# - If Rails's Turbolinks is used, the Better Errors page is probably - rendered in the host app's layout. Let's empty out the styles of the - host app. - %> - - -
-
-

<%= exception.type %> at <%= request_path %>

-

<%= exception.message %>

-
-
- -
- - - <% backtrace_frames.each_with_index do |frame, index| %> - - <% end %> -
- - - - - diff --git a/lib/better_errors/lib/better_errors/templates/text.erb b/lib/better_errors/lib/better_errors/templates/text.erb deleted file mode 100644 index fe9068bbb..000000000 --- a/lib/better_errors/lib/better_errors/templates/text.erb +++ /dev/null @@ -1,21 +0,0 @@ -<%== text_heading("=", "%s at %s" % [exception.type, request_path]) %> - -> <%== exception.message %> -<% if backtrace_frames.any? %> - -<%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %> - -``` ruby -<%== text_formatted_code_block(first_frame) %>``` - -App backtrace -------------- - -<%== application_frames.map { |s| " - #{s}" }.join("\n") %> - -Full backtrace --------------- - -<%== backtrace_frames.map { |s| " - #{s}" }.join("\n") %> - -<% end %> diff --git a/lib/better_errors/lib/better_errors/templates/variable_info.erb b/lib/better_errors/lib/better_errors/templates/variable_info.erb deleted file mode 100644 index bde5daab8..000000000 --- a/lib/better_errors/lib/better_errors/templates/variable_info.erb +++ /dev/null @@ -1,70 +0,0 @@ -
-
-

<%= @frame.name %>

- -
-
- <%== html_formatted_code_block @frame %> -
- - <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %> -
-
-

-                
>>
-
-
- <% end %> -
- -<% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %> -
- This is a live shell. Type in here. -
- -
-<% end %> - -<% unless BetterErrors.binding_of_caller_available? %> -
- Tip: add gem "binding_of_caller" to your Gemfile to enable the REPL and local/instance variable inspection. -
-<% end %> - -
-

Request info

-
- - <% if rails_params %> - - <% end %> - <% if rack_session %> - - <% end %> -
Request parameters
<%== inspect_value rails_params %>
Rack session
<%== inspect_value rack_session %>
-
-
- -
-

Local Variables

-
- - <% @frame.local_variables.each do |name, value| %> - - <% end %> -
<%= name %>
<%== inspect_value value %>
-
-
- -
-

Instance Variables

-
- - <% @frame.instance_variables.each do |name, value| %> - - <% end %> -
<%= name %>
<%== inspect_value value %>
-
-
- - diff --git a/lib/better_errors/lib/better_errors/version.rb b/lib/better_errors/lib/better_errors/version.rb deleted file mode 100644 index 81769ce8b..000000000 --- a/lib/better_errors/lib/better_errors/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module BetterErrors - VERSION = "1.1.0" -end diff --git a/lib/better_errors/spec/better_errors/code_formatter_spec.rb b/lib/better_errors/spec/better_errors/code_formatter_spec.rb deleted file mode 100644 index c084e2f91..000000000 --- a/lib/better_errors/spec/better_errors/code_formatter_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe CodeFormatter do - let(:filename) { File.expand_path("../support/my_source.rb", __FILE__) } - - let(:formatter) { CodeFormatter.new(filename, 8) } - - it "picks an appropriate scanner" do - formatter.coderay_scanner.should == :ruby - end - - it "shows 5 lines of context" do - formatter.line_range.should == (3..13) - - formatter.context_lines.should == [ - "three\n", - "four\n", - "five\n", - "six\n", - "seven\n", - "eight\n", - "nine\n", - "ten\n", - "eleven\n", - "twelve\n", - "thirteen\n" - ] - end - - it "works when the line is right on the edge" do - formatter = CodeFormatter.new(filename, 20) - formatter.line_range.should == (15..20) - end - - describe CodeFormatter::HTML do - it "highlights the erroring line" do - formatter = CodeFormatter::HTML.new(filename, 8) - formatter.output.should =~ /highlight.*eight/ - end - - it "works when the line is right on the edge" do - formatter = CodeFormatter::HTML.new(filename, 20) - formatter.output.should_not == formatter.source_unavailable - end - - it "doesn't barf when the lines don't make any sense" do - formatter = CodeFormatter::HTML.new(filename, 999) - formatter.output.should == formatter.source_unavailable - end - - it "doesn't barf when the file doesn't exist" do - formatter = CodeFormatter::HTML.new("fkdguhskd7e l", 1) - formatter.output.should == formatter.source_unavailable - end - end - - describe CodeFormatter::Text do - it "highlights the erroring line" do - formatter = CodeFormatter::Text.new(filename, 8) - formatter.output.should == <<-TEXT.gsub(/^ /, "") - 3 three - 4 four - 5 five - 6 six - 7 seven - > 8 eight - 9 nine - 10 ten - 11 eleven - 12 twelve - 13 thirteen - TEXT - end - - it "works when the line is right on the edge" do - formatter = CodeFormatter::Text.new(filename, 20) - formatter.output.should_not == formatter.source_unavailable - end - - it "doesn't barf when the lines don't make any sense" do - formatter = CodeFormatter::Text.new(filename, 999) - formatter.output.should == formatter.source_unavailable - end - - it "doesn't barf when the file doesn't exist" do - formatter = CodeFormatter::Text.new("fkdguhskd7e l", 1) - formatter.output.should == formatter.source_unavailable - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/error_page_spec.rb b/lib/better_errors/spec/better_errors/error_page_spec.rb deleted file mode 100644 index daea57be6..000000000 --- a/lib/better_errors/spec/better_errors/error_page_spec.rb +++ /dev/null @@ -1,76 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe ErrorPage do - let!(:exception) { raise ZeroDivisionError, "you divided by zero you silly goose!" rescue $! } - - let(:error_page) { ErrorPage.new exception, { "PATH_INFO" => "/some/path" } } - - let(:response) { error_page.render } - - let(:empty_binding) { - local_a = :value_for_local_a - local_b = :value_for_local_b - - @inst_c = :value_for_inst_c - @inst_d = :value_for_inst_d - - binding - } - - it "includes the error message" do - response.should include("you divided by zero you silly goose!") - end - - it "includes the request path" do - response.should include("/some/path") - end - - it "includes the exception class" do - response.should include("ZeroDivisionError") - end - - context "variable inspection" do - let(:exception) { empty_binding.eval("raise") rescue $! } - - if BetterErrors.binding_of_caller_available? - it "shows local variables" do - html = error_page.do_variables("index" => 0)[:html] - html.should include("local_a") - html.should include(":value_for_local_a") - html.should include("local_b") - html.should include(":value_for_local_b") - end - else - it "tells the user to add binding_of_caller to their gemfile to get fancy features" do - html = error_page.do_variables("index" => 0)[:html] - html.should include(%{gem "binding_of_caller"}) - end - end - - it "shows instance variables" do - html = error_page.do_variables("index" => 0)[:html] - html.should include("inst_c") - html.should include(":value_for_inst_c") - html.should include("inst_d") - html.should include(":value_for_inst_d") - end - - it "shows filter instance variables" do - BetterErrors.stub(:ignored_instance_variables).and_return([ :@inst_d ]) - html = error_page.do_variables("index" => 0)[:html] - html.should include("inst_c") - html.should include(":value_for_inst_c") - html.should_not include('@inst_d') - html.should_not include("
:value_for_inst_d
") - end - end - - it "doesn't die if the source file is not a real filename" do - exception.stub(:backtrace).and_return([ - ":10:in `spawn_rack_application'" - ]) - response.should include("Source unavailable") - end - end -end diff --git a/lib/better_errors/spec/better_errors/middleware_spec.rb b/lib/better_errors/spec/better_errors/middleware_spec.rb deleted file mode 100644 index 2c638bfab..000000000 --- a/lib/better_errors/spec/better_errors/middleware_spec.rb +++ /dev/null @@ -1,146 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe Middleware do - let(:app) { Middleware.new(->env { ":)" }) } - let(:exception) { RuntimeError.new("oh no :(") } - - it "passes non-error responses through" do - app.call({}).should == ":)" - end - - it "calls the internal methods" do - app.should_receive :internal_call - app.call("PATH_INFO" => "/__better_errors/1/preform_awesomness") - end - - it "calls the internal methods on any subfolder path" do - app.should_receive :internal_call - app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/1/preform_awesomness") - end - - it "shows the error page" do - app.should_receive :show_error_page - app.call("PATH_INFO" => "/__better_errors/") - end - - it "shows the error page on any subfolder path" do - app.should_receive :show_error_page - app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/") - end - - it "doesn't show the error page to a non-local address" do - app.should_not_receive :better_errors_call - app.call("REMOTE_ADDR" => "1.2.3.4") - end - - it "shows to a whitelisted IP" do - BetterErrors::Middleware.allow_ip! '77.55.33.11' - app.should_receive :better_errors_call - app.call("REMOTE_ADDR" => "77.55.33.11") - end - - it "doesn't blow up when given a blank REMOTE_ADDR" do - expect { app.call("REMOTE_ADDR" => " ") }.to_not raise_error - end - - it "doesn't blow up when given an IP address with a zone index" do - expect { app.call("REMOTE_ADDR" => "0:0:0:0:0:0:0:1%0" ) }.to_not raise_error - end - - context "when requesting the /__better_errors manually" do - let(:app) { Middleware.new(->env { ":)" }) } - - it "shows that no errors have been recorded" do - status, headers, body = app.call("PATH_INFO" => "/__better_errors") - body.join.should match /No errors have been recorded yet./ - end - - it "shows that no errors have been recorded on any subfolder path" do - status, headers, body = app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors") - body.join.should match /No errors have been recorded yet./ - end - end - - context "when handling an error" do - let(:app) { Middleware.new(->env { raise exception }) } - - it "returns status 500" do - status, headers, body = app.call({}) - - status.should == 500 - end - - context "original_exception" do - class OriginalExceptionException < Exception - attr_reader :original_exception - - def initialize(message, original_exception = nil) - super(message) - @original_exception = original_exception - end - end - - it "shows Original Exception if it responds_to and has an original_exception" do - app = Middleware.new(->env { - raise OriginalExceptionException.new("Other Exception", Exception.new("Original Exception")) - }) - - status, _, body = app.call({}) - - status.should == 500 - body.join.should_not match(/Other Exception/) - body.join.should match(/Original Exception/) - end - - it "won't crash if the exception responds_to but doesn't have an original_exception" do - app = Middleware.new(->env { - raise OriginalExceptionException.new("Other Exception") - }) - - status, _, body = app.call({}) - - status.should == 500 - body.join.should match(/Other Exception/) - end - end - - it "returns ExceptionWrapper's status_code" do - ad_ew = double("ActionDispatch::ExceptionWrapper") - ad_ew.stub('new').with({}, exception ){ double("ExceptionWrapper", status_code: 404) } - stub_const('ActionDispatch::ExceptionWrapper', ad_ew) - - status, headers, body = app.call({}) - - status.should == 404 - end - - it "returns UTF-8 error pages" do - status, headers, body = app.call({}) - - headers["Content-Type"].should match /charset=utf-8/ - end - - it "returns text pages by default" do - status, headers, body = app.call({}) - - headers["Content-Type"].should match /text\/plain/ - end - - it "returns HTML pages by default" do - # Chrome's 'Accept' header looks similar this. - status, headers, body = app.call("HTTP_ACCEPT" => "text/html,application/xhtml+xml;q=0.9,*/*") - - headers["Content-Type"].should match /text\/html/ - end - - it "logs the exception" do - logger = Object.new - logger.should_receive :fatal - BetterErrors.stub(:logger).and_return(logger) - - app.call({}) - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/raised_exception_spec.rb b/lib/better_errors/spec/better_errors/raised_exception_spec.rb deleted file mode 100644 index 605ab409c..000000000 --- a/lib/better_errors/spec/better_errors/raised_exception_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe RaisedException do - let(:exception) { RuntimeError.new("whoops") } - subject { RaisedException.new(exception) } - - its(:exception) { should == exception } - its(:message) { should == "whoops" } - its(:type) { should == RuntimeError } - - context "when the exception wraps another exception" do - let(:original_exception) { RuntimeError.new("something went wrong!") } - let(:exception) { double(:original_exception => original_exception) } - - its(:exception) { should == original_exception } - its(:message) { should == "something went wrong!" } - end - - context "when the exception is a syntax error" do - let(:exception) { SyntaxError.new("foo.rb:123: you made a typo!") } - - its(:message) { should == "you made a typo!" } - its(:type) { should == SyntaxError } - - it "has the right filename and line number in the backtrace" do - subject.backtrace.first.filename.should == "foo.rb" - subject.backtrace.first.line.should == 123 - end - end - - context "when the exception is a HAML syntax error" do - before do - stub_const("Haml::SyntaxError", Class.new(SyntaxError)) - end - - let(:exception) { - Haml::SyntaxError.new("you made a typo!").tap do |ex| - ex.set_backtrace(["foo.rb:123", "haml/internals/blah.rb:123456"]) - end - } - - its(:message) { should == "you made a typo!" } - its(:type) { should == Haml::SyntaxError } - - it "has the right filename and line number in the backtrace" do - subject.backtrace.first.filename.should == "foo.rb" - subject.backtrace.first.line.should == 123 - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/repl/basic_spec.rb b/lib/better_errors/spec/better_errors/repl/basic_spec.rb deleted file mode 100644 index c533f632c..000000000 --- a/lib/better_errors/spec/better_errors/repl/basic_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "spec_helper" -require "better_errors/repl/basic" -require "better_errors/repl/shared_examples" - -module BetterErrors - module REPL - describe Basic do - let(:fresh_binding) { - local_a = 123 - binding - } - - let(:repl) { Basic.new fresh_binding } - - it_behaves_like "a REPL provider" - end - end -end diff --git a/lib/better_errors/spec/better_errors/repl/pry_spec.rb b/lib/better_errors/spec/better_errors/repl/pry_spec.rb deleted file mode 100644 index 1aa502c56..000000000 --- a/lib/better_errors/spec/better_errors/repl/pry_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require "spec_helper" -require "pry" -require "better_errors/repl/pry" -require "better_errors/repl/shared_examples" - -module BetterErrors - module REPL - describe Pry do - let(:fresh_binding) { - local_a = 123 - binding - } - - let(:repl) { Pry.new fresh_binding } - - it "does line continuation" do - output, prompt, filled = repl.send_input "" - output.should == "=> nil\n" - prompt.should == ">>" - filled.should == "" - - output, prompt, filled = repl.send_input "def f(x)" - output.should == "" - prompt.should == ".." - filled.should == " " - - output, prompt, filled = repl.send_input "end" - if RUBY_VERSION >= "2.1.0" - output.should == "=> :f\n" - else - output.should == "=> nil\n" - end - prompt.should == ">>" - filled.should == "" - end - - it_behaves_like "a REPL provider" - end - end -end diff --git a/lib/better_errors/spec/better_errors/repl/shared_examples.rb b/lib/better_errors/spec/better_errors/repl/shared_examples.rb deleted file mode 100644 index 0154851db..000000000 --- a/lib/better_errors/spec/better_errors/repl/shared_examples.rb +++ /dev/null @@ -1,18 +0,0 @@ -shared_examples_for "a REPL provider" do - it "evaluates ruby code in a given context" do - repl.send_input("local_a = 456") - fresh_binding.eval("local_a").should == 456 - end - - it "returns a tuple of output and the new prompt" do - output, prompt = repl.send_input("1 + 2") - output.should == "=> 3\n" - prompt.should == ">>" - end - - it "doesn't barf if the code throws an exception" do - output, prompt = repl.send_input("raise Exception") - output.should include "Exception: Exception" - prompt.should == ">>" - end -end diff --git a/lib/better_errors/spec/better_errors/stack_frame_spec.rb b/lib/better_errors/spec/better_errors/stack_frame_spec.rb deleted file mode 100644 index 420111eec..000000000 --- a/lib/better_errors/spec/better_errors/stack_frame_spec.rb +++ /dev/null @@ -1,157 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe StackFrame do - context "#application?" do - it "is true for application filenames" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - - frame.application?.should be_true - end - - it "is false for everything else" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/nope", 123, "foo") - - frame.application?.should be_false - end - - it "doesn't care if no application_root is set" do - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - - frame.application?.should be_false - end - end - - context "#gem?" do - it "is true for gem filenames" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.gem?.should be_true - end - - it "is false for everything else" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/nope", 123, "foo") - - frame.gem?.should be_false - end - end - - context "#application_path" do - it "chops off the application root" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - - frame.application_path.should == "app/controllers/crap_controller.rb" - end - end - - context "#gem_path" do - it "chops of the gem path and stick (gem) there" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb" - end - - it "prioritizes gem path over application path" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - Gem.stub(:path).and_return(["/abc/xyz/vendor"]) - frame = StackFrame.new("/abc/xyz/vendor/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb" - end - end - - context "#pretty_path" do - it "returns #application_path for application paths" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - frame.pretty_path.should == frame.application_path - end - - it "returns #gem_path for gem paths" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.pretty_path.should == frame.gem_path - end - end - - it "special cases SyntaxErrors" do - begin - eval(%{ raise SyntaxError, "you wrote bad ruby!" }, nil, "my_file.rb", 123) - rescue SyntaxError => syntax_error - end - frames = StackFrame.from_exception(syntax_error) - frames.first.filename.should == "my_file.rb" - frames.first.line.should == 123 - end - - it "doesn't blow up if no method name is given" do - error = StandardError.allocate - - error.stub(:backtrace).and_return(["foo.rb:123"]) - frames = StackFrame.from_exception(error) - frames.first.filename.should == "foo.rb" - frames.first.line.should == 123 - - error.stub(:backtrace).and_return(["foo.rb:123: this is an error message"]) - frames = StackFrame.from_exception(error) - frames.first.filename.should == "foo.rb" - frames.first.line.should == 123 - end - - it "ignores a backtrace line if its format doesn't make any sense at all" do - error = StandardError.allocate - error.stub(:backtrace).and_return(["foo.rb:123:in `foo'", "C:in `find'", "bar.rb:123:in `bar'"]) - frames = StackFrame.from_exception(error) - frames.count.should == 2 - end - - it "doesn't blow up if a filename contains a colon" do - error = StandardError.allocate - error.stub(:backtrace).and_return(["crap:filename.rb:123"]) - frames = StackFrame.from_exception(error) - frames.first.filename.should == "crap:filename.rb" - end - - it "doesn't blow up with a BasicObject as frame binding" do - obj = BasicObject.new - def obj.my_binding - ::Kernel.binding - end - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index", obj.my_binding) - frame.class_name.should == 'BasicObject' - end - - it "sets method names properly" do - obj = "string" - def obj.my_method - begin - raise "foo" - rescue => err - err - end - end - - frame = StackFrame.from_exception(obj.my_method).first - if BetterErrors.binding_of_caller_available? - frame.method_name.should == "#my_method" - frame.class_name.should == "String" - else - frame.method_name.should == "my_method" - frame.class_name.should == nil - end - end - - if RUBY_ENGINE == "java" - it "doesn't blow up on a native Java exception" do - expect { StackFrame.from_exception(java.lang.Exception.new) }.to_not raise_error - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/support/my_source.rb b/lib/better_errors/spec/better_errors/support/my_source.rb deleted file mode 100644 index 6dfea0f66..000000000 --- a/lib/better_errors/spec/better_errors/support/my_source.rb +++ /dev/null @@ -1,20 +0,0 @@ -one -two -three -four -five -six -seven -eight -nine -ten -eleven -twelve -thirteen -fourteen -fifteen -sixteen -seventeen -eighteen -nineteen -twenty diff --git a/lib/better_errors/spec/better_errors_spec.rb b/lib/better_errors/spec/better_errors_spec.rb deleted file mode 100644 index e9b26b67d..000000000 --- a/lib/better_errors/spec/better_errors_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -require "spec_helper" - -describe BetterErrors do - context ".editor" do - it "defaults to textmate" do - subject.editor["foo.rb", 123].should == "txmt://open?url=file://foo.rb&line=123" - end - - it "url escapes the filename" do - subject.editor["&.rb", 0].should == "txmt://open?url=file://%26.rb&line=0" - end - - [:emacs, :emacsclient].each do |editor| - it "uses emacs:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "emacs://" - end - end - - [:macvim, :mvim].each do |editor| - it "uses mvim:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "mvim://" - end - end - - [:sublime, :subl, :st].each do |editor| - it "uses subl:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "subl://" - end - end - - [:textmate, :txmt, :tm].each do |editor| - it "uses txmt:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "txmt://" - end - end - - ["emacsclient", "/usr/local/bin/emacsclient"].each do |editor| - it "uses emacs:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "emacs://" - end - end - - ["mvim -f", "/usr/local/bin/mvim -f"].each do |editor| - it "uses mvim:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "mvim://" - end - end - - ["subl -w", "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl"].each do |editor| - it "uses mvim:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "subl://" - end - end - - ["mate -w", "/usr/bin/mate -w"].each do |editor| - it "uses txmt:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "txmt://" - end - end - end -end diff --git a/lib/better_errors/spec/spec_helper.rb b/lib/better_errors/spec/spec_helper.rb deleted file mode 100644 index 40d63261e..000000000 --- a/lib/better_errors/spec/spec_helper.rb +++ /dev/null @@ -1,5 +0,0 @@ -$: << File.expand_path("../../lib", __FILE__) - -ENV["EDITOR"] = nil - -require "better_errors" diff --git a/lib/better_errors/spec/without_binding_of_caller.rb b/lib/better_errors/spec/without_binding_of_caller.rb deleted file mode 100644 index 035e2e90f..000000000 --- a/lib/better_errors/spec/without_binding_of_caller.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Kernel - alias_method :require_with_binding_of_caller, :require - - def require(feature) - raise LoadError if feature == "binding_of_caller" - - require_with_binding_of_caller(feature) - end -end diff --git a/lib/git_refresh_changes.py b/lib/git_refresh_changes.py new file mode 100644 index 000000000..a0250243e --- /dev/null +++ b/lib/git_refresh_changes.py @@ -0,0 +1,30 @@ +#coding=utf-8 +#!/usr/bin/env python + +# 脚本用于刷新版本库,由git hooks里进行调用,传入参数为git仓库路径 +# 需要配置rails项目地址 +# 必须装此文件放在git的存放目录,现在是 /home/pdl/redmine-2.3.2-0/apache2/htdocs + +import sys +import os +import urllib +import urllib2 + +RAILS_URL = 'http://192.168.128.128:3000/' + +def get_git_path(): + return sys.argv[1] + path=os.path.realpath(sys.argv[0]) + if os.path.isfile(path): + path=os.path.dirname(os.path.dirname(path)) + return os.path.abspath(path) + +def post_http_data(url, data): + data_urlencode = urllib.urlencode(data) + req = urllib2.Request(url = url,data =data_urlencode) + res_data = urllib2.urlopen(req) + #res = res_data.read() + #return res + +path = get_git_path() +post_http_data(RAILS_URL + 'git_callback/post_update', {'root_url': path}) diff --git a/lib/rack-mini-profiler/.travis.yml b/lib/rack-mini-profiler/.travis.yml deleted file mode 100644 index 61ab0d68e..000000000 --- a/lib/rack-mini-profiler/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: ruby -rvm: - - 1.9.3 - - 2.0.0 - - 2.1.1 -bundler_args: "" -services: - - redis - - memcached diff --git a/lib/rack-mini-profiler/CHANGELOG b/lib/rack-mini-profiler/CHANGELOG deleted file mode 100644 index 7c08a89e1..000000000 --- a/lib/rack-mini-profiler/CHANGELOG +++ /dev/null @@ -1,181 +0,0 @@ -28-June-2012 - Sam - - * Started change log - * Corrected profiler so it properly captures POST requests (was supressing non 200s) - * Amended Rack.MiniProfiler.config[:user_provider] to use ip addres for identity - * Fixed bug where unviewed missing ids never got cleared - * Supress all '/assets/' in the rails tie (makes debugging easier) - * record_sql was mega buggy - * added MemcacheStore - -9-July-2012 - Sam - - * Cleaned up mechanism for profiling in production, all you need to do now - is call Rack::MiniProfiler.authorize_request to get profiling working in - production - * Added option to display full backtraces pp=full-backtrace - * Cleaned up railties, got rid of the post authorize callback - * Version 0.1.3 - -12-July-2012 - Sam - - * Fixed incorrect profiling steps (was not indenting or measuring start time right - * Implemented native PG and MySql2 interceptors, this gives way more accurate times - * Refactored context so its a proper class and not a hash - * Added some more client probing built in to rails - * More tests - -18-July-2012 - Sam - - * Added First Paint time for chrome - * Bug fix to ensure non Rails installs have mini profiler - * Version 0.1.7 - -30-July-2012 - Sam - - * Made compliant with ancient versions of Rack (including Rack used by Rails2) - * Fixed broken share link - * Fixed crashes on startup (in MemoryStore and FileStore) - * Version 0.1.8 - * Unicode fix - * Version 0.1.9 - -7-August-2012 - Sam - - * Added option to disable profiler for the current session (pp=disable / pp=enable) - * yajl compatability contributed by Sven Riedel - -10-August-2012 - Sam - - * Added basic prepared statement profiling for postgres - -20-August-2012 - Sam - - * 1.12.pre - * Cap X-MiniProfiler-Ids at 10, otherwise the header can get killed - -3-September-2012 - Sam - - * 1.13.pre - * pg gem prepared statements were not being logged correctly - * added setting config.backtrace_ignores = [] - an array of regexes that match on caller lines that get ignored - * added setting config.backtrace_includes = [] - an array of regexes that get included in the trace by default - * cleaned up the way client settings are stored - * made pp=full-backtrace "sticky" - * added pp=normal-backtrace to clear the "sticky" state - * change "pp=sample" to work with "caller" no need for stack trace gem - -4-September-2012 - Sam - - * 1.15.pre - * fixed annoying bug where client settings were not sticking - * fixed long standing issue with Rack::ConditionalGet stopping MiniProfiler from working properly - -5-September-2012 - Sam - - * 1.16 - * fixed long standing problem specs (issue with memory store) - * fixed issue where profiler would be dumped when you got a 404 in production (and any time rails is bypassed) - * implemented stacktrace properly - -9-September-2012 - Sam - - * 1.17 - * pp=sample was bust unless stacktrace was installed - -10-September-2012 - Sam - - * 1.19 - * fix compat issue with 1.8.7 - -12-September-2012 - Sam - - * 1.20 - * Added pp=profile-gc , it allows you to profile the GC in Ruby 1.9.3 - -17-September-2012 - * 1.21 - * New MemchacedStore - * Rails 4 support - -17-September-2012 - * Allow rack-mini-profiler to be sourced from github - * Extracted the pp=profile-gc-time out, the object space profiler needs to disable gc - -20-September-2012 - * 1.22 - * Fix permission issue in the gem - -8-April-2013 - * 1.24 - * Flame Graph Support see: http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler - * Fix file retention leak in file_store - * New toggle_shortcut and start_hidden options - * Fix for AngularJS support and MooTools - * More robust gc profiling - * Mongoid support - * Fix for html5 implicit body tags - * script tag initialized via data-attributes - * new - Rack::MiniProfiler.counter counter_name {} - * Allow usage of existing jQuery if its already loaded - * Fix pp=enable - * 1.8.7 support ... grrr - * Net:HTTP profiling - * pre authorize to run in all non development? and production? modes - -8-April-2013 - * 1.25 - * Missed flamegraph.html from build - -11-April-2013 - * 1.26 - * (minor) allow Rack::MiniProfilerRails.initialize!(Rails.application), for post config intialization - -26-June-2013 - * 1.27 - * Disable global ajax handlers on MP requests @JP - * Add Rack::MiniProfiler.config.backtrace_threshold_ms - * jQuery 2.0 support - -18-July-2013 - * 1.28 - * diagnostics in abstract storage was raising not implemented killing - ?pp=env and others - * SOLR xml unescaped by mistake - -20-August-2013 - * 1.29 - * Bugfix: SOLR patching had an incorrect monkey patch - * Implemented exception tracing using TracePoint see pp=trace-exceptions - -30-August-2013 - - * 1.30 - * Feature: Added Rack::MiniProfiler.counter_method(klass,name) for injecting counters - * Bug: Counters were not shifting the table correctly - -3-September-2013 - - * Ripped out flamegraph so it can be isolated into a gem - * Flamegraph now has much increased fidelity - * Ripped out pp=sample it just was never really used - -17-September-2013 - Ross Wilson - * Instead of supressing all "/assets/" requests we now check the configured - config.assets.prefix path since developers can rename the path to serve Asset Pipeline - files from - -12-December-2013 - Sam Saffron - * Version 0.9.0.pre (bumped up to reflect the stability of the project) - * Improved reports for pp=profile-gc - * pp=flamegraph&flamegraph_sample_rate=1 , allow you to specify sampling rates - -13-March-2014 - Sam Saffron - * Version 0.9.1 - * Added back Ruby 1.8 support (thanks Malet) - * Corrected Rails 3.0 support (thanks Zlatko) - * Corrected fix possible XSS (admin only) - * Amend Railstie so MiniProfiler can be launched with action view or action controller (Thanks Akira) - * Corrected Sql patching to avoid setting instance vars on nil which is frozen (thanks Andy, huoxito) - - diff --git a/lib/rack-mini-profiler/Gemfile b/lib/rack-mini-profiler/Gemfile deleted file mode 100644 index d65e2a669..000000000 --- a/lib/rack-mini-profiler/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source 'http://rubygems.org' - -gemspec diff --git a/lib/rack-mini-profiler/README.md b/lib/rack-mini-profiler/README.md deleted file mode 100644 index 550dc1e07..000000000 --- a/lib/rack-mini-profiler/README.md +++ /dev/null @@ -1,271 +0,0 @@ -# rack-mini-profiler - -[![Code Climate](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler.png)](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler) [![Build Status](https://travis-ci.org/MiniProfiler/rack-mini-profiler.png)](https://travis-ci.org/MiniProfiler/rack-mini-profiler) - -Middleware that displays speed badge for every html page. Designed to work both in production and in development. - -#### Features - -* database profiling. Currently supports Mysql2, Postgres, and Mongoid3 (with fallback support to ActiveRecord) - -#### Learn more - -* [Visit our community](http://community.miniprofiler.com) -* [Watch the RailsCast](http://railscasts.com/episodes/368-miniprofiler) -* [Read about Flame graphs in rack-mini-profiler](http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler) -* [Read the announcement posts from 2012](http://samsaffron.com/archive/2012/07/12/miniprofiler-ruby-edition) - -## rack-mini-profiler needs your help - -We have decided to restructure our repository so there is a central UI repo and the various language implementation have their own. - -**WE NEED HELP.** - -- Setting up a build that reuses https://github.com/MiniProfiler/ui -- Migrating the internal data structures [per the spec](https://github.com/MiniProfiler/ui) -- Cleaning up the [horrendous class structure that is using strings as keys and crazy non-objects](https://github.com/MiniProfiler/rack-mini-profiler/blob/master/lib/mini_profiler/sql_timer_struct.rb#L36-L44) - -If you feel like taking on any of this start an issue and update us on your progress. - -## Installation - -Install/add to Gemfile - -```ruby -gem 'rack-mini-profiler' -``` - -NOTE: Be sure to require rack_mini_profiler below the `pg` and `mysql` gems in your Gemfile. rack_mini_profiler will identify these gems if they are loaded to insert instrumentation. If included too early no SQL will show up. - -#### Rails - -All you have to do is include the Gem and you're good to go in development. See notes below for use in production. - -#### Rails and manual initialization - -In case you need to make sure rack_mini_profiler initialized after all other gems. -Or you want to execute some code before rack_mini_profiler required. - -```ruby -gem 'rack-mini-profiler', require: false -``` -Note the `require: false` part - if omitted, it will cause the Railtie for the mino-profiler to -be loaded outright, and an attempt to re-initialize it manually will raise an exception. - -Then put initialize code in file like `config/initializers/rack_profiler.rb` - -```ruby -if Rails.env == 'development' - require 'rack-mini-profiler' - - # initialization is skipped so trigger it - Rack::MiniProfilerRails.initialize!(Rails.application) -end -``` - -#### Rack Builder - -```ruby -require 'rack-mini-profiler' -builder = Rack::Builder.new do - use Rack::MiniProfiler - - map('/') { run get } -end -``` - -#### Sinatra - -```ruby -require 'rack-mini-profiler' -class MyApp < Sinatra::Base - use Rack::MiniProfiler -end -``` - -### Flamegraphs - -To generate [flamegraphs](http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler): - -* add the **flamegraph** gem to your Gemfile -* visit a page in your app with `?pp=flamegraph` - -Flamegraph generation is supported in MRI 2.0 and 2.1 only. - - -## Access control in production - -rack-mini-profiler is designed with production profiling in mind. To enable that just run `Rack::MiniProfiler.authorize_request` once you know a request is allowed to profile. - -```ruby -# A hook in your ApplicationController -def authorize - if current_user.is_admin? - Rack::MiniProfiler.authorize_request - end -end -``` - -## Configuration - -Various aspects of rack-mini-profiler's behavior can be configured when your app boots. -For example in a Rails app, this should be done in an initializer: -**config/initializers/mini_profiler.rb** - -### Storage - -rack-mini-profiler stores its results so they can be shared later and aren't lost at the end of the request. - -There are 4 storage options: `MemoryStore`, `RedisStore`, `MemcacheStore`, and `FileStore`. - -`FileStore` is the default in Rails environments and will write files to `tmp/miniprofiler/*`. `MemoryStore` is the default otherwise. - -```ruby -# set MemoryStore -Rack::MiniProfiler.config.storage = Rack::MiniProfiler::MemoryStore - -# set RedisStore -if Rails.env.production? - uri = URI.parse(ENV["REDIS_SERVER_URL"]) - Rack::MiniProfiler.config.storage_options = { :host => uri.host, :port => uri.port, :password => uri.password } - Rack::MiniProfiler.config.storage = Rack::MiniProfiler::RedisStore -end -``` - -MemoryStore stores results in a processes heap - something that does not work well in a multi process environment. -FileStore stores results in the file system - something that may not work well in a multi machine environment. -RedisStore/MemcacheStore work in multi process and multi machine environments (RedisStore only saves results for up to 24 hours so it won't continue to fill up Redis). - -Additionally you may implement an AbstractStore for your own provider. - -### User result segregation - -MiniProfiler will attempt to keep all user results isolated, out-of-the-box the user provider uses the ip address: - -```ruby -Rack::MiniProfiler.config.user_provider = Proc.new{|env| Rack::Request.new(env).ip} -``` - -You can override (something that is very important in a multi-machine production setup): - -```ruby -Rack::MiniProfiler.config.user_provider = Proc.new{ |env| CurrentUser.get(env) } -``` - -The string this function returns should be unique for each user on the system (for anonymous you may need to fall back to ip address) - -### Configuration Options - -You can set configuration options using the configuration accessor on `Rack::MiniProfiler`. -For example: - -```ruby -Rack::MiniProfiler.config.position = 'right' -Rack::MiniProfiler.config.start_hidden = true -``` -The available configuration options are: - -* pre_authorize_cb - A lambda callback you can set to determine whether or not mini_profiler should be visible on a given request. Default in a Rails environment is only on in development mode. If in a Rack app, the default is always on. -* position - Can either be 'right' or 'left'. Default is 'left'. -* skip_schema_queries - Whether or not you want to log the queries about the schema of your tables. Default is 'false', 'true' in rails development. -* auto_inject (default true) - when false the miniprofiler script is not injected in the page -* backtrace_filter - a regex you can use to filter out unwanted lines from the backtraces -* toggle_shortcut (default Alt+P) - a jquery.hotkeys.js-style keyboard shortcut, used to toggle the mini_profiler's visibility. See http://code.google.com/p/js-hotkeys/ for more info. -* start_hidden (default false) - Whether or not you want the mini_profiler to be visible when loading a page -* backtrace_threshold_ms (default zero) - Minimum SQL query elapsed time before a backtrace is recorded. Backtrace recording can take a couple of milliseconds on rubies earlier than 2.0, impacting performance for very small queries. -* flamegraph_sample_rate (default 0.5ms) - How often fast_stack should get stack trace info to generate flamegraphs - -### Custom middleware ordering (required if using `Rack::Deflate` with Rails) - -If you are using `Rack::Deflate` with rails and rack-mini-profiler in its default configuration, -`Rack::MiniProfiler` will be injected (as always) at position 0 in the middleware stack. This -will result in it attempting to inject html into the already-compressed response body. To fix this, -the middleware ordering must be overriden. - -To do this, first add `, require: false` to the gemfile entry for rack-mini-profiler. -This will prevent the railtie from running. Then, customize the initialization -in the initializer like so: - -```ruby -require 'rack-mini-profiler' - -Rack::MiniProfilerRails.initialize!(Rails.application) - -Rails.application.middleware.delete(Rack::MiniProfiler) -Rails.application.middleware.insert_after(Rack::Deflater, Rack::MiniProfiler) -``` - -Deleting the middleware and then reinserting it is a bit inelegant, but -a sufficient and costless solution. It is possible that rack-mini-profiler might -support this scenario more directly if it is found that -there is significant need for this confriguration or that -the above recipe causes problems. - - -## Special query strings - -If you include the query string `pp=help` at the end of your request you will see the various options available. You can use these options to extend or contract the amount of diagnostics rack-mini-profiler gathers. - - -## Rails 2.X support - -To get MiniProfiler working with Rails 2.3.X you need to do the initialization manually as well as monkey patch away an incompatibility between activesupport and json_pure. - -Add the following code to your environment.rb (or just in a specific environment such as development.rb) for initialization and configuration of MiniProfiler. - -```ruby -# configure and initialize MiniProfiler -require 'rack-mini-profiler' -c = ::Rack::MiniProfiler.config -c.pre_authorize_cb = lambda { |env| - Rails.env.development? || Rails.env.production? -} -tmp = Rails.root.to_s + "/tmp/miniprofiler" -FileUtils.mkdir_p(tmp) unless File.exists?(tmp) -c.storage_options = {:path => tmp} -c.storage = ::Rack::MiniProfiler::FileStore -config.middleware.use(::Rack::MiniProfiler) -::Rack::MiniProfiler.profile_method(ActionController::Base, :process) {|action| "Executing action: #{action}"} -::Rack::MiniProfiler.profile_method(ActionView::Template, :render) {|x,y| "Rendering: #{path_without_format_and_extension}"} - -# monkey patch away an activesupport and json_pure incompatability -# http://pivotallabs.com/users/alex/blog/articles/1332-monkey-patch-of-the-day-activesupport-vs-json-pure-vs-ruby-1-8 -if JSON.const_defined?(:Pure) - class JSON::Pure::Generator::State - include ActiveSupport::CoreExtensions::Hash::Except - end -end -``` - -## Running the Specs - -``` -$ rake build -$ rake spec -``` - -Additionally you can also run `autotest` if you like. - -## Licence - -The MIT License (MIT) - -Copyright (c) 2013 Sam Saffron - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/rack-mini-profiler/Rakefile b/lib/rack-mini-profiler/Rakefile deleted file mode 100644 index a908b5b62..000000000 --- a/lib/rack-mini-profiler/Rakefile +++ /dev/null @@ -1,46 +0,0 @@ -# Rakefile -require 'rubygems' -require 'bundler' -Bundler.setup(:default, :test) - -task :default => [:spec] - -require 'rspec/core' -require 'rspec/core/rake_task' -RSpec::Core::RakeTask.new(:spec) do |spec| - spec.pattern = FileList['spec/**/*_spec.rb'] -end - -desc "builds a gem" -task :build => :update_asset_version do - `gem build rack-mini-profiler.gemspec 1>&2` -end - -desc "compile less" -task :compile_less => :copy_files do - `lessc lib/html/includes.less > lib/html/includes.css` -end - -desc "update asset version file" -task :update_asset_version => :compile_less do - require 'digest/md5' - h = [] - Dir.glob('lib/html/*.{js,html,css,tmpl}').each do |f| - h << Digest::MD5.hexdigest(::File.read(f)) - end - File.open('lib/mini_profiler/version.rb','w') do |f| - f.write \ -"module Rack - class MiniProfiler - VERSION = '#{Digest::MD5.hexdigest(h.sort.join(''))}'.freeze - end -end" - end -end - - -desc "copy files from other parts of the tree" -task :copy_files do - # TODO grab files from MiniProfiler/UI -end - diff --git a/lib/rack-mini-profiler/autotest/discover.rb b/lib/rack-mini-profiler/autotest/discover.rb deleted file mode 100644 index de32a0121..000000000 --- a/lib/rack-mini-profiler/autotest/discover.rb +++ /dev/null @@ -1,2 +0,0 @@ -Autotest.add_discovery { "rspec2" } - diff --git a/lib/rack-mini-profiler/lib/html/includes.css b/lib/rack-mini-profiler/lib/html/includes.css deleted file mode 100644 index d96528b8d..000000000 --- a/lib/rack-mini-profiler/lib/html/includes.css +++ /dev/null @@ -1,451 +0,0 @@ -.profiler-result, -.profiler-queries { - color: #555; - line-height: 1; - font-size: 12px; -} -.profiler-result pre, -.profiler-queries pre, -.profiler-result code, -.profiler-queries code, -.profiler-result label, -.profiler-queries label, -.profiler-result table, -.profiler-queries table, -.profiler-result tbody, -.profiler-queries tbody, -.profiler-result thead, -.profiler-queries thead, -.profiler-result tfoot, -.profiler-queries tfoot, -.profiler-result tr, -.profiler-queries tr, -.profiler-result th, -.profiler-queries th, -.profiler-result td, -.profiler-queries td { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; - background-color: transparent; - overflow: visible; - max-height: none; -} -.profiler-result table, -.profiler-queries table { - border-collapse: collapse; - border-spacing: 0; -} -.profiler-result a, -.profiler-queries a, -.profiler-result a:hover, -.profiler-queries a:hover { - cursor: pointer; - color: #0077cc; -} -.profiler-result a, -.profiler-queries a { - text-decoration: none; -} -.profiler-result a:hover, -.profiler-queries a:hover { - text-decoration: underline; -} -.profiler-result { - font-family: Helvetica, Arial, sans-serif; -} -.profiler-result .profiler-toggle-duration-with-children { - float: right; -} -.profiler-result table.profiler-client-timings { - margin-top: 10px; -} -.profiler-result .profiler-label { - color: #555555; - overflow: hidden; - text-overflow: ellipsis; -} -.profiler-result .profiler-unit { - color: #aaaaaa; -} -.profiler-result .profiler-trivial { - display: none; -} -.profiler-result .profiler-trivial td, -.profiler-result .profiler-trivial td * { - color: #aaaaaa !important; -} -.profiler-result pre, -.profiler-result code, -.profiler-result .profiler-number, -.profiler-result .profiler-unit { - font-family: Consolas, monospace, serif; -} -.profiler-result .profiler-number { - color: #111111; -} -.profiler-result .profiler-info { - text-align: right; -} -.profiler-result .profiler-info .profiler-name { - float: left; -} -.profiler-result .profiler-info .profiler-server-time { - white-space: nowrap; -} -.profiler-result .profiler-timings th { - background-color: #fff; - color: #aaaaaa; - text-align: right; -} -.profiler-result .profiler-timings th, -.profiler-result .profiler-timings td { - white-space: nowrap; -} -.profiler-result .profiler-timings .profiler-duration-with-children { - display: none; -} -.profiler-result .profiler-timings .profiler-duration { - font-family: Consolas, monospace, serif; - color: #111111; - text-align: right; -} -.profiler-result .profiler-timings .profiler-indent { - letter-spacing: 4px; -} -.profiler-result .profiler-timings .profiler-queries-show .profiler-number, -.profiler-result .profiler-timings .profiler-queries-show .profiler-unit { - color: #0077cc; -} -.profiler-result .profiler-timings .profiler-queries-duration { - padding-left: 6px; -} -.profiler-result .profiler-timings .profiler-percent-in-sql { - white-space: nowrap; - text-align: right; -} -.profiler-result .profiler-timings tfoot td { - padding-top: 10px; - text-align: right; -} -.profiler-result .profiler-timings tfoot td a { - font-size: 95%; - display: inline-block; - margin-left: 12px; -} -.profiler-result .profiler-timings tfoot td a:first-child { - float: left; - margin-left: 0px; -} -.profiler-result .profiler-timings tfoot td a.profiler-custom-link { - float: left; -} -.profiler-result .profiler-queries { - font-family: Helvetica, Arial, sans-serif; -} -.profiler-result .profiler-queries .profiler-stack-trace { - margin-bottom: 15px; -} -.profiler-result .profiler-queries pre { - font-family: Consolas, monospace, serif; - white-space: pre-wrap; -} -.profiler-result .profiler-queries th { - background-color: #fff; - border-bottom: 1px solid #555; - font-weight: bold; - padding: 15px; - white-space: nowrap; -} -.profiler-result .profiler-queries td { - padding: 15px; - text-align: left; - background-color: #fff; -} -.profiler-result .profiler-queries td:last-child { - padding-right: 25px; -} -.profiler-result .profiler-queries .profiler-odd td { - background-color: #e5e5e5; -} -.profiler-result .profiler-queries .profiler-since-start, -.profiler-result .profiler-queries .profiler-duration { - text-align: right; -} -.profiler-result .profiler-queries .profiler-info div { - text-align: right; - margin-bottom: 5px; -} -.profiler-result .profiler-queries .profiler-gap-info, -.profiler-result .profiler-queries .profiler-gap-info td { - background-color: #ccc; -} -.profiler-result .profiler-queries .profiler-gap-info .profiler-unit { - color: #777; -} -.profiler-result .profiler-queries .profiler-gap-info .profiler-info { - text-align: right; -} -.profiler-result .profiler-queries .profiler-gap-info.profiler-trivial-gaps { - display: none; -} -.profiler-result .profiler-queries .profiler-trivial-gap-container { - text-align: center; -} -.profiler-result .profiler-queries .str { - color: #800000; -} -.profiler-result .profiler-queries .kwd { - color: #00008b; -} -.profiler-result .profiler-queries .com { - color: #808080; -} -.profiler-result .profiler-queries .typ { - color: #2b91af; -} -.profiler-result .profiler-queries .lit { - color: #800000; -} -.profiler-result .profiler-queries .pun { - color: #000000; -} -.profiler-result .profiler-queries .pln { - color: #000000; -} -.profiler-result .profiler-queries .tag { - color: #800000; -} -.profiler-result .profiler-queries .atn { - color: #ff0000; -} -.profiler-result .profiler-queries .atv { - color: #0000ff; -} -.profiler-result .profiler-queries .dec { - color: #800080; -} -.profiler-result .profiler-warning, -.profiler-result .profiler-warning *, -.profiler-result .profiler-warning .profiler-queries-show, -.profiler-result .profiler-warning .profiler-queries-show .profiler-unit { - color: #f00; -} -.profiler-result .profiler-warning:hover, -.profiler-result .profiler-warning *:hover, -.profiler-result .profiler-warning .profiler-queries-show:hover, -.profiler-result .profiler-warning .profiler-queries-show .profiler-unit:hover { - color: #f00; -} -.profiler-result .profiler-nuclear { - color: #f00; - font-weight: bold; - padding-right: 2px; -} -.profiler-result .profiler-nuclear:hover { - color: #f00; -} -.profiler-results { - z-index: 2147483643; - position: fixed; - top: 0px; -} -.profiler-results.profiler-left { - left: 0px; -} -.profiler-results.profiler-left.profiler-no-controls .profiler-result:last-child .profiler-button, -.profiler-results.profiler-left .profiler-controls { - -webkit-border-bottom-right-radius: 10px; - -moz-border-radius-bottomright: 10px; - border-bottom-right-radius: 10px; -} -.profiler-results.profiler-left .profiler-button, -.profiler-results.profiler-left .profiler-controls { - border-right: 1px solid #888888; -} -.profiler-results.profiler-right { - right: 0px; -} -.profiler-results.profiler-right.profiler-no-controls .profiler-result:last-child .profiler-button, -.profiler-results.profiler-right .profiler-controls { - -webkit-border-bottom-left-radius: 10px; - -moz-border-radius-bottomleft: 10px; - border-bottom-left-radius: 10px; -} -.profiler-results.profiler-right .profiler-button, -.profiler-results.profiler-right .profiler-controls { - border-left: 1px solid #888888; -} -.profiler-results .profiler-button, -.profiler-results .profiler-controls { - display: none; - z-index: 2147483640; - border-bottom: 1px solid #888888; - background-color: #fff; - padding: 4px 7px; - text-align: right; - cursor: pointer; -} -.profiler-results .profiler-button.profiler-button-active, -.profiler-results .profiler-controls.profiler-button-active { - background-color: maroon; -} -.profiler-results .profiler-button.profiler-button-active .profiler-number, -.profiler-results .profiler-controls.profiler-button-active .profiler-number, -.profiler-results .profiler-button.profiler-button-active .profiler-nuclear, -.profiler-results .profiler-controls.profiler-button-active .profiler-nuclear { - color: #fff; - font-weight: bold; -} -.profiler-results .profiler-button.profiler-button-active .profiler-unit, -.profiler-results .profiler-controls.profiler-button-active .profiler-unit { - color: #fff; - font-weight: normal; -} -.profiler-results .profiler-controls { - display: block; - font-size: 12px; - font-family: Consolas, monospace, serif; - cursor: default; - text-align: center; -} -.profiler-results .profiler-controls span { - border-right: 1px solid #aaaaaa; - padding-right: 5px; - margin-right: 5px; - cursor: pointer; -} -.profiler-results .profiler-controls span:last-child { - border-right: none; -} -.profiler-results .profiler-popup { - display: none; - z-index: 2147483641; - position: absolute; - background-color: #fff; - border: 1px solid #aaa; - padding: 5px 10px; - text-align: left; - line-height: 18px; - overflow: auto; - -moz-box-shadow: 0px 1px 15px #555555; - -webkit-box-shadow: 0px 1px 15px #555555; - box-shadow: 0px 1px 15px #555555; -} -.profiler-results .profiler-popup .profiler-info { - margin-bottom: 3px; - padding-bottom: 2px; - border-bottom: 1px solid #ddd; -} -.profiler-results .profiler-popup .profiler-info .profiler-name { - font-size: 110%; - font-weight: bold; -} -.profiler-results .profiler-popup .profiler-info .profiler-name .profiler-overall-duration { - display: none; -} -.profiler-results .profiler-popup .profiler-info .profiler-server-time { - font-size: 95%; -} -.profiler-results .profiler-popup .profiler-timings th, -.profiler-results .profiler-popup .profiler-timings td { - padding-left: 6px; - padding-right: 6px; -} -.profiler-results .profiler-popup .profiler-timings th { - font-size: 95%; - padding-bottom: 3px; -} -.profiler-results .profiler-popup .profiler-timings .profiler-label { - max-width: 275px; -} -.profiler-results .profiler-queries { - display: none; - z-index: 2147483643; - position: absolute; - overflow-y: auto; - overflow-x: auto; - background-color: #fff; -} -.profiler-results .profiler-queries th { - font-size: 17px; -} -.profiler-results.profiler-min .profiler-result { - display: none; -} -.profiler-results.profiler-min .profiler-controls span { - display: none; -} -.profiler-results.profiler-min .profiler-controls .profiler-min-max { - border-right: none; - padding: 0px; - margin: 0px; -} -.profiler-queries-bg { - z-index: 2147483642; - display: none; - background: #000; - opacity: 0.7; - position: absolute; - top: 0px; - left: 0px; - min-width: 100%; -} -.profiler-result-full .profiler-result { - width: 950px; - margin: 30px auto; -} -.profiler-result-full .profiler-result .profiler-button { - display: none; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-info { - font-size: 25px; - border-bottom: 1px solid #aaaaaa; - padding-bottom: 3px; - margin-bottom: 25px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-info .profiler-overall-duration { - padding-right: 20px; - font-size: 80%; - color: #888; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings td, -.profiler-result-full .profiler-result .profiler-popup .profiler-timings th { - padding-left: 8px; - padding-right: 8px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings th { - padding-bottom: 7px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings td { - font-size: 14px; - padding-bottom: 4px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings td:first-child { - padding-left: 10px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings .profiler-label { - max-width: 550px; -} -.profiler-result-full .profiler-result .profiler-queries { - margin: 25px 0; -} -.profiler-result-full .profiler-result .profiler-queries table { - width: 100%; -} -.profiler-result-full .profiler-result .profiler-queries th { - font-size: 16px; - color: #555; - line-height: 20px; -} -.profiler-result-full .profiler-result .profiler-queries td { - padding: 15px 10px; - text-align: left; -} -.profiler-result-full .profiler-result .profiler-queries .profiler-info div { - text-align: right; - margin-bottom: 5px; -} diff --git a/lib/rack-mini-profiler/lib/html/includes.js b/lib/rack-mini-profiler/lib/html/includes.js deleted file mode 100644 index d8b4de083..000000000 --- a/lib/rack-mini-profiler/lib/html/includes.js +++ /dev/null @@ -1,960 +0,0 @@ -"use strict"; -var MiniProfiler = (function () { - var $; - - var options, - container, - controls, - fetchedIds = [], - fetchingIds = [], // so we never pull down a profiler twice - ajaxStartTime - ; - - var hasLocalStorage = function () { - try { - return 'localStorage' in window && window['localStorage'] !== null; - } catch (e) { - return false; - } - }; - - var getVersionedKey = function (keyPrefix) { - return keyPrefix + '-' + options.version; - }; - - var save = function (keyPrefix, value) { - if (!hasLocalStorage()) { return; } - - // clear old keys with this prefix, if any - for (var i = 0; i < localStorage.length; i++) { - if ((localStorage.key(i) || '').indexOf(keyPrefix) > -1) { - localStorage.removeItem(localStorage.key(i)); - } - } - - // save under this version - localStorage[getVersionedKey(keyPrefix)] = value; - }; - - var load = function (keyPrefix) { - if (!hasLocalStorage()) { return null; } - - return localStorage[getVersionedKey(keyPrefix)]; - }; - - var fetchTemplates = function (success) { - var key = 'templates', - cached = load(key); - - if (cached) { - $('body').append(cached); - success(); - } - else { - $.get(options.path + 'includes.tmpl?v=' + options.version, function (data) { - if (data) { - save(key, data); - $('body').append(data); - success(); - } - }); - } - }; - - var getClientPerformance = function() { - return window.performance == null ? null : window.performance; - }; - - var fetchResults = function (ids) { - var clientPerformance, clientProbes, i, j, p, id, idx; - - for (i = 0; i < ids.length; i++) { - id = ids[i]; - - clientPerformance = null; - clientProbes = null; - - if (window.mPt) { - clientProbes = mPt.results(); - for (j = 0; j < clientProbes.length; j++) { - clientProbes[j].d = clientProbes[j].d.getTime(); - } - mPt.flush(); - } - - if (id == options.currentId) { - - clientPerformance = getClientPerformance(); - - if (clientPerformance != null) { - // ie is buggy strip out functions - var copy = { navigation: {}, timing: {} }; - - var timing = $.extend({}, clientPerformance.timing); - - for (p in timing) { - if (timing.hasOwnProperty(p) && !$.isFunction(timing[p])) { - copy.timing[p] = timing[p]; - } - } - if (clientPerformance.navigation) { - copy.navigation.redirectCount = clientPerformance.navigation.redirectCount; - } - clientPerformance = copy; - - // hack to add chrome timings - if (window.chrome && window.chrome.loadTimes) { - var chromeTimes = window.chrome.loadTimes(); - if (chromeTimes.firstPaintTime) { - clientPerformance.timing["First Paint Time"] = Math.round(chromeTimes.firstPaintTime * 1000); - } - if (chromeTimes.firstPaintTime) { - clientPerformance.timing["First Paint After Load Time"] = Math.round(chromeTimes.firstPaintAfterLoadTime * 1000); - } - - } - } - } else if (ajaxStartTime != null && clientProbes && clientProbes.length > 0) { - clientPerformance = { timing: { navigationStart: ajaxStartTime.getTime() } }; - ajaxStartTime = null; - } - - if ($.inArray(id, fetchedIds) < 0 && $.inArray(id, fetchingIds) < 0) { - idx = fetchingIds.push(id) - 1; - - $.ajax({ - url: options.path + 'results', - data: { id: id, clientPerformance: clientPerformance, clientProbes: clientProbes, popup: 1 }, - dataType: 'json', - global: false, - type: 'POST', - success: function (json) { - fetchedIds.push(id); - if (json != "hidden") { - buttonShow(json); - } - }, - complete: function () { - fetchingIds.splice(idx, 1); - } - }); - } - } - }; - - var renderTemplate = function (json) { - return $('#profilerTemplate').tmpl(json); - }; - - var buttonShow = function (json) { - var result = renderTemplate(json); - - if (controls) - result.insertBefore(controls); - else - result.appendTo(container); - - var button = result.find('.profiler-button'), - popup = result.find('.profiler-popup'); - - // button will appear in corner with the total profiling duration - click to show details - button.click(function () { buttonClick(button, popup); }); - - // small duration steps and the column with aggregate durations are hidden by default; allow toggling - toggleHidden(popup); - - // lightbox in the queries - popup.find('.profiler-queries-show').click(function () { queriesShow($(this), result); }); - - // limit count - if (container.find('.profiler-result').length > options.maxTracesToShow) - container.find('.profiler-result').first().remove(); - button.show(); - }; - - var toggleHidden = function (popup) { - var trivial = popup.find('.profiler-toggle-trivial'); - var childrenTime = popup.find('.profiler-toggle-duration-with-children'); - var trivialGaps = popup.parent().find('.profiler-toggle-trivial-gaps'); - - var toggleIt = function (node) { - var link = $(node), - klass = "profiler-" + link.attr('class').substr('profiler-toggle-'.length), - isHidden = link.text().indexOf('show') > -1; - - popup.parent().find('.' + klass).toggle(isHidden); - link.text(link.text().replace(isHidden ? 'show' : 'hide', isHidden ? 'hide' : 'show')); - - popupPreventHorizontalScroll(popup); - }; - - childrenTime.add(trivial).add(trivialGaps).click(function () { - toggleIt(this); - }); - - // if option is set or all our timings are trivial, go ahead and show them - if (options.showTrivial || trivial.data('show-on-load')) { - toggleIt(trivial); - } - // if option is set, go ahead and show time with children - if (options.showChildrenTime) { - toggleIt(childrenTime); - } - }; - - var buttonClick = function (button, popup) { - // we're toggling this button/popup - if (popup.is(':visible')) { - popupHide(button, popup); - } - else { - var visiblePopups = container.find('.profiler-popup:visible'), - theirButtons = visiblePopups.siblings('.profiler-button'); - - // hide any other popups - popupHide(theirButtons, visiblePopups); - - // before showing the one we clicked - popupShow(button, popup); - } - }; - - var popupShow = function (button, popup) { - button.addClass('profiler-button-active'); - - popupSetDimensions(button, popup); - - popup.show(); - - popupPreventHorizontalScroll(popup); - }; - - var popupSetDimensions = function (button, popup) { - var top = button.position().top - 1, // position next to the button we clicked - windowHeight = $(window).height(), - maxHeight = windowHeight - top - 40; // make sure the popup doesn't extend below the fold - - popup - .css({ 'top': top, 'max-height': maxHeight }) - .css(options.renderPosition, button.outerWidth() - 3); // move left or right, based on config - }; - - var popupPreventHorizontalScroll = function (popup) { - var childrenHeight = 0; - - popup.children().each(function () { childrenHeight += $(this).height(); }); - - popup.css({ 'padding-right': childrenHeight > popup.height() ? 40 : 10 }); - }; - - var popupHide = function (button, popup) { - button.removeClass('profiler-button-active'); - popup.hide(); - }; - - var queriesShow = function (link, result) { - - var px = 30, - win = $(window), - width = win.width() - 2 * px, - height = win.height() - 2 * px, - queries = result.find('.profiler-queries'); - - // opaque background - $('
').appendTo('body').css({ 'height': $(document).height() }).show(); - - // center the queries and ensure long content is scrolled - queries.css({ 'top': px, 'max-height': height, 'width': width }).css(options.renderPosition, px) - .find('table').css({ 'width': width }); - - // have to show everything before we can get a position for the first query - queries.show(); - - queriesScrollIntoView(link, queries, queries); - - // syntax highlighting - prettyPrint(); - }; - - var queriesScrollIntoView = function (link, queries, whatToScroll) { - var id = link.closest('tr').attr('data-timing-id'), - cells = queries.find('tr[data-timing-id="' + id + '"] td'); - - // ensure they're in view - whatToScroll.scrollTop(whatToScroll.scrollTop() + cells.first().position().top - 100); - - // highlight and then fade back to original bg color; do it ourselves to prevent any conflicts w/ jquery.UI or other implementations of Resig's color plugin - cells.each(function () { - var cell = $(this), - highlightHex = '#FFFFBB', - highlightRgb = getRGB(highlightHex), - originalRgb = getRGB(cell.css('background-color')), - getColorDiff = function (fx, i) { - // adapted from John Resig's color plugin: http://plugins.jquery.com/project/color - return Math.max(Math.min(parseInt((fx.pos * (originalRgb[i] - highlightRgb[i])) + highlightRgb[i], 10), 255), 0); - }; - - // we need to animate some other property to piggy-back on the step function, so I choose you, opacity! - cell.css({ 'opacity': 1, 'background-color': highlightHex }) - .animate({ 'opacity': 1 }, { duration: 2000, step: function (now, fx) { - fx.elem.style.backgroundColor = "rgb(" + [getColorDiff(fx, 0), getColorDiff(fx, 1), getColorDiff(fx, 2)].join(",") + ")"; - } - }); - }); - }; - - // Color Conversion functions from highlightFade - // By Blair Mitchelmore - // http://jquery.offput.ca/highlightFade/ - // Parse strings looking for color tuples [255,255,255] - var getRGB = function (color) { - var result; - - // Check if we're already dealing with an array of colors - if (color && color.constructor == Array && color.length == 3) return color; - - // Look for rgb(num,num,num) - if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])]; - - // Look for rgb(num%,num%,num%) - if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) return [parseFloat(result[1]) * 2.55, parseFloat(result[2]) * 2.55, parseFloat(result[3]) * 2.55]; - - // Look for #a0b1c2 - if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]; - - // Look for #fff - if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) return [parseInt(result[1] + result[1], 16), parseInt(result[2] + result[2], 16), parseInt(result[3] + result[3], 16)]; - - // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 - if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) return colors['transparent']; - - return null; - }; - - var bindDocumentEvents = function () { - $(document).bind('click keyup', function (e) { - - // this happens on every keystroke, and :visible is crazy expensive in IE <9 - // and in this case, the display:none check is sufficient. - var popup = $('.profiler-popup').filter(function () { return $(this).css("display") !== "none"; }); - - if (!popup.length) { - return; - } - - var button = popup.siblings('.profiler-button'), - queries = popup.closest('.profiler-result').find('.profiler-queries'), - bg = $('.profiler-queries-bg'), - isEscPress = e.type == 'keyup' && e.which == 27, - hidePopup = false, - hideQueries = false; - - if (bg.is(':visible')) { - hideQueries = isEscPress || (e.type == 'click' && !$.contains(queries[0], e.target) && !$.contains(popup[0], e.target)); - } - else if (popup.is(':visible')) { - hidePopup = isEscPress || (e.type == 'click' && !$.contains(popup[0], e.target) && !$.contains(button[0], e.target) && button[0] != e.target); - } - - if (hideQueries) { - bg.remove(); - queries.hide(); - } - - if (hidePopup) { - popupHide(button, popup); - } - }); - $(document).bind('keydown', options.toggleShortcut, function(e) { - $('.profiler-results').toggle(); - }); - }; - - var initFullView = function () { - - // first, get jquery tmpl, then render and bind handlers - fetchTemplates(function () { - - // profiler will be defined in the full page's head - renderTemplate(profiler).appendTo(container); - - var popup = $('.profiler-popup'); - - toggleHidden(popup); - - prettyPrint(); - - // since queries are already shown, just highlight and scroll when clicking a "1 sql" link - popup.find('.profiler-queries-show').click(function () { - queriesScrollIntoView($(this), $('.profiler-queries'), $(document)); - }); - }); - }; - - var initControls = function (container) { - if (options.showControls) { - controls = $('
mc
').appendTo(container); - - $('.profiler-controls .profiler-min-max').click(function () { - container.toggleClass('profiler-min'); - }); - - container.hover(function () { - if ($(this).hasClass('profiler-min')) { - $(this).find('.profiler-min-max').show(); - } - }, - function () { - if ($(this).hasClass('profiler-min')) { - $(this).find('.profiler-min-max').hide(); - } - }); - - $('.profiler-controls .profiler-clear').click(function () { - container.find('.profiler-result').remove(); - }); - } - else { - container.addClass('profiler-no-controls'); - } - }; - - var initPopupView = function () { - - if (options.authorized) { - // all fetched profilings will go in here - container = $('
').appendTo('body'); - - // MiniProfiler.RenderIncludes() sets which corner to render in - default is upper left - container.addClass("profiler-" + options.renderPosition); - - //initialize the controls - initControls(container); - - // we'll render results json via a jquery.tmpl - after we get the templates, we'll fetch the initial json to populate it - fetchTemplates(function () { - // get master page profiler results - fetchResults(options.ids); - }); - if (options.startHidden) container.hide(); - } - else { - fetchResults(options.ids); - } - - var jQueryAjaxComplete = function (e, xhr, settings) { - if (xhr) { - // should be an array of strings, e.g. ["008c4813-9bd7-443d-9376-9441ec4d6a8c","16ff377b-8b9c-4c20-a7b5-97cd9fa7eea7"] - var stringIds = xhr.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - }; - - // fetch profile results for any ajax calls - // note, this does not use $ cause we want to hook into the main jQuery - if (jQuery && jQuery(document) && jQuery(document).ajaxComplete) { - jQuery(document).ajaxComplete(jQueryAjaxComplete); - } - - if (jQuery && jQuery(document).ajaxStart) - jQuery(document).ajaxStart(function () { ajaxStartTime = new Date(); }); - - // fetch results after ASP Ajax calls - if (typeof (Sys) != 'undefined' && typeof (Sys.WebForms) != 'undefined' && typeof (Sys.WebForms.PageRequestManager) != 'undefined') { - // Get the instance of PageRequestManager. - var PageRequestManager = Sys.WebForms.PageRequestManager.getInstance(); - - PageRequestManager.add_endRequest(function (sender, args) { - if (args) { - var response = args.get_response(); - if (response.get_responseAvailable() && response._xmlHttpRequest != null) { - var stringIds = args.get_response().getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - } - }); - } - - // more Asp.Net callbacks - if (typeof (WebForm_ExecuteCallback) == "function") { - WebForm_ExecuteCallback = (function (callbackObject) { - // Store original function - var original = WebForm_ExecuteCallback; - - return function (callbackObject) { - original(callbackObject); - - var stringIds = callbackObject.xmlRequest.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - }; - - })(); - } - - // also fetch results after ExtJS requests, in case it is being used - if (typeof (Ext) != 'undefined' && typeof (Ext.Ajax) != 'undefined' && typeof (Ext.Ajax.on) != 'undefined') { - // Ext.Ajax is a singleton, so we just have to attach to its 'requestcomplete' event - Ext.Ajax.on('requestcomplete', function (e, xhr, settings) { - //iframed file uploads don't have headers - if (!xhr || !xhr.getResponseHeader) { - return; - } - - var stringIds = xhr.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - }); - } - - if (typeof (MooTools) != 'undefined' && typeof (Request) != 'undefined') { - Request.prototype.addEvents({ - onComplete: function() { - var stringIds = this.xhr.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - }); - } - - // add support for AngularJS, which use the basic XMLHttpRequest object. - if (window.angular && typeof (XMLHttpRequest) != 'undefined') { - var _send = XMLHttpRequest.prototype.send; - - XMLHttpRequest.prototype.send = function sendReplacement(data) { - this._onreadystatechange = this.onreadystatechange; - - this.onreadystatechange = function onReadyStateChangeReplacement() { - if (this.readyState == 4) { - var stringIds = this.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - - return this._onreadystatechange.apply(this, arguments); - }; - - return _send.apply(this, arguments); - }; - } - - // some elements want to be hidden on certain doc events - bindDocumentEvents(); - }; - - return { - - init: function () { - var script = document.getElementById('mini-profiler'); - if (!script || !script.getAttribute) return; - - options = (function () { - var version = script.getAttribute('data-version'); - var path = script.getAttribute('data-path'); - - var currentId = script.getAttribute('data-current-id'); - - var ids = script.getAttribute('data-ids'); - if (ids) ids = ids.split(','); - - var position = script.getAttribute('data-position'); - - var toggleShortcut = script.getAttribute('data-toggle-shortcut'); - - if (script.getAttribute('data-max-traces')) { - var maxTraces = parseInt(script.getAttribute('data-max-traces'), 10); - } - - if (script.getAttribute('data-trivial') === 'true') var trivial = true; - if (script.getAttribute('data-children') == 'true') var children = true; - if (script.getAttribute('data-controls') == 'true') var controls = true; - if (script.getAttribute('data-authorized') == 'true') var authorized = true; - if (script.getAttribute('data-start-hidden') == 'true') var startHidden = true; - - return { - ids: ids, - path: path, - version: version, - renderPosition: position, - showTrivial: trivial, - showChildrenTime: children, - maxTracesToShow: maxTraces, - showControls: controls, - currentId: currentId, - authorized: authorized, - toggleShortcut: toggleShortcut, - startHidden: startHidden - }; - })(); - - var doInit = function () { - // when rendering a shared, full page, this div will exist - container = $('.profiler-result-full'); - if (container.length) { - if (window.location.href.indexOf("&trivial=1") > 0) { - options.showTrivial = true; - } - initFullView(); - } - else { - initPopupView(); - } - }; - - // this preserves debugging - var load = function (s, f) { - var sc = document.createElement("script"); - sc.async = "async"; - sc.type = "text/javascript"; - sc.src = s; - var done = false; - sc.onload = sc.onreadystatechange = function (_, abort) { - if (!sc.readyState || /loaded|complete/.test(sc.readyState)) { - if (!abort && !done) { done = true; f(); } - } - }; - document.getElementsByTagName('head')[0].appendChild(sc); - }; - - var wait = 0; - var finish = false; - var deferInit = function() { - if (finish) return; - if (window.performance && window.performance.timing && window.performance.timing.loadEventEnd === 0 && wait < 10000) { - setTimeout(deferInit, 100); - wait += 100; - } else { - finish = true; - init(); - } - }; - - var init = function() { - if (options.authorized) { - var url = options.path + "includes.css?v=" + options.version; - if (document.createStyleSheet) { - document.createStyleSheet(url); - } else { - $('head').append($('')); - } - if (!$.tmpl) { - load(options.path + 'jquery.tmpl.js?v=' + options.version, doInit); - } else { - doInit(); - } - } else { - doInit(); - } - - // jquery.hotkeys.js - // https://github.com/jeresig/jquery.hotkeys/blob/master/jquery.hotkeys.js - - (function(d){function h(g){if("string"===typeof g.data){var h=g.handler,j=g.data.toLowerCase().split(" ");g.handler=function(b){if(!(this!==b.target&&(/textarea|select/i.test(b.target.nodeName)||"text"===b.target.type))){var c="keypress"!==b.type&&d.hotkeys.specialKeys[b.which],e=String.fromCharCode(b.which).toLowerCase(),a="",f={};b.altKey&&"alt"!==c&&(a+="alt+");b.ctrlKey&&"ctrl"!==c&&(a+="ctrl+");b.metaKey&&(!b.ctrlKey&&"meta"!==c)&&(a+="meta+");b.shiftKey&&"shift"!==c&&(a+="shift+");c?f[a+c]= - !0:(f[a+e]=!0,f[a+d.hotkeys.shiftNums[e]]=!0,"shift+"===a&&(f[d.hotkeys.shiftNums[e]]=!0));c=0;for(e=j.length;c","/":"?","\\":"|"}};d.each(["keydown","keyup","keypress"],function(){d.event.special[this]={add:h}})})(MiniProfiler.jQuery); - - }; - - var major, minor; - if (typeof(jQuery) == 'function') { - var jQueryVersion = jQuery.fn.jquery.split('.'); - major = parseInt(jQueryVersion[0], 10); - minor = parseInt(jQueryVersion[1], 10); - } - - - if (major === 2 || (major === 1 && minor >= 7)) { - MiniProfiler.jQuery = $ = jQuery; - $(deferInit); - } else { - load(options.path + "jquery.1.7.1.js?v=" + options.version, function() { - MiniProfiler.jQuery = $ = jQuery.noConflict(true); - $(deferInit); - }); - } - }, - - getClientTimingByName: function (clientTiming, name) { - - for (var i = 0; i < clientTiming.Timings.length; i++) { - if (clientTiming.Timings[i].Name == name) { - return clientTiming.Timings[i]; - } - } - return { Name: name, Duration: "", Start: "" }; - }, - - renderDate: function (jsonDate) { // JavaScriptSerializer sends dates as /Date(1308024322065)/ - if (jsonDate) { - return (typeof jsonDate === 'string') ? new Date(parseInt(jsonDate.replace("/Date(", "").replace(")/", ""), 10)).toUTCString() : jsonDate; - } - }, - - renderIndent: function (depth) { - var result = ''; - for (var i = 0; i < depth; i++) { - result += ' '; - } - return result; - }, - - renderExecuteType: function (typeId) { - // see StackExchange.Profiling.ExecuteType enum - switch (typeId) { - case 0: return 'None'; - case 1: return 'NonQuery'; - case 2: return 'Scalar'; - case 3: return 'Reader'; - } - }, - - shareUrl: function (id) { - return options.path + 'results?id=' + id; - }, - - getClientTimings: function (clientTimings) { - var list = []; - var t; - - if (!clientTimings.Timings) return []; - - for (var i = 0; i < clientTimings.Timings.length; i++) { - t = clientTimings.Timings[i]; - var trivial = t.Name != "Dom Complete" && t.Name != "Response" && t.Name != "First Paint Time"; - trivial = t.Duration < 2 ? trivial : false; - list.push( - { - isTrivial: trivial, - name: t.Name, - duration: t.Duration, - start: t.Start - }); - } - - list.sort(function (a, b) { return a.start - b.start; }); - return list; - }, - - getSqlTimings: function (root) { - var result = [], - addToResults = function (timing) { - if (timing.SqlTimings) { - for (var i = 0, sqlTiming; i < timing.SqlTimings.length; i++) { - sqlTiming = timing.SqlTimings[i]; - - // HACK: add info about the parent Timing to each SqlTiming so UI can render - sqlTiming.ParentTimingName = timing.Name; - result.push(sqlTiming); - } - } - - if (timing.Children) { - for (var i = 0; i < timing.Children.length; i++) { - addToResults(timing.Children[i]); - } - } - }; - - // start adding at the root and recurse down - addToResults(root); - - var removeDuration = function(list, duration) { - - var newList = []; - for (var i = 0; i < list.length; i++) { - - var item = list[i]; - if (duration.start > item.start) { - if (duration.start > item.finish) { - newList.push(item); - continue; - } - newList.push({ start: item.start, finish: duration.start }); - } - - if (duration.finish < item.finish) { - if (duration.finish < item.start) { - newList.push(item); - continue; - } - newList.push({ start: duration.finish, finish: item.finish }); - } - } - - return newList; - }; - - var processTimes = function (elem, parent) { - var duration = { start: elem.StartMilliseconds, finish: (elem.StartMilliseconds + elem.DurationMilliseconds) }; - elem.richTiming = [duration]; - if (parent != null) { - elem.parent = parent; - elem.parent.richTiming = removeDuration(elem.parent.richTiming, duration); - } - - if (elem.Children) { - for (var i = 0; i < elem.Children.length; i++) { - processTimes(elem.Children[i], elem); - } - } - }; - - processTimes(root, null); - - // sort results by time - result.sort(function (a, b) { return a.StartMilliseconds - b.StartMilliseconds; }); - - var determineOverlap = function(gap, node) { - var overlap = 0; - for (var i = 0; i < node.richTiming.length; i++) { - var current = node.richTiming[i]; - if (current.start > gap.finish) { - break; - } - if (current.finish < gap.start) { - continue; - } - - overlap += Math.min(gap.finish, current.finish) - Math.max(gap.start, current.start); - } - return overlap; - }; - - var determineGap = function (gap, node, match) { - var overlap = determineOverlap(gap, node); - if (match == null || overlap > match.duration) { - match = { name: node.Name, duration: overlap }; - } - else if (match.name == node.Name) { - match.duration += overlap; - } - - if (node.Children) { - for (var i = 0; i < node.Children.length; i++) { - match = determineGap(gap, node.Children[i], match); - } - } - return match; - }; - - var time = 0; - var prev = null; - $.each(result, function () { - this.prevGap = { - duration: (this.StartMilliseconds - time).toFixed(2), - start: time, - finish: this.StartMilliseconds - }; - - this.prevGap.topReason = determineGap(this.prevGap, root, null); - - time = this.StartMilliseconds + this.DurationMilliseconds; - prev = this; - }); - - - if (result.length > 0) { - var me = result[result.length - 1]; - me.nextGap = { - duration: (root.DurationMilliseconds - time).toFixed(2), - start: time, - finish: root.DurationMilliseconds - }; - me.nextGap.topReason = determineGap(me.nextGap, root, null); - } - - return result; - }, - - getSqlTimingsCount: function (root) { - var result = 0, - countSql = function (timing) { - if (timing.SqlTimings) { - result += timing.SqlTimings.length; - } - - if (timing.Children) { - for (var i = 0; i < timing.Children.length; i++) { - countSql(timing.Children[i]); - } - } - }; - countSql(root); - return result; - }, - - fetchResultsExposed: function (ids) { - return fetchResults(ids); - }, - - formatDuration: function (duration) { - return (duration || 0).toFixed(1); - } - }; -})(); - -MiniProfiler.init(); - -if (typeof prettyPrint === "undefined") { - - // prettify.js - // http://code.google.com/p/google-code-prettify/ - - window.PR_SHOULD_USE_CONTINUATION=true;window.PR_TAB_WIDTH=8;window.PR_normalizedHtml=window.PR=window.prettyPrintOne=window.prettyPrint=void 0;window._pr_isIE6=function(){var y=navigator&&navigator.userAgent&&navigator.userAgent.match(/\bMSIE ([678])\./);y=y?+y[1]:false;window._pr_isIE6=function(){return y};return y}; - (function(){function y(b){return b.replace(L,"&").replace(M,"<").replace(N,">")}function H(b,f,i){switch(b.nodeType){case 1:var o=b.tagName.toLowerCase();f.push("<",o);var l=b.attributes,n=l.length;if(n){if(i){for(var r=[],j=n;--j>=0;)r[j]=l[j];r.sort(function(q,m){return q.name"); - for(l=b.firstChild;l;l=l.nextSibling)H(l,f,i);if(b.firstChild||!/^(?:br|link|img)$/.test(o))f.push("");break;case 3:case 4:f.push(y(b.nodeValue));break}}function O(b){function f(c){if(c.charAt(0)!=="\\")return c.charCodeAt(0);switch(c.charAt(1)){case "b":return 8;case "t":return 9;case "n":return 10;case "v":return 11;case "f":return 12;case "r":return 13;case "u":case "x":return parseInt(c.substring(2),16)||c.charCodeAt(1);case "0":case "1":case "2":case "3":case "4":case "5":case "6":case "7":return parseInt(c.substring(1), - 8);default:return c.charCodeAt(1)}}function i(c){if(c<32)return(c<16?"\\x0":"\\x")+c.toString(16);c=String.fromCharCode(c);if(c==="\\"||c==="-"||c==="["||c==="]")c="\\"+c;return c}function o(c){var d=c.substring(1,c.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));c=[];for(var a=[],k=d[0]==="^",e=k?1:0,h=d.length;e122)){s<65||g>90||a.push([Math.max(65,g)|32,Math.min(s,90)|32]);s<97||g>122||a.push([Math.max(97,g)&-33,Math.min(s,122)&-33])}}a.sort(function(v,w){return v[0]-w[0]||w[1]-v[1]});d=[];g=[NaN,NaN];for(e=0;eh[0]){h[1]+1>h[0]&&a.push("-"); - a.push(i(h[1]))}}a.push("]");return a.join("")}function l(c){for(var d=c.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g")),a=d.length,k=[],e=0,h=0;e=2&&c==="[")d[e]=o(g);else if(c!=="\\")d[e]=g.replace(/[a-zA-Z]/g,function(s){s=s.charCodeAt(0);return"["+String.fromCharCode(s&-33,s|32)+"]"})}return d.join("")}for(var n=0,r=false,j=false,q=0,m=b.length;q=0;l-=16)o.push(" ".substring(0,l));l=n+1;break;case "\n":f=0;break;default:++f}if(!o)return i;o.push(i.substring(l));return o.join("")}}function I(b, - f,i,o){if(f){b={source:f,c:b};i(b);o.push.apply(o,b.d)}}function B(b,f){var i={},o;(function(){for(var r=b.concat(f),j=[],q={},m=0,t=r.length;m=0;)i[c.charAt(d)]=p;p=p[1];c=""+p;if(!q.hasOwnProperty(c)){j.push(p);q[c]=null}}j.push(/[\0-\uffff]/);o=O(j)})();var l=f.length;function n(r){for(var j=r.c,q=[j,z],m=0,t=r.source.match(o)||[],p={},c=0,d=t.length;c=5&&"lang-"===k.substring(0,5))&&!(e&&typeof e[1]==="string")){h=false;k=P}h||(p[a]=k)}g=m;m+=a.length;if(h){h=e[1];var s=a.indexOf(h),v=s+h.length;if(e[2]){v=a.length-e[2].length;s=v-h.length}k=k.substring(5);I(j+g,a.substring(0,s),n,q);I(j+g+s,h,Q(k,h),q);I(j+g+v,a.substring(v),n,q)}else q.push(j+g,k)}r.d=q}return n}function x(b){var f=[],i=[];if(b.tripleQuotedStrings)f.push([A,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, - null,"'\""]);else b.multiLineStrings?f.push([A,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):f.push([A,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);b.verbatimStrings&&i.push([A,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);if(b.hashComments)if(b.cStyleComments){f.push([C,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"]);i.push([A,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/, - null])}else f.push([C,/^#[^\r\n]*/,null,"#"]);if(b.cStyleComments){i.push([C,/^\/\/[^\r\n]*/,null]);i.push([C,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}b.regexLiterals&&i.push(["lang-regex",RegExp("^"+Z+"(/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/)")]);b=b.keywords.replace(/^\s+|\s+$/g,"");b.length&&i.push([R,RegExp("^(?:"+b.replace(/\s+/g,"|")+")\\b"),null]);f.push([z,/^\s+/,null," \r\n\t\u00a0"]);i.push([J,/^@[a-z_$][a-z_$@0-9]*/i,null],[S,/^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/, - null],[z,/^[a-z_$][a-z_$@0-9]*/i,null],[J,/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],[E,/^.[^\s\w\.$@\'\"\`\/\#]*/,null]);return B(f,i)}function $(b){function f(D){if(D>r){if(j&&j!==q){n.push("");j=null}if(!j&&q){j=q;n.push('')}var T=y(p(i.substring(r,D))).replace(e?d:c,"$1 ");e=k.test(T);n.push(T.replace(a,s));r=D}}var i=b.source,o=b.g,l=b.d,n=[],r=0,j=null,q=null,m=0,t=0,p=Y(window.PR_TAB_WIDTH),c=/([\r\n ]) /g, - d=/(^| ) /gm,a=/\r\n?|\n/g,k=/[ \r\n]$/,e=true,h=window._pr_isIE6();h=h?b.b.tagName==="PRE"?h===6?" \r\n":h===7?" 
\r":" \r":" 
":"
";var g=b.b.className.match(/\blinenums\b(?::(\d+))?/),s;if(g){for(var v=[],w=0;w<10;++w)v[w]=h+'
  • ';var F=g[1]&&g[1].length?g[1]-1:0;n.push('
    1. ");s=function(){var D=v[++F%10];return j?""+D+'':D}}else s=h; - for(;;)if(m");j=null}n.push(o[m+1]);m+=2}else if(t");g&&n.push("
    ");b.a=n.join("")}function u(b,f){for(var i=f.length;--i>=0;){var o=f[i];if(G.hasOwnProperty(o))"console"in window&&console.warn("cannot override language handler %s",o);else G[o]=b}}function Q(b,f){b&&G.hasOwnProperty(b)||(b=/^\s*1&&m.charAt(0)==="<"){if(!ba.test(m))if(ca.test(m)){f.push(m.substring(9,m.length-3));n+=m.length-12}else if(da.test(m)){f.push("\n");++n}else if(m.indexOf(V)>=0&&m.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/)){var t=m.match(W)[2],p=1,c;c=j+1;a:for(;c=0;){var e=p.indexOf(";",k);if(e>=0){var h=p.substring(k+3,e),g=10;if(h&&h.charAt(0)==="x"){h=h.substring(1);g=16}var s=parseInt(h,g);isNaN(s)||(p=p.substring(0,k)+String.fromCharCode(s)+p.substring(e+1))}}a=p.replace(ea,"<").replace(fa,">").replace(ga,"'").replace(ha,'"').replace(ia," ").replace(ja, - "&")}f.push(a);n+=a.length}}o={source:f.join(""),h:r};var v=o.source;b.source=v;b.c=0;b.g=o.h;Q(i,v)(b);$(b)}catch(w){if("console"in window)console.log(w&&w.stack?w.stack:w)}}var A="str",R="kwd",C="com",S="typ",J="lit",E="pun",z="pln",P="src",V="nocode",Z=function(){for(var b=["!","!=","!==","#","%","%=","&","&&","&&=","&=","(","*","*=","+=",",","-=","->","/","/=",":","::",";","<","<<","<<=","<=","=","==","===",">",">=",">>",">>=",">>>",">>>=","?","@","[","^","^=","^^","^^=","{","|","|=","||","||=", - "~","break","case","continue","delete","do","else","finally","instanceof","return","throw","try","typeof"],f="(?:^^|[+-]",i=0;i:&a-z])/g,"\\$1");f+=")\\s*";return f}(),L=/&/g,M=//g,X=/\"/g,ea=/</g,fa=/>/g,ga=/'/g,ha=/"/g,ja=/&/g,ia=/ /g,ka=/[\r\n]/g,K=null,aa=RegExp("[^<]+|