diff --git a/.coverage/.last_run.json b/.coverage/.last_run.json new file mode 100644 index 00000000..1f98b598 --- /dev/null +++ b/.coverage/.last_run.json @@ -0,0 +1,5 @@ +{ + "result": { + "covered_percent": 67.05 + } +} diff --git a/.coverage/.resultset.json b/.coverage/.resultset.json new file mode 100644 index 00000000..d9523d63 --- /dev/null +++ b/.coverage/.resultset.json @@ -0,0 +1,4393 @@ +{ + "RSpec": { + "coverage": { + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + null, + 1, + 28, + null, + null, + null, + null, + null, + null, + null, + 1, + 28, + 28, + 28, + null, + null, + 1, + 27, + 27, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + null, + 1, + 27, + 50, + null, + 27, + 27, + 27, + 23, + null, + null, + 27, + 0, + null, + null, + 27, + 27, + 27, + 27, + 27, + 27, + null, + 27, + 27, + 0, + null, + null, + null, + null, + 27, + 27, + 27, + null, + 27, + 23, + 23, + null, + null, + null, + 27, + 27, + 27, + 27, + null, + null, + 27, + null, + null, + 27, + null, + 27, + 27, + 27, + null, + null, + 27, + 486, + null, + 972, + null, + null, + null, + null, + null, + 1, + 23, + null, + 0, + 0, + null, + 0, + null, + null, + null, + 1, + null, + 1, + 0, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 1, + null, + 1, + 0, + 0, + null, + null, + null, + 1, + null, + 0, + 0, + null, + 0, + 0, + 0, + null, + null, + 1, + 6, + 20, + null, + null, + 1, + 1, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2.rb": [ + 1, + 1, + 1, + 1, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/serializer.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + null, + null, + null, + 1, + 1, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/accounts.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + null, + 0, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/annotations.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + null, + null, + 1, + null, + 0, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/broadcasts.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + null, + 0, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/branch.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/branches.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + 0, + 0, + 0, + null, + null, + 1, + null, + 0, + 0, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/build.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + null, + 0, + 0, + null, + null, + 1, + null, + null, + null, + 0, + null, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + 1, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/builds.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + null, + 0, + 0, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/caches.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/hooks.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + null, + 0, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/job.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + null, + null, + null, + null, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/jobs.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + null, + 0, + 0, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/log.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + null, + null, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + 0, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/permissions.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + 0, + null, + null, + 1, + 1, + 0, + 0, + null, + 0, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/repositories.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + null, + 0, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/repository.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + null, + null, + 1, + null, + null, + 0, + null, + null, + 1, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/requests.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + null, + 0, + 0, + 0, + null, + null, + 1, + null, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/request.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 0, + 0, + null, + 0, + null, + null, + 1, + null, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/ssl_key.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/env_var.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/env_vars.rb": [ + 1, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/user.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + null, + null, + 0, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/validation_error.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 0, + 0, + 0, + 0, + null, + null, + null, + 0, + null, + null, + 1, + 0, + null, + 0, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v2/http/ssh_key.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + 0, + null, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/private_key.rb": [ + 1, + 1, + 1, + 0, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + 0, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 49, + 53, + null, + null, + 1, + 22, + 22, + 22, + null, + null, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/access_control.rb": [ + 1, + 1, + 1, + null, + 1, + 23, + 23, + 23, + 23, + 46, + 23, + 23, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/error.rb": [ + 1, + null, + 1, + 1, + 1, + 5, + 38, + null, + null, + 1, + 0, + null, + null, + 1, + 10, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + null, + 1, + 10, + 10, + 10, + null, + null, + 10, + 10, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/opt_in.rb": [ + 1, + 1, + 1, + null, + 1, + 27, + 27, + 27, + 27, + 27, + null, + null, + 1, + 23, + null, + 23, + 23, + 23, + null, + null, + 23, + 23, + null, + null, + 1, + 23, + 10, + 10, + null, + null, + 1, + 23, + null, + null, + 1, + 0, + null, + null, + 1, + 23, + null, + null, + 1, + 23, + 23, + null, + null, + 1, + 23, + 20, + null, + null, + null, + null, + null, + 1, + 3, + null, + null, + 1, + 2, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/renderer.rb": [ + 1, + 1, + 1, + null, + 1, + 18, + 18, + null, + null, + 1, + 16, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/result.rb": [ + 1, + 1, + 1, + null, + 1, + 22, + null, + null, + 1, + 0, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 18, + null, + null, + 1, + 2, + 2, + 2, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/router.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 27, + 27, + null, + null, + 1, + 23, + 18, + 18, + 18, + null, + 18, + null, + 18, + 18, + 8, + null, + 10, + 10, + null, + null, + 1, + 8, + null, + null, + 1, + 5, + null, + null, + 1, + 18, + 18, + 18, + null, + 18, + 0, + 0, + 0, + null, + null, + 18, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/routes.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/routes/dsl.rb": [ + 1, + null, + 1, + 1, + 1, + 126, + null, + null, + 1, + 32, + null, + null, + 1, + 3, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + null, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + 1, + 0, + null, + null, + 1, + 27, + 27, + 27, + 27, + 27, + 27, + null, + null, + 27, + null, + null, + 1, + 18, + 18, + 18, + 18, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/routes/resource.rb": [ + 1, + null, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/service.rb": [ + 1, + 1, + 1, + 0, + null, + null, + 1, + 1, + 1, + 3, + 39, + 3, + 3, + null, + 1, + null, + null, + 1, + null, + 1, + 18, + 18, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/service_index.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 5, + 5, + 5, + null, + null, + 1, + null, + 1, + 2, + 2, + 2, + 2, + null, + null, + 1, + 5, + null, + null, + 1, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + null, + null, + null, + 2, + null, + null, + 1, + 2, + null, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + null, + null, + null, + null, + 2, + 2, + 2, + 0, + 0, + 0, + 0, + 0, + null, + null, + 2, + null, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + null, + 2, + null, + null, + null, + null, + 2, + null, + null, + 1, + 5, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/services.rb": [ + 1, + 1, + 1, + 27, + 27, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/access_control/anonymous.rb": [ + 1, + null, + 1, + 1, + null, + 1, + null, + 1, + 13, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/access_control/generic.rb": [ + 1, + 1, + 1, + null, + null, + 1, + 7, + null, + null, + 1, + 18, + null, + null, + 1, + null, + 1, + 14, + 12, + null, + null, + 1, + 4, + null, + null, + 1, + 28, + null, + null, + 1, + 14, + null, + null, + 1, + 14, + null, + null, + 1, + 14, + null, + null, + 1, + null, + 1, + 14, + 14, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/access_control/application.rb": [ + 1, + null, + 1, + 1, + 1, + null, + 1, + 6, + 6, + 6, + 6, + 6, + null, + null, + 1, + null, + 1, + 0, + null, + null, + 1, + 4, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/access_control/legacy_token.rb": [ + 1, + 1, + null, + 1, + null, + null, + 1, + 1, + null, + 1, + 4, + 4, + 4, + null, + null, + 1, + 4, + 4, + null, + null, + 1, + null, + 1, + 4, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/access_token.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + null, + 1, + 4, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 8, + 8, + 8, + 8, + null, + null, + 1, + 12, + 12, + null, + 12, + 12, + null, + 0, + null, + null, + 12, + 12, + 12, + 12, + 12, + 12, + null, + null, + 1, + 4, + 4, + 4, + 4, + 4, + 4, + null, + 4, + 0, + 0, + null, + null, + null, + 1, + 4, + null, + null, + 1, + 0, + null, + null, + 1, + 4, + null, + null, + 1, + 1, + 1, + 24, + null, + null, + 1, + 12, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 1, + null, + 1, + null, + 1, + 4, + null, + null, + 1, + null, + 4, + 4, + 4, + 8, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/access_control/user.rb": [ + 1, + null, + 1, + 1, + 1, + null, + 1, + 4, + 4, + 4, + null, + null, + 1, + null, + 1, + 4, + null, + null, + 1, + 4, + 4, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/access_control/scoped.rb": [ + 1, + null, + 1, + 1, + 1, + null, + 1, + 4, + 4, + null, + null, + 1, + null, + 1, + 4, + 4, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/access_control/signature.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 1, + null, + 1, + 6, + 16, + 6, + null, + 6, + 0, + null, + null, + 6, + 6, + null, + null, + 6, + 0, + 0, + null, + null, + 6, + 6, + null, + 6, + 6, + 6, + null, + 0, + 0, + null, + null, + 6, + 4, + null, + null, + 12, + null, + null, + 1, + null, + 0, + null, + null, + null, + null, + 1, + 6, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/renderer/error.rb": [ + 1, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + 10, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/renderer/repository.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 8, + null, + null, + 1, + 56, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 8, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/v3/services/find_repository.rb": [ + 1, + 1, + 1, + null, + 1, + 18, + 8, + null, + null, + 1, + 42, + 42, + null, + null, + 1, + 18, + 0, + 0, + 0, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/middleware/logging.rb": [ + 1, + null, + 1, + 1, + null, + 1, + 2, + null, + 1, + 23, + 23, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/middleware.rb": [ + 1, + null, + 1, + null, + 1, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/base.rb": [ + 1, + 1, + 1, + null, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + null, + 1, + 135, + null, + null, + 1, + 135, + null, + 0, + null, + null, + 1, + null, + null, + null, + null, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + null, + null, + 0, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/extensions.rb": [ + 1, + null, + 1, + null, + 1, + 5, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/extensions/expose_pattern.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 119, + 119, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/extensions/scoping.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + 0, + 0, + null, + 0, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 118, + 0, + 0, + null, + 0, + 0, + 0, + 0, + null, + 0, + 0, + 0, + 0, + null, + null, + null, + 0, + 0, + 0, + null, + 0, + 0, + null, + 0, + null, + null, + null, + 0, + null, + null, + null, + 1, + 118, + 118, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/extensions/smart_constants.rb": [ + 1, + null, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 4, + null, + null, + 1, + 4, + null, + null, + 1, + null, + 1, + 20, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/extensions/subclass_tracker.rb": [ + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + 707, + null, + null, + null, + 1, + 594, + 85, + null, + null, + 1, + 28, + 28, + 28, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/helpers.rb": [ + 1, + null, + 1, + null, + 1, + 7, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/helpers/accept.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + 0, + null, + null, + 1, + null, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + null, + 0, + 0, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + 1, + null, + null, + 0, + 0, + null, + 0, + 0, + 0, + 0, + null, + null, + 0, + 0, + 0, + null, + null, + 0, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + 0, + null, + null, + null, + 1, + 43, + null, + null, + 1, + 10, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/helpers/current_user.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/helpers/db_follower.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/helpers/flash.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 10, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/helpers/mime_types.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/helpers/respond_with.rb": [ + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + null, + 1, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + 0, + null, + null, + 1, + 40, + 40, + null, + null, + 1, + null, + 1, + 0, + null, + 0, + 0, + 0, + 0, + 0, + null, + null, + null, + 0, + 0, + 0, + 0, + null, + null, + null, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/middleware/metriks.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + null, + 1, + 23, + null, + null, + 1, + 23, + 0, + 0, + null, + null, + 23, + 13, + 13, + 0, + 0, + 0, + 0, + null, + 13, + 13, + 13, + null, + 0, + null, + 13, + null, + null, + 23, + 23, + null, + null, + 1, + 46, + 46, + 46, + 46, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/middleware/rewrite.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 2, + null, + 1, + 10, + 10, + 10, + null, + null, + 1, + 10, + null, + null, + 1, + null, + 1, + 10, + 10, + 10, + null, + null, + 1, + 10, + null, + null, + 1, + 0, + null, + null, + 1, + 10, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + null, + null, + 1, + 10, + null, + null, + 1, + 10, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 20, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/middleware/scope_check.rb": [ + 1, + null, + 1, + 1, + null, + 1, + 1, + 23, + 4, + 4, + 4, + null, + null, + 1, + 23, + 23, + 23, + null, + null, + null, + 1, + 27, + null, + null, + 1, + null, + 1, + 19, + 0, + null, + null, + 1, + 19, + null, + null, + 1, + 23, + 23, + null, + 10, + 0, + 4, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/middleware/user_agent_tracker.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + 1, + 23, + 23, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + null, + null, + null, + 1, + null, + 0, + 0, + null, + null, + 1, + 0, + null, + 0, + 0, + 0, + null, + null, + 0, + null, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/accounts.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint.rb": [ + 1, + 1, + 1, + null, + 1, + null, + 1, + 1, + null, + 471, + 1, + 1, + 1, + null, + null, + 11, + 11, + null, + 1, + 1, + 10, + 10, + 0, + null, + 10, + null, + null, + 0, + null, + null, + null, + 1, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/authorization.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + 1, + 0, + null, + null, + 1, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + null, + null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + null, + 0, + 0, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 1, + null, + 1, + null, + 1, + 0, + null, + 0, + null, + null, + 1, + 0, + 0, + null, + 0, + 0, + null, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + null, + 0, + 0, + 0, + 0, + null, + 0, + null, + null, + 0, + null, + null, + 0, + null, + 0, + 0, + 0, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + 0, + null, + null, + null, + 0, + 0, + 0, + null, + null, + 0, + 0, + 0, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + null, + 0, + 0, + 0, + null, + null, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/branches.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/broadcasts.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/builds.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + 0, + 0, + 0, + null, + null, + null, + 0, + 0, + 0, + null, + 0, + null, + null, + null, + null, + 0, + 0, + 0, + null, + 0, + null, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/documentation.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + null, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/endpoints.rb": [ + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + null, + 1, + 1, + 1, + null, + 1, + 68, + 68, + 68, + 68, + null, + null, + null, + null, + 68, + null, + null, + null, + null, + null, + 68, + null, + null, + 18, + 18, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/env_vars.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + 0, + null, + null, + 0, + 0, + null, + null, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/setting_endpoint.rb": [ + 1, + null, + 1, + 1, + 66, + null, + 1, + null, + null, + 1, + 54, + 54, + 53, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + null, + 1, + null, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/home.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/hooks.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/jobs.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + null, + 1, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + 0, + 0, + 0, + null, + null, + null, + 1, + 0, + null, + 0, + 0, + 0, + null, + null, + null, + 0, + 0, + 0, + null, + 0, + null, + null, + null, + null, + 0, + 0, + 0, + null, + 0, + null, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + 0, + 0, + null, + 0, + 0, + 0, + 0, + null, + 0, + null, + null, + 0, + null, + null, + 0, + null, + null, + null, + 1, + 0, + 0, + null, + 0, + 0, + null, + 0, + 0, + null, + 0, + 0, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + null, + 0, + null, + 0, + null, + 0, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/lint.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + null, + null, + 1, + 1, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/logs.rb": [ + 1, + null, + 1, + 1, + null, + 1, + null, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/repos.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null, + 1, + 0, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + 0, + null, + null, + null, + 1, + 0, + null, + 0, + 0, + null, + null, + 0, + 0, + 0, + null, + null, + 0, + 0, + null, + 0, + 0, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/requests.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + 0, + 0, + null, + null, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + null, + 0, + 0, + null, + null, + null, + 1, + 0, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/services/schedule_request.rb": [ + 1, + 1, + 1, + null, + 1, + 1, + 1, + 1, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + null, + 1, + 0, + 0, + 0, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/singleton_settings_endpoint.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/uptime.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + null, + 0, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/endpoint/users.rb": [ + 1, + null, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + 0, + null, + null, + 1, + 0, + null, + null, + 1, + 0, + 0, + 0, + null, + 0, + null, + null, + null, + null, + null + ], + "/Users/konstantinhaase/Workspace/travis-api/lib/travis/api/app/cors.rb": [ + 1, + null, + 1, + null, + null, + null, + null, + 1, + 1, + 23, + 23, + 23, + null, + null, + 1, + 0, + 0, + null, + null, + null + ] + }, + "timestamp": 1421854653 + } +} diff --git a/.coverage/.resultset.json.lock b/.coverage/.resultset.json.lock new file mode 100644 index 00000000..e69de29b diff --git a/.coverage/assets/0.8.0/application.css b/.coverage/assets/0.8.0/application.css new file mode 100644 index 00000000..d8656043 --- /dev/null +++ b/.coverage/assets/0.8.0/application.css @@ -0,0 +1,799 @@ +/* ----------------------------------------------------------------------- + + + Blueprint CSS Framework 0.9 + http://blueprintcss.org + + * Copyright (c) 2007-Present. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* reset.css */ + +html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, dialog, figure, footer, header, hgroup, nav, section {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;} +article, aside, dialog, figure, footer, header, hgroup, nav, section {display:block;} +body {line-height:1.5;} +table {border-collapse:separate;border-spacing:0;} +caption, th, td {text-align:left;font-weight:normal;} +table, td, th {vertical-align:middle;} +blockquote:before, blockquote:after, q:before, q:after {content:"";} +blockquote, q {quotes:"" "";} +a img {border:none;} + +/* typography.css */ +html {font-size:100.01%;} +body {font-size:82%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;} +h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;} +h1 {font-size:3em;line-height:1;margin-bottom:0.5em;} +h2 {font-size:2em;margin-bottom:0.75em;} +h3 {font-size:1.5em;line-height:1;margin-bottom:1em;} +h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;} +h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;} +h6 {font-size:1em;font-weight:bold;} +h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;} +p {margin:0 0 1.5em;} +p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;} +p img.right {float:right;margin:1.5em 0 1.5em 1.5em;} +a:focus, a:hover {color:#000;} +a {color:#009;text-decoration:underline;} +blockquote {margin:1.5em;color:#666;font-style:italic;} +strong {font-weight:bold;} +em, dfn {font-style:italic;} +dfn {font-weight:bold;} +sup, sub {line-height:0;} +abbr, acronym {border-bottom:1px dotted #666;} +address {margin:0 0 1.5em;font-style:italic;} +del {color:#666;} +pre {margin:1.5em 0;white-space:pre;} +pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;} +li ul, li ol {margin:0;} +ul, ol {margin:0 1.5em 1.5em 0;padding-left:3.333em;} +ul {list-style-type:disc;} +ol {list-style-type:decimal;} +dl {margin:0 0 1.5em 0;} +dl dt {font-weight:bold;} +dd {margin-left:1.5em;} +table {margin-bottom:1.4em;width:100%;} +th {font-weight:bold;} +thead th {background:#c3d9ff;} +th, td, caption {padding:4px 10px 4px 5px;} +tr.even td {background:#efefef;} +tfoot {font-style:italic;} +caption {background:#eee;} +.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;} +.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;} +.hide {display:none;} +.quiet {color:#666;} +.loud {color:#000;} +.highlight {background:#ff0;} +.added {background:#060;color:#fff;} +.removed {background:#900;color:#fff;} +.first {margin-left:0;padding-left:0;} +.last {margin-right:0;padding-right:0;} +.top {margin-top:0;padding-top:0;} +.bottom {margin-bottom:0;padding-bottom:0;} + +/* forms.css */ +label {font-weight:bold;} +fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;} +legend {font-weight:bold;font-size:1.2em;} +input[type=text], input[type=password], input.text, input.title, textarea, select {background-color:#fff;border:1px solid #bbb;} +input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus, select:focus {border-color:#666;} +input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;} +input.text, input.title {width:300px;padding:5px;} +input.title {font-size:1.5em;} +textarea {width:390px;height:250px;padding:5px;} +input[type=checkbox], input[type=radio], input.checkbox, input.radio {position:relative;top:.25em;} +form.inline {line-height:3;} +form.inline p {margin-bottom:0;} +.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;} +.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;} +.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;} +.success {background:#E6EFC2;color:#264409;border-color:#C6D880;} +.error a {color:#8a1f11;} +.notice a {color:#514721;} +.success a {color:#264409;} +.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;} +hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;} +hr.space {background:#fff;color:#fff;visibility:hidden;} +.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;} +.clearfix, .container {display:block;} +.clear {clear:both;} +/* +github.com style (c) Vasily Polovnyov <vast@whiteants.net> +*/ + + +pre code { +} + +pre .comment, +pre .template_comment, +pre .diff .header, +pre .javadoc { + color: #998; + font-style: italic +} + +pre .keyword, +pre .css .rule .keyword, +pre .winutils, +pre .javascript .title, +pre .lisp .title { + color: #000; + font-weight: bold +} + +pre .number, +pre .hexcolor { + color: #458 +} + + +pre .string, +pre .tag .value, +pre .phpdoc, +pre .tex .formula { + color: #d14 +} + +pre .subst { + color: #712; +} + +pre .constant, +pre .title, +pre .id { + color: #900; + font-weight: bold +} + +pre .javascript .title, +pre .lisp .title, +pre .subst { + font-weight: normal +} + +pre .class .title, +pre .haskell .label, +pre .tex .command { + color: #458; + font-weight: bold +} + +pre .tag, +pre .tag .title, +pre .rules .property, +pre .django .tag .keyword { + color: #000080; + font-weight: normal +} + +pre .attribute, +pre .variable, +pre .instancevar, +pre .lisp .body { + color: #008080 +} + +pre .regexp { + color: #009926 +} + +pre .class { + color: #458; + font-weight: bold +} + +pre .symbol, +pre .ruby .symbol .string, +pre .ruby .symbol .keyword, +pre .ruby .symbol .keymethods, +pre .lisp .keyword, +pre .tex .special, +pre .input_number { + color: #990073 +} + +pre .builtin, +pre .built_in, +pre .lisp .title { + color: #0086b3 +} + +pre .preprocessor, +pre .pi, +pre .doctype, +pre .shebang, +pre .cdata { + color: #999; + font-weight: bold +} + +pre .deletion { + background: #fdd +} + +pre .addition { + background: #dfd +} + +pre .diff .change { + background: #0086b3 +} + +pre .chunk { + color: #aaa +} + +pre .tex .formula { + opacity: 0.5; +} +/* + * jQuery UI CSS Framework @VERSION + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ + +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/* + * jQuery UI CSS Framework @VERSION + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; } +/* + ColorBox Core Style: + The following CSS is consistent between example themes and should not be altered. +*/ +#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;} +#cboxOverlay{position:fixed; width:100%; height:100%;} +#cboxMiddleLeft, #cboxBottomLeft{clear:left;} +#cboxContent{position:relative;} +#cboxLoadedContent{overflow:auto;} +#cboxTitle{margin:0;} +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} +#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} +.cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none;} +.cboxIframe{width:100%; height:100%; display:block; border:0;} +#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box;} + +/* + User Style: + Change the following styles to modify the appearance of ColorBox. They are + ordered & tabbed in a way that represents the nesting of the generated HTML. +*/ +#cboxOverlay{background:#000;} +#colorbox{} + #cboxTopLeft{width:14px; height:14px; background:url(colorbox/controls.png) no-repeat 0 0;} + #cboxTopCenter{height:14px; background:url(colorbox/border.png) repeat-x top left;} + #cboxTopRight{width:14px; height:14px; background:url(colorbox/controls.png) no-repeat -36px 0;} + #cboxBottomLeft{width:14px; height:43px; background:url(colorbox/controls.png) no-repeat 0 -32px;} + #cboxBottomCenter{height:43px; background:url(colorbox/border.png) repeat-x bottom left;} + #cboxBottomRight{width:14px; height:43px; background:url(colorbox/controls.png) no-repeat -36px -32px;} + #cboxMiddleLeft{width:14px; background:url(colorbox/controls.png) repeat-y -175px 0;} + #cboxMiddleRight{width:14px; background:url(colorbox/controls.png) repeat-y -211px 0;} + #cboxContent{background:#fff; overflow:visible;} + .cboxIframe{background:#fff;} + #cboxError{padding:50px; border:1px solid #ccc;} + #cboxLoadedContent{margin-bottom:5px;} + #cboxLoadingOverlay{background:url(colorbox/loading_background.png) no-repeat center center;} + #cboxLoadingGraphic{background:url(colorbox/loading.gif) no-repeat center center;} + #cboxTitle{position:absolute; bottom:-25px; left:0; text-align:center; width:100%; font-weight:bold; color:#7C7C7C;} + #cboxCurrent{position:absolute; bottom:-25px; left:58px; font-weight:bold; color:#7C7C7C;} + + #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{position:absolute; bottom:-29px; background:url(colorbox/controls.png) no-repeat 0px 0px; width:23px; height:23px; text-indent:-9999px;} + #cboxPrevious{left:0px; background-position: -51px -25px;} + #cboxPrevious:hover{background-position:-51px 0px;} + #cboxNext{left:27px; background-position:-75px -25px;} + #cboxNext:hover{background-position:-75px 0px;} + #cboxClose{right:0; background-position:-100px -25px;} + #cboxClose:hover{background-position:-100px 0px;} + + .cboxSlideshow_on #cboxSlideshow{background-position:-125px 0px; right:27px;} + .cboxSlideshow_on #cboxSlideshow:hover{background-position:-150px 0px;} + .cboxSlideshow_off #cboxSlideshow{background-position:-150px -25px; right:27px;} + .cboxSlideshow_off #cboxSlideshow:hover{background-position:-125px 0px;} +#loading { + position: fixed; + left: 40%; + top: 50%; } + +a { + color: #333333; + text-decoration: none; } + a:hover { + color: black; + text-decoration: underline; } + +body { + font-family: "Lucida Grande", Helvetica, "Helvetica Neue", Arial, sans-serif; + padding: 12px; + background-color: #333333; } + +h1, h2, h3, h4 { + color: #1c2324; + margin: 0; + padding: 0; + margin-bottom: 12px; } + +table { + width: 100%; } + +#content { + clear: left; + background-color: white; + border: 2px solid #dddddd; + border-top: 8px solid #dddddd; + padding: 18px; + -webkit-border-bottom-left-radius: 5px; + -webkit-border-bottom-right-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-bottomleft: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-topright: 5px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + border-top-right-radius: 5px; } + +.dataTables_filter, .dataTables_info { + padding: 2px 6px; } + +abbr.timeago { + text-decoration: none; + border: none; + font-weight: bold; } + +.timestamp { + float: right; + color: #dddddd; } + +.group_tabs { + list-style: none; + float: left; + margin: 0; + padding: 0; } + .group_tabs li { + display: inline; + float: left; } + .group_tabs li a { + font-family: Helvetica, Arial, sans-serif; + display: block; + float: left; + text-decoration: none; + padding: 4px 8px; + background-color: #aaaaaa; + background: -webkit-gradient(linear, 0 0, 0 bottom, from(#dddddd), to(#aaaaaa)); + background: -moz-linear-gradient(#dddddd, #aaaaaa); + background: linear-gradient(#dddddd, #aaaaaa); + text-shadow: #e5e5e5 1px 1px 0px; + border-bottom: none; + color: #333333; + font-weight: bold; + margin-right: 8px; + border-top: 1px solid #efefef; + -webkit-border-top-left-radius: 2px; + -webkit-border-top-right-radius: 2px; + -moz-border-radius-topleft: 2px; + -moz-border-radius-topright: 2px; + border-top-left-radius: 2px; + border-top-right-radius: 2px; } + .group_tabs li a:hover { + background-color: #cccccc; + background: -webkit-gradient(linear, 0 0, 0 bottom, from(#eeeeee), to(#aaaaaa)); + background: -moz-linear-gradient(#eeeeee, #aaaaaa); + background: linear-gradient(#eeeeee, #aaaaaa); } + .group_tabs li a:active { + padding-top: 5px; + padding-bottom: 3px; } + .group_tabs li.active a { + color: black; + text-shadow: white 1px 1px 0px; + background-color: #dddddd; + background: -webkit-gradient(linear, 0 0, 0 bottom, from(white), to(#dddddd)); + background: -moz-linear-gradient(white, #dddddd); + background: linear-gradient(white, #dddddd); } + +.file_list { + margin-bottom: 18px; } + +a.src_link { + background: url("./magnify.png") no-repeat left 50%; + padding-left: 18px; } + +tr, td { + margin: 0; + padding: 0; } + +th { + white-space: nowrap; } + th.ui-state-default { + cursor: pointer; } + th span.ui-icon { + float: left; } + +td { + padding: 4px 8px; } + td.strong { + font-weight: bold; } + +.source_table h3, .source_table h4 { + padding: 0; + margin: 0; + margin-bottom: 4px; } +.source_table .header { + padding: 10px; } +.source_table pre { + margin: 0; + padding: 0; + white-space: normal; + color: black; + font-family: "Monaco", "Inconsolata", "Consolas", monospace; } +.source_table code { + color: black; + font-family: "Monaco", "Inconsolata", "Consolas", monospace; } +.source_table pre { + background-color: #333333; } + .source_table pre ol { + margin: 0px; + padding: 0px; + margin-left: 45px; + font-size: 12px; + color: white; } + .source_table pre li { + margin: 0px; + padding: 2px 6px; + border-left: 5px solid white; } + .source_table pre li code { + white-space: pre; + white-space: pre-wrap; } + .source_table pre .hits { + float: right; + margin-left: 10px; + padding: 2px 4px; + background-color: #444444; + background: -webkit-gradient(linear, 0 0, 0 bottom, from(#222222), to(#666666)); + background: -moz-linear-gradient(#222222, #666666); + background: linear-gradient(#222222, #666666); + color: white; + font-family: Helvetica, "Helvetica Neue", Arial, sans-serif; + font-size: 10px; + font-weight: bold; + text-align: center; + border-radius: 6px; } + +#footer { + color: #dddddd; + font-size: 12px; + font-weight: bold; + margin-top: 12px; + text-align: right; } + #footer a { + color: #eeeeee; + text-decoration: underline; } + #footer a:hover { + color: white; + text-decoration: none; } + +.green { + color: #009900; } + +.red { + color: #990000; } + +.yellow { + color: #ddaa00; } + +.source_table .covered { + border-color: #009900; } +.source_table .missed { + border-color: #990000; } +.source_table .never { + border-color: black; } +.source_table .skipped { + border-color: #ffcc00; } +.source_table .covered:nth-child(odd) { + background-color: #cdf2cd; } +.source_table .covered:nth-child(even) { + background-color: #dbf2db; } +.source_table .missed:nth-child(odd) { + background-color: #f7c0c0; } +.source_table .missed:nth-child(even) { + background-color: #f7cfcf; } +.source_table .never:nth-child(odd) { + background-color: #efefef; } +.source_table .never:nth-child(even) { + background-color: #f4f4f4; } +.source_table .skipped:nth-child(odd) { + background-color: #fbf0c0; } +.source_table .skipped:nth-child(even) { + background-color: #fbffcf; } + + + diff --git a/.coverage/assets/0.8.0/application.js b/.coverage/assets/0.8.0/application.js new file mode 100644 index 00000000..5e06df5f --- /dev/null +++ b/.coverage/assets/0.8.0/application.js @@ -0,0 +1,1559 @@ +/*! + * jQuery JavaScript Library v1.6.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Jun 30 14:16:56 2011 -0400 + */ + +(function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bC.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bR,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bX(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bX(a,c,d,e,"*",g));return l}function bW(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bN),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bA(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bv:bw;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bg(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function W(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(R.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(x,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(H)return H.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g](h)}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u=/\:|^on/,v,w;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i. +shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,N(a.origType,a.selector),f.extend({},a,{handler:M,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,N(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?E:D):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=E;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=E;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=E,this.stopPropagation()},isDefaultPrevented:D,isPropagationStopped:D,isImmediatePropagationStopped:D};var F=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},G=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?G:F,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?G:F)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&f(b).closest("form").length&&K("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&K("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var H,I=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var L={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||D,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=x.exec(h),k="",j&&(k=j[0],h=h.replace(x,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,L[h]?(a.push(L[h]+k),h=h+k):h=(L[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+N(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+N(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var O=/Until$/,P=/^(?:parents|prevUntil|prevAll)/,Q=/,/,R=/^.[^:#\[\.,]*$/,S=Array.prototype.slice,T=f.expr.match.POS,U={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(W(this,a,!1),"not",a)},filter:function(a){return this.pushStack(W(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=T.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/<tbody/i,ba=/<|&#?\w+;/,bb=/<(?:script|object|embed|option|style)/i,bc=/checked\s*(?:[^=]|=\s*.checked.)/i,bd=/\/(java|ecma)script/i,be=/^\s*<!(?:\[CDATA\[|\-\-)/,bf={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bc.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bg(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bm)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!bb.test(a[0])&&(f.support.checkClone||!bc.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j +)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1></$2>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bl(k[i]);else bl(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bd.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bn=/alpha\([^)]*\)/i,bo=/opacity=([^)]*)/,bp=/([A-Z]|^ms)/g,bq=/^-?\d+(?:px)?$/i,br=/^-?\d/,bs=/^[+\-]=/,bt=/[^+\-\.\de]+/g,bu={position:"absolute",visibility:"hidden",display:"block"},bv=["Left","Right"],bw=["Top","Bottom"],bx,by,bz;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bx(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d;if(h==="number"&&isNaN(d)||d==null)return;h==="string"&&bs.test(d)&&(d=+d.replace(bt,"")+parseFloat(f.css(a,c)),h="number"),h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bx)return bx(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bA(a,b,d);f.swap(a,bu,function(){e=bA(a,b,d)});return e}},set:function(a,b){if(!bq.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cs(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cr("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cr("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cs(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cr("show",1),slideUp:cr("hide",1),slideToggle:cr("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function h(a){return d.step(a)}var d=this,e=f.fx,g;this.startTime=cn||cp(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,h.elem=this.elem,h()&&f.timers.push(h)&&!cl&&(co?(cl=!0,g=function(){cl&&(co(g),e.tick())},co(g)):cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||cp(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var ct=/^t(?:able|d|h)$/i,cu=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cv(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!ct.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); +var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(/</gm,"<")}function c(q,p,o){return RegExp(p,"m"+(q.cI?"i":"")+(o?"g":""))}function i(q){for(var o=0;o<q.childNodes.length;o++){var p=q.childNodes[o];if(p.nodeName=="CODE"){return p}if(!(p.nodeType==3&&p.nodeValue.match(/\s+/))){break}}}function g(s,r){var q="";for(var p=0;p<s.childNodes.length;p++){if(s.childNodes[p].nodeType==3){var o=s.childNodes[p].nodeValue;if(r){o=o.replace(/\n/g,"")}q+=o}else{if(s.childNodes[p].nodeName=="BR"){q+="\n"}else{q+=g(s.childNodes[p])}}}if(/MSIE [678]/.test(navigator.userAgent)){q=q.replace(/\r/g,"\n")}return q}function a(r){var p=r.className.split(/\s+/);p=p.concat(r.parentNode.className.split(/\s+/));for(var o=0;o<p.length;o++){var q=p[o].replace(/^language-/,"");if(d[q]||q=="no-highlight"){return q}}}function b(o){var p=[];(function(r,s){for(var q=0;q<r.childNodes.length;q++){if(r.childNodes[q].nodeType==3){s+=r.childNodes[q].nodeValue.length}else{if(r.childNodes[q].nodeName=="BR"){s+=1}else{p.push({event:"start",offset:s,node:r.childNodes[q]});s=arguments.callee(r.childNodes[q],s);p.push({event:"stop",offset:s,node:r.childNodes[q]})}}}return s})(o,0);return p}function k(x,y,w){var q=0;var v="";var s=[];function t(){if(x.length&&y.length){if(x[0].offset!=y[0].offset){return(x[0].offset<y[0].offset)?x:y}else{return y[0].event=="start"?x:y}}else{return x.length?x:y}}function r(B){var C="<"+B.nodeName.toLowerCase();for(var z=0;z<B.attributes.length;z++){var A=B.attributes[z];C+=" "+A.nodeName.toLowerCase();if(A.nodeValue!=undefined){C+='="'+l(A.nodeValue)+'"'}}return C+">"}while(x.length||y.length){var u=t().splice(0,1)[0];v+=l(w.substr(q,u.offset-q));q=u.offset;if(u.event=="start"){v+=r(u.node);s.push(u.node)}else{if(u.event=="stop"){var p=s.length;do{p--;var o=s[p];v+=("</"+o.nodeName.toLowerCase()+">")}while(o!=u.node);s.splice(p,1);while(p<s.length){v+=r(s[p]);p++}}}}v+=w.substr(q);return v}function f(I,C){function y(r,L){for(var K=0;K<L.c.length;K++){if(L.c[K].bR.test(r)){return L.c[K]}}}function v(K,r){if(B[K].e&&B[K].eR.test(r)){return 1}if(B[K].eW){var L=v(K-1,r);return L?L+1:0}return 0}function w(r,K){return K.iR&&K.iR.test(r)}function z(N,M){var L=[];for(var K=0;K<N.c.length;K++){L.push(N.c[K].b)}var r=B.length-1;do{if(B[r].e){L.push(B[r].e)}r--}while(B[r+1].eW);if(N.i){L.push(N.i)}return c(M,"("+L.join("|")+")",true)}function q(L,K){var M=B[B.length-1];if(!M.t){M.t=z(M,G)}M.t.lastIndex=K;var r=M.t.exec(L);if(r){return[L.substr(K,r.index-K),r[0],false]}else{return[L.substr(K),"",true]}}function o(N,r){var K=G.cI?r[0].toLowerCase():r[0];for(var M in N.kG){if(!N.kG.hasOwnProperty(M)){continue}var L=N.kG[M].hasOwnProperty(K);if(L){return[M,L]}}return false}function E(L,N){if(!N.k){return l(L)}var M="";var O=0;N.lR.lastIndex=0;var K=N.lR.exec(L);while(K){M+=l(L.substr(O,K.index-O));var r=o(N,K);if(r){s+=r[1];M+='<span class="'+r[0]+'">'+l(K[0])+"</span>"}else{M+=l(K[0])}O=N.lR.lastIndex;K=N.lR.exec(L)}M+=l(L.substr(O,L.length-O));return M}function J(r,L){if(L.sL&&d[L.sL]){var K=f(L.sL,r);s+=K.keyword_count;return K.value}else{return E(r,L)}}function H(L,r){var K=L.cN?'<span class="'+L.cN+'">':"";if(L.rB){p+=K;L.buffer=""}else{if(L.eB){p+=l(r)+K;L.buffer=""}else{p+=K;L.buffer=r}}B.push(L);A+=L.r}function D(N,K,P){var Q=B[B.length-1];if(P){p+=J(Q.buffer+N,Q);return false}var L=y(K,Q);if(L){p+=J(Q.buffer+N,Q);H(L,K);return L.rB}var r=v(B.length-1,K);if(r){var M=Q.cN?"</span>":"";if(Q.rE){p+=J(Q.buffer+N,Q)+M}else{if(Q.eE){p+=J(Q.buffer+N,Q)+M+l(K)}else{p+=J(Q.buffer+N+K,Q)+M}}while(r>1){M=B[B.length-2].cN?"</span>":"";p+=M;r--;B.length--}var O=B[B.length-1];B.length--;B[B.length-1].buffer="";if(O.starts){H(O.starts,"")}return Q.rE}if(w(K,Q)){throw"Illegal"}}var G=d[I];var B=[G.dM];var A=0;var s=0;var p="";try{var u=0;G.dM.buffer="";do{var x=q(C,u);var t=D(x[0],x[1],x[2]);u+=x[0].length;if(!t){u+=x[1].length}}while(!x[2]);if(B.length>1){throw"Illegal"}return{language:I,r:A,keyword_count:s,value:p}}catch(F){if(F=="Illegal"){return{language:null,r:0,keyword_count:0,value:l(C)}}else{throw F}}}function h(){function o(t,s,u){if(t.compiled){return}if(!u){t.bR=c(s,t.b?t.b:"\\B|\\b");if(!t.e&&!t.eW){t.e="\\B|\\b"}if(t.e){t.eR=c(s,t.e)}}if(t.i){t.iR=c(s,t.i)}if(t.r==undefined){t.r=1}if(t.k){t.lR=c(s,t.l||hljs.IR,true)}for(var r in t.k){if(!t.k.hasOwnProperty(r)){continue}if(t.k[r] instanceof Object){t.kG=t.k}else{t.kG={keyword:t.k}}break}if(!t.c){t.c=[]}t.compiled=true;for(var q=0;q<t.c.length;q++){o(t.c[q],s,false)}if(t.starts){o(t.starts,s,false)}}for(var p in d){if(!d.hasOwnProperty(p)){continue}o(d[p].dM,d[p],true)}}function e(){if(e.called){return}e.called=true;h()}function n(t,y,p){e();var A=g(t,p);var r=a(t);if(r=="no-highlight"){return}if(r){var w=f(r,A)}else{var w={language:"",keyword_count:0,r:0,value:l(A)};var x=w;for(var z in d){if(!d.hasOwnProperty(z)){continue}var u=f(z,A);if(u.keyword_count+u.r>x.keyword_count+x.r){x=u}if(u.keyword_count+u.r>w.keyword_count+w.r){x=w;w=u}}}var s=t.className;if(!s.match(w.language)){s=s?(s+" "+w.language):w.language}var o=b(t);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=k(o,b(q),A)}if(y){w.value=w.value.replace(/^((<[^>]+>|\t)+)/gm,function(B,E,D,C){return E.replace(/\t/g,y)})}if(p){w.value=w.value.replace(/\n/g,"<br>")}if(/MSIE [678]/.test(navigator.userAgent)&&t.tagName=="CODE"&&t.parentNode.tagName=="PRE"){var q=t.parentNode;var v=document.createElement("div");v.innerHTML="<pre><code>"+w.value+"</code></pre>";t=v.firstChild.firstChild;v.firstChild.cN=q.cN;q.parentNode.replaceChild(v.firstChild,q)}else{t.innerHTML=w.value}t.className=s;t.dataset={};t.dataset.result={language:w.language,kw:w.keyword_count,re:w.r};if(x&&x.language){t.dataset.second_best={language:x.language,kw:x.keyword_count,re:x.r}}}function j(){if(j.called){return}j.called=true;e();var q=document.getElementsByTagName("pre");for(var o=0;o<q.length;o++){var p=i(q[o]);if(p){n(p,hljs.tabReplace)}}}function m(){var o=arguments;var p=function(){j.apply(null,o)};if(window.addEventListener){window.addEventListener("DOMContentLoaded",p,false);window.addEventListener("load",p,false)}else{if(window.attachEvent){window.attachEvent("onload",p)}else{window.onload=p}}}var d={};this.LANGUAGES=d;this.initHighlightingOnLoad=m;this.highlightBlock=n;this.initHighlighting=j;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="\\b(0x[A-Za-z0-9]+|\\d+(\\.\\d+)?)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\.",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.inherit=function(o,r){var q={};for(var p in o){q[p]=o[p]}if(r){for(var p in r){q[p]=r[p]}}return q}}();hljs.LANGUAGES.ruby=function(){var g="[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?";var a="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?";var n={keyword:{and:1,"false":1,then:1,defined:1,module:1,"in":1,"return":1,redo:1,"if":1,BEGIN:1,retry:1,end:1,"for":1,"true":1,self:1,when:1,next:1,until:1,"do":1,begin:1,unless:1,END:1,rescue:1,nil:1,"else":1,"break":1,undef:1,not:1,"super":1,"class":1,"case":1,require:1,yield:1,alias:1,"while":1,ensure:1,elsif:1,or:1,def:1},keymethods:{__id__:1,__send__:1,abort:1,abs:1,"all?":1,allocate:1,ancestors:1,"any?":1,arity:1,assoc:1,at:1,at_exit:1,autoload:1,"autoload?":1,"between?":1,binding:1,binmode:1,"block_given?":1,call:1,callcc:1,caller:1,capitalize:1,"capitalize!":1,casecmp:1,"catch":1,ceil:1,center:1,chomp:1,"chomp!":1,chop:1,"chop!":1,chr:1,"class":1,class_eval:1,"class_variable_defined?":1,class_variables:1,clear:1,clone:1,close:1,close_read:1,close_write:1,"closed?":1,coerce:1,collect:1,"collect!":1,compact:1,"compact!":1,concat:1,"const_defined?":1,const_get:1,const_missing:1,const_set:1,constants:1,count:1,crypt:1,"default":1,default_proc:1,"delete":1,"delete!":1,delete_at:1,delete_if:1,detect:1,display:1,div:1,divmod:1,downcase:1,"downcase!":1,downto:1,dump:1,dup:1,each:1,each_byte:1,each_index:1,each_key:1,each_line:1,each_pair:1,each_value:1,each_with_index:1,"empty?":1,entries:1,eof:1,"eof?":1,"eql?":1,"equal?":1,"eval":1,exec:1,exit:1,"exit!":1,extend:1,fail:1,fcntl:1,fetch:1,fileno:1,fill:1,find:1,find_all:1,first:1,flatten:1,"flatten!":1,floor:1,flush:1,for_fd:1,foreach:1,fork:1,format:1,freeze:1,"frozen?":1,fsync:1,getc:1,gets:1,global_variables:1,grep:1,gsub:1,"gsub!":1,"has_key?":1,"has_value?":1,hash:1,hex:1,id:1,include:1,"include?":1,included_modules:1,index:1,indexes:1,indices:1,induced_from:1,inject:1,insert:1,inspect:1,instance_eval:1,instance_method:1,instance_methods:1,"instance_of?":1,"instance_variable_defined?":1,instance_variable_get:1,instance_variable_set:1,instance_variables:1,"integer?":1,intern:1,invert:1,ioctl:1,"is_a?":1,isatty:1,"iterator?":1,join:1,"key?":1,keys:1,"kind_of?":1,lambda:1,last:1,length:1,lineno:1,ljust:1,load:1,local_variables:1,loop:1,lstrip:1,"lstrip!":1,map:1,"map!":1,match:1,max:1,"member?":1,merge:1,"merge!":1,method:1,"method_defined?":1,method_missing:1,methods:1,min:1,module_eval:1,modulo:1,name:1,nesting:1,"new":1,next:1,"next!":1,"nil?":1,nitems:1,"nonzero?":1,object_id:1,oct:1,open:1,pack:1,partition:1,pid:1,pipe:1,pop:1,popen:1,pos:1,prec:1,prec_f:1,prec_i:1,print:1,printf:1,private_class_method:1,private_instance_methods:1,"private_method_defined?":1,private_methods:1,proc:1,protected_instance_methods:1,"protected_method_defined?":1,protected_methods:1,public_class_method:1,public_instance_methods:1,"public_method_defined?":1,public_methods:1,push:1,putc:1,puts:1,quo:1,raise:1,rand:1,rassoc:1,read:1,read_nonblock:1,readchar:1,readline:1,readlines:1,readpartial:1,rehash:1,reject:1,"reject!":1,remainder:1,reopen:1,replace:1,require:1,"respond_to?":1,reverse:1,"reverse!":1,reverse_each:1,rewind:1,rindex:1,rjust:1,round:1,rstrip:1,"rstrip!":1,scan:1,seek:1,select:1,send:1,set_trace_func:1,shift:1,singleton_method_added:1,singleton_methods:1,size:1,sleep:1,slice:1,"slice!":1,sort:1,"sort!":1,sort_by:1,split:1,sprintf:1,squeeze:1,"squeeze!":1,srand:1,stat:1,step:1,store:1,strip:1,"strip!":1,sub:1,"sub!":1,succ:1,"succ!":1,sum:1,superclass:1,swapcase:1,"swapcase!":1,sync:1,syscall:1,sysopen:1,sysread:1,sysseek:1,system:1,syswrite:1,taint:1,"tainted?":1,tell:1,test:1,"throw":1,times:1,to_a:1,to_ary:1,to_f:1,to_hash:1,to_i:1,to_int:1,to_io:1,to_proc:1,to_s:1,to_str:1,to_sym:1,tr:1,"tr!":1,tr_s:1,"tr_s!":1,trace_var:1,transpose:1,trap:1,truncate:1,"tty?":1,type:1,ungetc:1,uniq:1,"uniq!":1,unpack:1,unshift:1,untaint:1,untrace_var:1,upcase:1,"upcase!":1,update:1,upto:1,"value?":1,values:1,values_at:1,warn:1,write:1,write_nonblock:1,"zero?":1,zip:1}};var h={cN:"yardoctag",b:"@[A-Za-z]+"};var d={cN:"comment",b:"#",e:"$",c:[h]};var c={cN:"comment",b:"^\\=begin",e:"^\\=end",c:[h],r:10};var b={cN:"comment",b:"^__END__",e:"\\n$"};var u={cN:"subst",b:"#\\{",e:"}",l:g,k:n};var p=[hljs.BE,u];var s={cN:"string",b:"'",e:"'",c:p,r:0};var r={cN:"string",b:'"',e:'"',c:p,r:0};var q={cN:"string",b:"%[qw]?\\(",e:"\\)",c:p,r:10};var o={cN:"string",b:"%[qw]?\\[",e:"\\]",c:p,r:10};var m={cN:"string",b:"%[qw]?{",e:"}",c:p,r:10};var l={cN:"string",b:"%[qw]?<",e:">",c:p,r:10};var k={cN:"string",b:"%[qw]?/",e:"/",c:p,r:10};var j={cN:"string",b:"%[qw]?%",e:"%",c:p,r:10};var i={cN:"string",b:"%[qw]?-",e:"-",c:p,r:10};var t={cN:"string",b:"%[qw]?\\|",e:"\\|",c:p,r:10};var e={cN:"function",b:"\\bdef\\s+",e:" |$|;",l:g,k:n,c:[{cN:"title",b:a,l:g,k:n},{cN:"params",b:"\\(",e:"\\)",l:g,k:n},d,c,b]};var f={cN:"identifier",b:g,l:g,k:n,r:0};var v=[d,c,b,s,r,q,o,m,l,k,j,i,t,{cN:"class",b:"\\b(class|module)\\b",e:"$|;",k:{"class":1,module:1},c:[{cN:"title",b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?",r:0},{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+hljs.IR+"::)?"+hljs.IR}]},d,c,b]},e,{cN:"constant",b:"(::)?([A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:":",c:[s,r,q,o,m,l,k,j,i,t,f],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"number",b:"\\?\\w"},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},f,{b:"("+hljs.RSR+")\\s*",c:[d,c,b,{cN:"regexp",b:"/",e:"/[a-z]*",i:"\\n",c:[hljs.BE]}],r:0}];u.c=v;e.c[1].c=v;return{dM:{l:g,k:n,c:v}}}(); +// ColorBox v1.3.20.1 - jQuery lightbox plugin +// (c) 2011 Jack Moore - jacklmoore.com +// License: http://www.opensource.org/licenses/mit-license.php +(function ($, document, window) { + var + // Default settings object. + // See http://jacklmoore.com/colorbox for details. + defaults = { + transition: "elastic", + speed: 300, + width: false, + initialWidth: "600", + innerWidth: false, + maxWidth: false, + height: false, + initialHeight: "450", + innerHeight: false, + maxHeight: false, + scalePhotos: true, + scrolling: true, + inline: false, + html: false, + iframe: false, + fastIframe: true, + photo: false, + href: false, + title: false, + rel: false, + opacity: 0.9, + preloading: true, + + current: "image {current} of {total}", + previous: "previous", + next: "next", + close: "close", + xhrError: "This content failed to load.", + imgError: "This image failed to load.", + + open: false, + returnFocus: true, + reposition: true, + loop: true, + slideshow: false, + slideshowAuto: true, + slideshowSpeed: 2500, + slideshowStart: "start slideshow", + slideshowStop: "stop slideshow", + onOpen: false, + onLoad: false, + onComplete: false, + onCleanup: false, + onClosed: false, + overlayClose: true, + escKey: true, + arrowKey: true, + top: false, + bottom: false, + left: false, + right: false, + fixed: false, + data: undefined + }, + + // Abstracting the HTML and event identifiers for easy rebranding + colorbox = 'colorbox', + prefix = 'cbox', + boxElement = prefix + 'Element', + + // Events + event_open = prefix + '_open', + event_load = prefix + '_load', + event_complete = prefix + '_complete', + event_cleanup = prefix + '_cleanup', + event_closed = prefix + '_closed', + event_purge = prefix + '_purge', + + // Special Handling for IE + isIE = !$.support.opacity && !$.support.style, // IE7 & IE8 + isIE6 = isIE && !window.XMLHttpRequest, // IE6 + event_ie6 = prefix + '_IE6', + + // Cached jQuery Object Variables + $overlay, + $box, + $wrap, + $content, + $topBorder, + $leftBorder, + $rightBorder, + $bottomBorder, + $related, + $window, + $loaded, + $loadingBay, + $loadingOverlay, + $title, + $current, + $slideshow, + $next, + $prev, + $close, + $groupControls, + + // Variables for cached values or use across multiple functions + settings, + interfaceHeight, + interfaceWidth, + loadedHeight, + loadedWidth, + element, + index, + photo, + open, + active, + closing, + loadingTimer, + publicMethod, + div = "div", + init; + + // **************** + // HELPER FUNCTIONS + // **************** + + // Convience function for creating new jQuery objects + function $tag(tag, id, css) { + var element = document.createElement(tag); + + if (id) { + element.id = prefix + id; + } + + if (css) { + element.style.cssText = css; + } + + return $(element); + } + + // Determine the next and previous members in a group. + function getIndex(increment) { + var + max = $related.length, + newIndex = (index + increment) % max; + + return (newIndex < 0) ? max + newIndex : newIndex; + } + + // Convert '%' and 'px' values to integers + function setSize(size, dimension) { + return Math.round((/%/.test(size) ? ((dimension === 'x' ? winWidth() : winHeight()) / 100) : 1) * parseInt(size, 10)); + } + + // Checks an href to see if it is a photo. + // There is a force photo option (photo: true) for hrefs that cannot be matched by this regex. + function isImage(url) { + return settings.photo || /\.(gif|png|jp(e|g|eg)|bmp|ico)((#|\?).*)?$/i.test(url); + } + + function winWidth() { + // $(window).width() is incorrect for some mobile browsers, but + // window.innerWidth is unsupported in IE8 and lower. + return window.innerWidth || $window.width(); + } + + function winHeight() { + return window.innerHeight || $window.height(); + } + + // Assigns function results to their respective properties + function makeSettings() { + var i, + data = $.data(element, colorbox); + + if (data == null) { + settings = $.extend({}, defaults); + if (console && console.log) { + console.log('Error: cboxElement missing settings object'); + } + } else { + settings = $.extend({}, data); + } + + for (i in settings) { + if ($.isFunction(settings[i]) && i.slice(0, 2) !== 'on') { // checks to make sure the function isn't one of the callbacks, they will be handled at the appropriate time. + settings[i] = settings[i].call(element); + } + } + + settings.rel = settings.rel || element.rel || $(element).data('rel') || 'nofollow'; + settings.href = settings.href || $(element).attr('href'); + settings.title = settings.title || element.title; + + if (typeof settings.href === "string") { + settings.href = $.trim(settings.href); + } + } + + function trigger(event, callback) { + $.event.trigger(event); + if (callback) { + callback.call(element); + } + } + + // Slideshow functionality + function slideshow() { + var + timeOut, + className = prefix + "Slideshow_", + click = "click." + prefix, + start, + stop, + clear; + + if (settings.slideshow && $related[1]) { + start = function () { + $slideshow + .html(settings.slideshowStop) + .unbind(click) + .bind(event_complete, function () { + if (settings.loop || $related[index + 1]) { + timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed); + } + }) + .bind(event_load, function () { + clearTimeout(timeOut); + }) + .one(click + ' ' + event_cleanup, stop); + $box.removeClass(className + "off").addClass(className + "on"); + timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed); + }; + + stop = function () { + clearTimeout(timeOut); + $slideshow + .html(settings.slideshowStart) + .unbind([event_complete, event_load, event_cleanup, click].join(' ')) + .one(click, function () { + publicMethod.next(); + start(); + }); + $box.removeClass(className + "on").addClass(className + "off"); + }; + + if (settings.slideshowAuto) { + start(); + } else { + stop(); + } + } else { + $box.removeClass(className + "off " + className + "on"); + } + } + + function launch(target) { + if (!closing) { + + element = target; + + makeSettings(); + + $related = $(element); + + index = 0; + + if (settings.rel !== 'nofollow') { + $related = $('.' + boxElement).filter(function () { + var data = $.data(this, colorbox), + relRelated; + + if (data) { + relRelated = $(this).data('rel') || data.rel || this.rel; + } + + return (relRelated === settings.rel); + }); + index = $related.index(element); + + // Check direct calls to ColorBox. + if (index === -1) { + $related = $related.add(element); + index = $related.length - 1; + } + } + + if (!open) { + open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys. + + $box.show(); + + if (settings.returnFocus) { + $(element).blur().one(event_closed, function () { + $(this).focus(); + }); + } + + // +settings.opacity avoids a problem in IE when using non-zero-prefixed-string-values, like '.5' + $overlay.css({"opacity": +settings.opacity, "cursor": settings.overlayClose ? "pointer" : "auto"}).show(); + + // Opens inital empty ColorBox prior to content being loaded. + settings.w = setSize(settings.initialWidth, 'x'); + settings.h = setSize(settings.initialHeight, 'y'); + publicMethod.position(); + + if (isIE6) { + $window.bind('resize.' + event_ie6 + ' scroll.' + event_ie6, function () { + $overlay.css({width: winWidth(), height: winHeight(), top: $window.scrollTop(), left: $window.scrollLeft()}); + }).trigger('resize.' + event_ie6); + } + + trigger(event_open, settings.onOpen); + + $groupControls.add($title).hide(); + + $close.html(settings.close).show(); + } + + publicMethod.load(true); + } + } + + // ColorBox's markup needs to be added to the DOM prior to being called + // so that the browser will go ahead and load the CSS background images. + function appendHTML() { + if (!$box && document.body) { + init = false; + + $window = $(window); + $box = $tag(div).attr({id: colorbox, 'class': isIE ? prefix + (isIE6 ? 'IE6' : 'IE') : ''}).hide(); + $overlay = $tag(div, "Overlay", isIE6 ? 'position:absolute' : '').hide(); + $loadingOverlay = $tag(div, "LoadingOverlay").add($tag(div, "LoadingGraphic")); + $wrap = $tag(div, "Wrapper"); + $content = $tag(div, "Content").append( + $loaded = $tag(div, "LoadedContent", 'width:0; height:0; overflow:hidden'), + $title = $tag(div, "Title"), + $current = $tag(div, "Current"), + $next = $tag(div, "Next"), + $prev = $tag(div, "Previous"), + $slideshow = $tag(div, "Slideshow").bind(event_open, slideshow), + $close = $tag(div, "Close") + ); + + $wrap.append( // The 3x3 Grid that makes up ColorBox + $tag(div).append( + $tag(div, "TopLeft"), + $topBorder = $tag(div, "TopCenter"), + $tag(div, "TopRight") + ), + $tag(div, false, 'clear:left').append( + $leftBorder = $tag(div, "MiddleLeft"), + $content, + $rightBorder = $tag(div, "MiddleRight") + ), + $tag(div, false, 'clear:left').append( + $tag(div, "BottomLeft"), + $bottomBorder = $tag(div, "BottomCenter"), + $tag(div, "BottomRight") + ) + ).find('div div').css({'float': 'left'}); + + $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none'); + + $groupControls = $next.add($prev).add($current).add($slideshow); + + $(document.body).append($overlay, $box.append($wrap, $loadingBay)); + } + } + + // Add ColorBox's event bindings + function addBindings() { + if ($box) { + if (!init) { + init = true; + + // Cache values needed for size calculations + interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();//Subtraction needed for IE6 + interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width(); + loadedHeight = $loaded.outerHeight(true); + loadedWidth = $loaded.outerWidth(true); + + // Setting padding to remove the need to do size conversions during the animation step. + $box.css({"padding-bottom": interfaceHeight, "padding-right": interfaceWidth}); + + // Anonymous functions here keep the public method from being cached, thereby allowing them to be redefined on the fly. + $next.click(function () { + publicMethod.next(); + }); + $prev.click(function () { + publicMethod.prev(); + }); + $close.click(function () { + publicMethod.close(); + }); + $overlay.click(function () { + if (settings.overlayClose) { + publicMethod.close(); + } + }); + + // Key Bindings + $(document).bind('keydown.' + prefix, function (e) { + var key = e.keyCode; + if (open && settings.escKey && key === 27) { + e.preventDefault(); + publicMethod.close(); + } + if (open && settings.arrowKey && $related[1]) { + if (key === 37) { + e.preventDefault(); + $prev.click(); + } else if (key === 39) { + e.preventDefault(); + $next.click(); + } + } + }); + + $('.' + boxElement, document).live('click', function (e) { + // ignore non-left-mouse-clicks and clicks modified with ctrl / command, shift, or alt. + // See: http://jacklmoore.com/notes/click-events/ + if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey)) { + e.preventDefault(); + launch(this); + } + }); + } + return true; + } + return false; + } + + // Don't do anything if ColorBox already exists. + if ($.colorbox) { + return; + } + + // Append the HTML when the DOM loads + $(appendHTML); + + + // **************** + // PUBLIC FUNCTIONS + // Usage format: $.fn.colorbox.close(); + // Usage from within an iframe: parent.$.fn.colorbox.close(); + // **************** + + publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) { + var $this = this; + + options = options || {}; + + appendHTML(); + + if (addBindings()) { + if (!$this[0]) { + if ($this.selector) { // if a selector was given and it didn't match any elements, go ahead and exit. + return $this; + } + // if no selector was given (ie. $.colorbox()), create a temporary element to work with + $this = $('<a/>'); + options.open = true; // assume an immediate open + } + + if (callback) { + options.onComplete = callback; + } + + $this.each(function () { + $.data(this, colorbox, $.extend({}, $.data(this, colorbox) || defaults, options)); + }).addClass(boxElement); + + if (($.isFunction(options.open) && options.open.call($this)) || options.open) { + launch($this[0]); + } + } + + return $this; + }; + + publicMethod.position = function (speed, loadedCallback) { + var + css, + top = 0, + left = 0, + offset = $box.offset(), + scrollTop, + scrollLeft; + + $window.unbind('resize.' + prefix); + + // remove the modal so that it doesn't influence the document width/height + $box.css({top: -9e4, left: -9e4}); + + scrollTop = $window.scrollTop(); + scrollLeft = $window.scrollLeft(); + + if (settings.fixed && !isIE6) { + offset.top -= scrollTop; + offset.left -= scrollLeft; + $box.css({position: 'fixed'}); + } else { + top = scrollTop; + left = scrollLeft; + $box.css({position: 'absolute'}); + } + + // keeps the top and left positions within the browser's viewport. + if (settings.right !== false) { + left += Math.max(winWidth() - settings.w - loadedWidth - interfaceWidth - setSize(settings.right, 'x'), 0); + } else if (settings.left !== false) { + left += setSize(settings.left, 'x'); + } else { + left += Math.round(Math.max(winWidth() - settings.w - loadedWidth - interfaceWidth, 0) / 2); + } + + if (settings.bottom !== false) { + top += Math.max(winHeight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.bottom, 'y'), 0); + } else if (settings.top !== false) { + top += setSize(settings.top, 'y'); + } else { + top += Math.round(Math.max(winHeight() - settings.h - loadedHeight - interfaceHeight, 0) / 2); + } + + $box.css({top: offset.top, left: offset.left}); + + // setting the speed to 0 to reduce the delay between same-sized content. + speed = ($box.width() === settings.w + loadedWidth && $box.height() === settings.h + loadedHeight) ? 0 : speed || 0; + + // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly, + // but it has to be shrank down around the size of div#colorbox when it's done. If not, + // it can invoke an obscure IE bug when using iframes. + $wrap[0].style.width = $wrap[0].style.height = "9999px"; + + function modalDimensions(that) { + $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = that.style.width; + $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = that.style.height; + } + + css = {width: settings.w + loadedWidth, height: settings.h + loadedHeight, top: top, left: left}; + if(speed===0){ // temporary workaround to side-step jQuery-UI 1.8 bug (http://bugs.jquery.com/ticket/12273) + $box.css(css); + } + $box.dequeue().animate(css, { + duration: speed, + complete: function () { + modalDimensions(this); + + active = false; + + // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation. + $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px"; + $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px"; + + if (settings.reposition) { + setTimeout(function () { // small delay before binding onresize due to an IE8 bug. + $window.bind('resize.' + prefix, publicMethod.position); + }, 1); + } + + if (loadedCallback) { + loadedCallback(); + } + }, + step: function () { + modalDimensions(this); + } + }); + }; + + publicMethod.resize = function (options) { + if (open) { + options = options || {}; + + if (options.width) { + settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth; + } + if (options.innerWidth) { + settings.w = setSize(options.innerWidth, 'x'); + } + $loaded.css({width: settings.w}); + + if (options.height) { + settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight; + } + if (options.innerHeight) { + settings.h = setSize(options.innerHeight, 'y'); + } + if (!options.innerHeight && !options.height) { + $loaded.css({height: "auto"}); + settings.h = $loaded.height(); + } + $loaded.css({height: settings.h}); + + publicMethod.position(settings.transition === "none" ? 0 : settings.speed); + } + }; + + publicMethod.prep = function (object) { + if (!open) { + return; + } + + var callback, speed = settings.transition === "none" ? 0 : settings.speed; + + $loaded.remove(); + $loaded = $tag(div, 'LoadedContent').append(object); + + function getWidth() { + settings.w = settings.w || $loaded.width(); + settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w; + return settings.w; + } + function getHeight() { + settings.h = settings.h || $loaded.height(); + settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h; + return settings.h; + } + + $loaded.hide() + .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations. + .css({width: getWidth(), overflow: settings.scrolling ? 'auto' : 'hidden'}) + .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height. + .prependTo($content); + + $loadingBay.hide(); + + // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width. + //$(photo).css({'float': 'none', marginLeft: 'auto', marginRight: 'auto'}); + + $(photo).css({'float': 'none'}); + + // Hides SELECT elements in IE6 because they would otherwise sit on top of the overlay. + if (isIE6) { + $('select').not($box.find('select')).filter(function () { + return this.style.visibility !== 'hidden'; + }).css({'visibility': 'hidden'}).one(event_cleanup, function () { + this.style.visibility = 'inherit'; + }); + } + + callback = function () { + var preload, + i, + total = $related.length, + iframe, + frameBorder = 'frameBorder', + allowTransparency = 'allowTransparency', + complete, + src, + img, + data; + + if (!open) { + return; + } + + function removeFilter() { + if (isIE) { + $box[0].style.removeAttribute('filter'); + } + } + + complete = function () { + clearTimeout(loadingTimer); + // Detaching forces Andriod stock browser to redraw the area underneat the loading overlay. Hiding alone isn't enough. + $loadingOverlay.detach().hide(); + trigger(event_complete, settings.onComplete); + }; + + if (isIE) { + //This fadeIn helps the bicubic resampling to kick-in. + if (photo) { + $loaded.fadeIn(100); + } + } + + $title.html(settings.title).add($loaded).show(); + + if (total > 1) { // handle grouping + if (typeof settings.current === "string") { + $current.html(settings.current.replace('{current}', index + 1).replace('{total}', total)).show(); + } + + $next[(settings.loop || index < total - 1) ? "show" : "hide"]().html(settings.next); + $prev[(settings.loop || index) ? "show" : "hide"]().html(settings.previous); + + if (settings.slideshow) { + $slideshow.show(); + } + + // Preloads images within a rel group + if (settings.preloading) { + preload = [ + getIndex(-1), + getIndex(1) + ]; + while (i = $related[preload.pop()]) { + data = $.data(i, colorbox); + + if (data && data.href) { + src = data.href; + if ($.isFunction(src)) { + src = src.call(i); + } + } else { + src = i.href; + } + + if (isImage(src)) { + img = new Image(); + img.src = src; + } + } + } + } else { + $groupControls.hide(); + } + + if (settings.iframe) { + iframe = $tag('iframe')[0]; + + if (frameBorder in iframe) { + iframe[frameBorder] = 0; + } + + if (allowTransparency in iframe) { + iframe[allowTransparency] = "true"; + } + + if (!settings.scrolling) { + iframe.scrolling = "no"; + } + + $(iframe) + .attr({ + src: settings.href, + name: (new Date()).getTime(), // give the iframe a unique name to prevent caching + 'class': prefix + 'Iframe', + allowFullScreen : true, // allow HTML5 video to go fullscreen + webkitAllowFullScreen : true, + mozallowfullscreen : true + }) + .one('load', complete) + .one(event_purge, function () { + iframe.src = "//about:blank"; + }) + .appendTo($loaded); + + if (settings.fastIframe) { + $(iframe).trigger('load'); + } + } else { + complete(); + } + + if (settings.transition === 'fade') { + $box.fadeTo(speed, 1, removeFilter); + } else { + removeFilter(); + } + }; + + if (settings.transition === 'fade') { + $box.fadeTo(speed, 0, function () { + publicMethod.position(0, callback); + }); + } else { + publicMethod.position(speed, callback); + } + }; + + publicMethod.load = function (launched) { + var href, setResize, prep = publicMethod.prep; + + active = true; + + photo = false; + + element = $related[index]; + + if (!launched) { + makeSettings(); + } + + trigger(event_purge); + + trigger(event_load, settings.onLoad); + + settings.h = settings.height ? + setSize(settings.height, 'y') - loadedHeight - interfaceHeight : + settings.innerHeight && setSize(settings.innerHeight, 'y'); + + settings.w = settings.width ? + setSize(settings.width, 'x') - loadedWidth - interfaceWidth : + settings.innerWidth && setSize(settings.innerWidth, 'x'); + + // Sets the minimum dimensions for use in image scaling + settings.mw = settings.w; + settings.mh = settings.h; + + // Re-evaluate the minimum width and height based on maxWidth and maxHeight values. + // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead. + if (settings.maxWidth) { + settings.mw = setSize(settings.maxWidth, 'x') - loadedWidth - interfaceWidth; + settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw; + } + if (settings.maxHeight) { + settings.mh = setSize(settings.maxHeight, 'y') - loadedHeight - interfaceHeight; + settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh; + } + + href = settings.href; + + loadingTimer = setTimeout(function () { + $loadingOverlay.show().appendTo($content); + }, 100); + + if (settings.inline) { + // Inserts an empty placeholder where inline content is being pulled from. + // An event is bound to put inline content back when ColorBox closes or loads new content. + $tag(div).hide().insertBefore($(href)[0]).one(event_purge, function () { + $(this).replaceWith($loaded.children()); + }); + prep($(href)); + } else if (settings.iframe) { + // IFrame element won't be added to the DOM until it is ready to be displayed, + // to avoid problems with DOM-ready JS that might be trying to run in that iframe. + prep(" "); + } else if (settings.html) { + prep(settings.html); + } else if (isImage(href)) { + $(photo = new Image()) + .addClass(prefix + 'Photo') + .error(function () { + settings.title = false; + prep($tag(div, 'Error').html(settings.imgError)); + }) + .load(function () { + var percent; + photo.onload = null; //stops animated gifs from firing the onload repeatedly. + + if (settings.scalePhotos) { + setResize = function () { + photo.height -= photo.height * percent; + photo.width -= photo.width * percent; + }; + if (settings.mw && photo.width > settings.mw) { + percent = (photo.width - settings.mw) / photo.width; + setResize(); + } + if (settings.mh && photo.height > settings.mh) { + percent = (photo.height - settings.mh) / photo.height; + setResize(); + } + } + + if (settings.h) { + photo.style.marginTop = Math.max(settings.h - photo.height, 0) / 2 + 'px'; + } + + if ($related[1] && (settings.loop || $related[index + 1])) { + photo.style.cursor = 'pointer'; + photo.onclick = function () { + publicMethod.next(); + }; + } + + if (isIE) { + photo.style.msInterpolationMode = 'bicubic'; + } + + setTimeout(function () { // A pause because Chrome will sometimes report a 0 by 0 size otherwise. + prep(photo); + }, 1); + }); + + setTimeout(function () { // A pause because Opera 10.6+ will sometimes not run the onload function otherwise. + photo.src = href; + }, 1); + } else if (href) { + $loadingBay.load(href, settings.data, function (data, status, xhr) { + prep(status === 'error' ? $tag(div, 'Error').html(settings.xhrError) : $(this).contents()); + }); + } + }; + + // Navigates to the next page/image in a set. + publicMethod.next = function () { + if (!active && $related[1] && (settings.loop || $related[index + 1])) { + index = getIndex(1); + publicMethod.load(); + } + }; + + publicMethod.prev = function () { + if (!active && $related[1] && (settings.loop || index)) { + index = getIndex(-1); + publicMethod.load(); + } + }; + + // Note: to use this within an iframe use the following format: parent.$.fn.colorbox.close(); + publicMethod.close = function () { + if (open && !closing) { + + closing = true; + + open = false; + + trigger(event_cleanup, settings.onCleanup); + + $window.unbind('.' + prefix + ' .' + event_ie6); + + $overlay.fadeTo(200, 0); + + $box.stop().fadeTo(300, 0, function () { + + $box.add($overlay).css({'opacity': 1, cursor: 'auto'}).hide(); + + trigger(event_purge); + + $loaded.remove(); + + setTimeout(function () { + closing = false; + trigger(event_closed, settings.onClosed); + }, 1); + }); + } + }; + + // Removes changes ColorBox made to the document, but does not remove the plugin + // from jQuery. + publicMethod.remove = function () { + $([]).add($box).add($overlay).remove(); + $box = null; + $('.' + boxElement) + .removeData(colorbox) + .removeClass(boxElement) + .die(); + }; + + // A method for fetching the current element ColorBox is referencing. + // returns a jQuery object. + publicMethod.element = function () { + return $(element); + }; + + publicMethod.settings = defaults; + +}(jQuery, document, window)); +/* + * File: jquery.dataTables.min.js + * Version: 1.7.0 + * Author: Allan Jardine (www.sprymedia.co.uk) + * Info: www.datatables.net + * + * Copyright 2008-2010 Allan Jardine, all rights reserved. + * + * This source file is free software, under either the GPL v2 license or a + * BSD style license, as supplied with this software. + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + */ + +(function(j,Y,p){j.fn.dataTableSettings=[];var E=j.fn.dataTableSettings;j.fn.dataTableExt={};var m=j.fn.dataTableExt;m.sVersion="1.7.0";m.sErrMode="alert";m.iApiIndex=0;m.oApi={};m.afnFiltering=[];m.aoFeatures=[];m.ofnSearch={};m.afnSortData=[];m.oStdClasses={sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active", +sPageButtonStaticDisabled:"paginate_button",sPageFirst:"first",sPagePrevious:"previous",sPageNext:"next",sPageLast:"last",sStripOdd:"odd",sStripEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled", +sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sFooterTH:""};m.oJUIClasses={sPagePrevEnabled:"fg-button ui-state-default ui-corner-left",sPagePrevDisabled:"fg-button ui-state-default ui-corner-left ui-state-disabled", +sPageNextEnabled:"fg-button ui-state-default ui-corner-right",sPageNextDisabled:"fg-button ui-state-default ui-corner-right ui-state-disabled",sPageJUINext:"ui-icon ui-icon-circle-arrow-e",sPageJUIPrev:"ui-icon ui-icon-circle-arrow-w",sPageButton:"fg-button ui-state-default",sPageButtonActive:"fg-button ui-state-default ui-state-disabled",sPageButtonStaticDisabled:"fg-button ui-state-default ui-state-disabled",sPageFirst:"first ui-corner-tl ui-corner-bl",sPagePrevious:"previous",sPageNext:"next", +sPageLast:"last ui-corner-tr ui-corner-br",sStripOdd:"odd",sStripEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate fg-buttonset fg-buttonset-multi paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"ui-state-default",sSortDesc:"ui-state-default",sSortable:"ui-state-default",sSortableAsc:"ui-state-default",sSortableDesc:"ui-state-default",sSortableNone:"ui-state-default", +sSortColumn:"sorting_",sSortJUIAsc:"css_right ui-icon ui-icon-triangle-1-n",sSortJUIDesc:"css_right ui-icon ui-icon-triangle-1-s",sSortJUI:"css_right ui-icon ui-icon-carat-2-n-s",sSortJUIAscAllowed:"css_right ui-icon ui-icon-carat-1-n",sSortJUIDescAllowed:"css_right ui-icon ui-icon-carat-1-s",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead ui-state-default",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot ui-state-default", +sScrollFootInner:"dataTables_scrollFootInner",sFooterTH:"ui-state-default"};m.oPagination={two_button:{fnInit:function(g,l,q){var r,u,y;if(g.bJUI){r=p.createElement("a");u=p.createElement("a");y=p.createElement("span");y.className=g.oClasses.sPageJUINext;u.appendChild(y);y=p.createElement("span");y.className=g.oClasses.sPageJUIPrev;r.appendChild(y)}else{r=p.createElement("div");u=p.createElement("div")}r.className=g.oClasses.sPagePrevDisabled;u.className=g.oClasses.sPageNextDisabled;r.title=g.oLanguage.oPaginate.sPrevious; +u.title=g.oLanguage.oPaginate.sNext;l.appendChild(r);l.appendChild(u);j(r).click(function(){g.oApi._fnPageChange(g,"previous")&&q(g)});j(u).click(function(){g.oApi._fnPageChange(g,"next")&&q(g)});j(r).bind("selectstart",function(){return false});j(u).bind("selectstart",function(){return false});if(g.sTableId!==""&&typeof g.aanFeatures.p=="undefined"){l.setAttribute("id",g.sTableId+"_paginate");r.setAttribute("id",g.sTableId+"_previous");u.setAttribute("id",g.sTableId+"_next")}},fnUpdate:function(g){if(g.aanFeatures.p)for(var l= +g.aanFeatures.p,q=0,r=l.length;q<r;q++)if(l[q].childNodes.length!==0){l[q].childNodes[0].className=g._iDisplayStart===0?g.oClasses.sPagePrevDisabled:g.oClasses.sPagePrevEnabled;l[q].childNodes[1].className=g.fnDisplayEnd()==g.fnRecordsDisplay()?g.oClasses.sPageNextDisabled:g.oClasses.sPageNextEnabled}}},iFullNumbersShowPages:5,full_numbers:{fnInit:function(g,l,q){var r=p.createElement("span"),u=p.createElement("span"),y=p.createElement("span"),C=p.createElement("span"),w=p.createElement("span");r.innerHTML= +g.oLanguage.oPaginate.sFirst;u.innerHTML=g.oLanguage.oPaginate.sPrevious;C.innerHTML=g.oLanguage.oPaginate.sNext;w.innerHTML=g.oLanguage.oPaginate.sLast;var x=g.oClasses;r.className=x.sPageButton+" "+x.sPageFirst;u.className=x.sPageButton+" "+x.sPagePrevious;C.className=x.sPageButton+" "+x.sPageNext;w.className=x.sPageButton+" "+x.sPageLast;l.appendChild(r);l.appendChild(u);l.appendChild(y);l.appendChild(C);l.appendChild(w);j(r).click(function(){g.oApi._fnPageChange(g,"first")&&q(g)});j(u).click(function(){g.oApi._fnPageChange(g, +"previous")&&q(g)});j(C).click(function(){g.oApi._fnPageChange(g,"next")&&q(g)});j(w).click(function(){g.oApi._fnPageChange(g,"last")&&q(g)});j("span",l).bind("mousedown",function(){return false}).bind("selectstart",function(){return false});if(g.sTableId!==""&&typeof g.aanFeatures.p=="undefined"){l.setAttribute("id",g.sTableId+"_paginate");r.setAttribute("id",g.sTableId+"_first");u.setAttribute("id",g.sTableId+"_previous");C.setAttribute("id",g.sTableId+"_next");w.setAttribute("id",g.sTableId+"_last")}}, +fnUpdate:function(g,l){if(g.aanFeatures.p){var q=m.oPagination.iFullNumbersShowPages,r=Math.floor(q/2),u=Math.ceil(g.fnRecordsDisplay()/g._iDisplayLength),y=Math.ceil(g._iDisplayStart/g._iDisplayLength)+1,C="",w,x=g.oClasses;if(u<q){r=1;w=u}else if(y<=r){r=1;w=q}else if(y>=u-r){r=u-q+1;w=u}else{r=y-Math.ceil(q/2)+1;w=r+q-1}for(q=r;q<=w;q++)C+=y!=q?'<span class="'+x.sPageButton+'">'+q+"</span>":'<span class="'+x.sPageButtonActive+'">'+q+"</span>";w=g.aanFeatures.p;var z,D=function(){g._iDisplayStart= +(this.innerHTML*1-1)*g._iDisplayLength;l(g);return false},L=function(){return false};q=0;for(r=w.length;q<r;q++)if(w[q].childNodes.length!==0){z=w[q].childNodes[2];z.innerHTML=C;j("span",z).click(D).bind("mousedown",L).bind("selectstart",L);z=w[q].getElementsByTagName("span");z=[z[0],z[1],z[z.length-2],z[z.length-1]];j(z).removeClass(x.sPageButton+" "+x.sPageButtonActive+" "+x.sPageButtonStaticDisabled);if(y==1){z[0].className+=" "+x.sPageButtonStaticDisabled;z[1].className+=" "+x.sPageButtonStaticDisabled}else{z[0].className+= +" "+x.sPageButton;z[1].className+=" "+x.sPageButton}if(u===0||y==u||g._iDisplayLength==-1){z[2].className+=" "+x.sPageButtonStaticDisabled;z[3].className+=" "+x.sPageButtonStaticDisabled}else{z[2].className+=" "+x.sPageButton;z[3].className+=" "+x.sPageButton}}}}}};m.oSort={"string-asc":function(g,l){g=g.toLowerCase();l=l.toLowerCase();return g<l?-1:g>l?1:0},"string-desc":function(g,l){g=g.toLowerCase();l=l.toLowerCase();return g<l?1:g>l?-1:0},"html-asc":function(g,l){g=g.replace(/<.*?>/g,"").toLowerCase(); +l=l.replace(/<.*?>/g,"").toLowerCase();return g<l?-1:g>l?1:0},"html-desc":function(g,l){g=g.replace(/<.*?>/g,"").toLowerCase();l=l.replace(/<.*?>/g,"").toLowerCase();return g<l?1:g>l?-1:0},"date-asc":function(g,l){g=Date.parse(g);l=Date.parse(l);if(isNaN(g)||g==="")g=Date.parse("01/01/1970 00:00:00");if(isNaN(l)||l==="")l=Date.parse("01/01/1970 00:00:00");return g-l},"date-desc":function(g,l){g=Date.parse(g);l=Date.parse(l);if(isNaN(g)||g==="")g=Date.parse("01/01/1970 00:00:00");if(isNaN(l)||l=== +"")l=Date.parse("01/01/1970 00:00:00");return l-g},"numeric-asc":function(g,l){return(g=="-"||g===""?0:g*1)-(l=="-"||l===""?0:l*1)},"numeric-desc":function(g,l){return(l=="-"||l===""?0:l*1)-(g=="-"||g===""?0:g*1)}};m.aTypes=[function(g){if(g.length===0)return"numeric";var l,q=false;l=g.charAt(0);if("0123456789-".indexOf(l)==-1)return null;for(var r=1;r<g.length;r++){l=g.charAt(r);if("0123456789.".indexOf(l)==-1)return null;if(l=="."){if(q)return null;q=true}}return"numeric"},function(g){var l=Date.parse(g); +if(l!==null&&!isNaN(l)||g.length===0)return"date";return null},function(g){if(g.indexOf("<")!=-1&&g.indexOf(">")!=-1)return"html";return null}];m.fnVersionCheck=function(g){var l=function(w,x){for(;w.length<x;)w+="0";return w},q=m.sVersion.split(".");g=g.split(".");for(var r="",u="",y=0,C=g.length;y<C;y++){r+=l(q[y],3);u+=l(g[y],3)}return parseInt(r,10)>=parseInt(u,10)};m._oExternConfig={iNextUnique:0};j.fn.dataTable=function(g){function l(){this.fnRecordsTotal=function(){return this.oFeatures.bServerSide? +this._iRecordsTotal:this.aiDisplayMaster.length};this.fnRecordsDisplay=function(){return this.oFeatures.bServerSide?this._iRecordsDisplay:this.aiDisplay.length};this.fnDisplayEnd=function(){return this.oFeatures.bServerSide?this.oFeatures.bPaginate===false?this._iDisplayStart+this.aiDisplay.length:Math.min(this._iDisplayStart+this._iDisplayLength,this._iDisplayStart+this.aiDisplay.length):this._iDisplayEnd};this.sInstance=this.oInstance=null;this.oFeatures={bPaginate:true,bLengthChange:true,bFilter:true, +bSort:true,bInfo:true,bAutoWidth:true,bProcessing:false,bSortClasses:true,bStateSave:false,bServerSide:false};this.oScroll={sX:"",sXInner:"",sY:"",bCollapse:false,iBarWidth:0};this.aanFeatures=[];this.oLanguage={sProcessing:"Processing...",sLengthMenu:"Show _MENU_ entries",sZeroRecords:"No matching records found",sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)", +sInfoPostFix:"",sSearch:"Search:",sUrl:"",oPaginate:{sFirst:"First",sPrevious:"Previous",sNext:"Next",sLast:"Last"}};this.aoData=[];this.aiDisplay=[];this.aiDisplayMaster=[];this.aoColumns=[];this.iNextId=0;this.asDataSearch=[];this.oPreviousSearch={sSearch:"",bRegex:false,bSmart:true};this.aoPreSearchCols=[];this.aaSorting=[[0,"asc",0]];this.aaSortingFixed=null;this.asStripClasses=[];this.asDestoryStrips=[];this.fnFooterCallback=this.fnHeaderCallback=this.fnRowCallback=null;this.aoDrawCallback=[]; +this.fnInitComplete=null;this.sTableId="";this.nTableWrapper=this.nTBody=this.nTFoot=this.nTHead=this.nTable=null;this.iDefaultSortIndex=0;this.bInitialised=false;this.aoOpenRows=[];this.sDom="lfrtip";this.sPaginationType="two_button";this.iCookieDuration=7200;this.sCookiePrefix="SpryMedia_DataTables_";this.sAjaxSource=null;this.bAjaxDataGet=true;this.fnServerData=function(a,b,c){j.ajax({url:a,data:b,success:c,dataType:"json",cache:false,error:function(){alert("DataTables warning: JSON data from server failed to load or be parsed. This is most likely to be caused by a JSON formatting error.")}})}; +this.fnFormatNumber=function(a){if(a<1E3)return a;else{var b=a+"";a=b.split("");var c="";b=b.length;for(var d=0;d<b;d++){if(d%3===0&&d!==0)c=","+c;c=a[b-d-1]+c}}return c};this.aLengthMenu=[10,25,50,100];this.iDraw=0;this.iDrawError=-1;this._iDisplayLength=10;this._iDisplayStart=0;this._iDisplayEnd=10;this._iRecordsDisplay=this._iRecordsTotal=0;this.bJUI=false;this.oClasses=m.oStdClasses;this.bSorted=this.bFiltered=false;this.oInit=null}function q(a){return function(){var b=[B(this[m.iApiIndex])].concat(Array.prototype.slice.call(arguments)); +return m.oApi[a].apply(this,b)}}function r(a){if(a.bInitialised===false)setTimeout(function(){r(a)},200);else{na(a);z(a);if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();F(a);D(a)}if(a.sAjaxSource!==null&&!a.oFeatures.bServerSide){K(a,true);a.fnServerData.call(a.oInstance,a.sAjaxSource,null,function(b){for(var c=0;c<b.aaData.length;c++)w(a,b.aaData[c]);a.iInitDisplayStart=a._iDisplayStart;if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();F(a);D(a)}K(a,false); +typeof a.fnInitComplete=="function"&&a.fnInitComplete.call(a.oInstance,a,b)})}else{typeof a.fnInitComplete=="function"&&a.fnInitComplete.call(a.oInstance,a);a.oFeatures.bServerSide||K(a,false)}}}function u(a,b,c){n(a.oLanguage,b,"sProcessing");n(a.oLanguage,b,"sLengthMenu");n(a.oLanguage,b,"sEmptyTable");n(a.oLanguage,b,"sZeroRecords");n(a.oLanguage,b,"sInfo");n(a.oLanguage,b,"sInfoEmpty");n(a.oLanguage,b,"sInfoFiltered");n(a.oLanguage,b,"sInfoPostFix");n(a.oLanguage,b,"sSearch");if(typeof b.oPaginate!= +"undefined"){n(a.oLanguage.oPaginate,b.oPaginate,"sFirst");n(a.oLanguage.oPaginate,b.oPaginate,"sPrevious");n(a.oLanguage.oPaginate,b.oPaginate,"sNext");n(a.oLanguage.oPaginate,b.oPaginate,"sLast")}typeof b.sEmptyTable=="undefined"&&typeof b.sZeroRecords!="undefined"&&n(a.oLanguage,b,"sZeroRecords","sEmptyTable");c&&r(a)}function y(a,b){a.aoColumns[a.aoColumns.length++]={sType:null,_bAutoType:true,bVisible:true,bSearchable:true,bSortable:true,asSorting:["asc","desc"],sSortingClass:a.oClasses.sSortable, +sSortingClassJUI:a.oClasses.sSortJUI,sTitle:b?b.innerHTML:"",sName:"",sWidth:null,sWidthOrig:null,sClass:null,fnRender:null,bUseRendered:true,iDataSort:a.aoColumns.length-1,sSortDataType:"std",nTh:b?b:p.createElement("th"),nTf:null};b=a.aoColumns.length-1;if(typeof a.aoPreSearchCols[b]=="undefined"||a.aoPreSearchCols[b]===null)a.aoPreSearchCols[b]={sSearch:"",bRegex:false,bSmart:true};else{if(typeof a.aoPreSearchCols[b].bRegex=="undefined")a.aoPreSearchCols[b].bRegex=true;if(typeof a.aoPreSearchCols[b].bSmart== +"undefined")a.aoPreSearchCols[b].bSmart=true}C(a,b,null)}function C(a,b,c){b=a.aoColumns[b];if(typeof c!="undefined"&&c!==null){if(typeof c.sType!="undefined"){b.sType=c.sType;b._bAutoType=false}n(b,c,"bVisible");n(b,c,"bSearchable");n(b,c,"bSortable");n(b,c,"sTitle");n(b,c,"sName");n(b,c,"sWidth");n(b,c,"sWidth","sWidthOrig");n(b,c,"sClass");n(b,c,"fnRender");n(b,c,"bUseRendered");n(b,c,"iDataSort");n(b,c,"asSorting");n(b,c,"sSortDataType")}if(!a.oFeatures.bSort)b.bSortable=false;if(!b.bSortable|| +j.inArray("asc",b.asSorting)==-1&&j.inArray("desc",b.asSorting)==-1){b.sSortingClass=a.oClasses.sSortableNone;b.sSortingClassJUI=""}else if(j.inArray("asc",b.asSorting)!=-1&&j.inArray("desc",b.asSorting)==-1){b.sSortingClass=a.oClasses.sSortableAsc;b.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed}else if(j.inArray("asc",b.asSorting)==-1&&j.inArray("desc",b.asSorting)!=-1){b.sSortingClass=a.oClasses.sSortableDesc;b.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed}}function w(a,b){if(b.length!=a.aoColumns.length&& +a.iDrawError!=a.iDraw){J(a,0,"Added data does not match known number of columns");a.iDrawError=a.iDraw;return-1}b=b.slice();var c=a.aoData.length;a.aoData.push({nTr:p.createElement("tr"),_iId:a.iNextId++,_aData:b,_anHidden:[],_sRowStripe:""});for(var d,f,e=0;e<b.length;e++){d=p.createElement("td");if(b[e]===null)b[e]="";if(typeof b[e]!="string")b[e]+="";b[e]=j.trim(b[e]);if(typeof a.aoColumns[e].fnRender=="function"){f=a.aoColumns[e].fnRender({iDataRow:c,iDataColumn:e,aData:b,oSettings:a});d.innerHTML= +f;if(a.aoColumns[e].bUseRendered)a.aoData[c]._aData[e]=f}else d.innerHTML=b[e];if(a.aoColumns[e].sClass!==null)d.className=a.aoColumns[e].sClass;if(a.aoColumns[e]._bAutoType&&a.aoColumns[e].sType!="string"){f=Z(a.aoData[c]._aData[e]);if(a.aoColumns[e].sType===null)a.aoColumns[e].sType=f;else if(a.aoColumns[e].sType!=f)a.aoColumns[e].sType="string"}if(a.aoColumns[e].bVisible)a.aoData[c].nTr.appendChild(d);else a.aoData[c]._anHidden[e]=d}a.aiDisplayMaster.push(c);return c}function x(a){var b,c,d,f, +e,i,h,k;if(a.sAjaxSource===null){h=a.nTBody.childNodes;b=0;for(c=h.length;b<c;b++)if(h[b].nodeName.toUpperCase()=="TR"){i=a.aoData.length;a.aoData.push({nTr:h[b],_iId:a.iNextId++,_aData:[],_anHidden:[],_sRowStripe:""});a.aiDisplayMaster.push(i);k=a.aoData[i]._aData;i=h[b].childNodes;d=e=0;for(f=i.length;d<f;d++)if(i[d].nodeName.toUpperCase()=="TD"){k[e]=j.trim(i[d].innerHTML);e++}}}h=S(a);i=[];b=0;for(c=h.length;b<c;b++){d=0;for(f=h[b].childNodes.length;d<f;d++){e=h[b].childNodes[d];e.nodeName.toUpperCase()== +"TD"&&i.push(e)}}i.length!=h.length*a.aoColumns.length&&J(a,1,"Unexpected number of TD elements. Expected "+h.length*a.aoColumns.length+" and got "+i.length+". DataTables does not support rowspan / colspan in the table body, and there must be one cell for each row/column combination.");h=0;for(d=a.aoColumns.length;h<d;h++){if(a.aoColumns[h].sTitle===null)a.aoColumns[h].sTitle=a.aoColumns[h].nTh.innerHTML;f=a.aoColumns[h]._bAutoType;e=typeof a.aoColumns[h].fnRender=="function";k=a.aoColumns[h].sClass!== +null;var o=a.aoColumns[h].bVisible,t,s;if(f||e||k||!o){b=0;for(c=a.aoData.length;b<c;b++){t=i[b*d+h];if(f)if(a.aoColumns[h].sType!="string"){s=Z(a.aoData[b]._aData[h]);if(a.aoColumns[h].sType===null)a.aoColumns[h].sType=s;else if(a.aoColumns[h].sType!=s)a.aoColumns[h].sType="string"}if(e){s=a.aoColumns[h].fnRender({iDataRow:b,iDataColumn:h,aData:a.aoData[b]._aData,oSettings:a});t.innerHTML=s;if(a.aoColumns[h].bUseRendered)a.aoData[b]._aData[h]=s}if(k)t.className+=" "+a.aoColumns[h].sClass;if(!o){a.aoData[b]._anHidden[h]= +t;t.parentNode.removeChild(t)}}}}}function z(a){var b,c,d,f=0;if(a.nTHead.getElementsByTagName("th").length!==0){b=0;for(d=a.aoColumns.length;b<d;b++){c=a.aoColumns[b].nTh;if(a.aoColumns[b].bVisible){if(a.aoColumns[b].sWidth!==null)c.style.width=a.aoColumns[b].sWidth;if(a.aoColumns[b].sTitle!=c.innerHTML)c.innerHTML=a.aoColumns[b].sTitle}else{c.parentNode.removeChild(c);f++}}}else{f=p.createElement("tr");b=0;for(d=a.aoColumns.length;b<d;b++){c=a.aoColumns[b].nTh;c.innerHTML=a.aoColumns[b].sTitle; +if(a.aoColumns[b].bVisible){if(a.aoColumns[b].sClass!==null)c.className=a.aoColumns[b].sClass;if(a.aoColumns[b].sWidth!==null)c.style.width=a.aoColumns[b].sWidth;f.appendChild(c)}}j(a.nTHead).html("")[0].appendChild(f)}if(a.bJUI){b=0;for(d=a.aoColumns.length;b<d;b++)a.aoColumns[b].nTh.insertBefore(p.createElement("span"),a.aoColumns[b].nTh.firstChild)}if(a.oFeatures.bSort){for(b=0;b<a.aoColumns.length;b++)a.aoColumns[b].bSortable!==false?$(a,a.aoColumns[b].nTh,b):j(a.aoColumns[b].nTh).addClass(a.oClasses.sSortableNone); +j("th",a.nTHead).mousedown(function(){this.onselectstart=function(){return false};return false})}if(a.nTFoot!==null){f=0;c=a.nTFoot.getElementsByTagName("th");b=0;for(d=c.length;b<d;b++)if(typeof a.aoColumns[b]!="undefined"){a.aoColumns[b].nTf=c[b-f];if(a.oClasses.sFooterTH!=="")a.aoColumns[b].nTf.className+=" "+a.oClasses.sFooterTH;if(!a.aoColumns[b].bVisible){c[b-f].parentNode.removeChild(c[b-f]);f++}}}}function D(a){var b,c,d=[],f=0,e=false;b=a.asStripClasses.length;c=a.aoOpenRows.length;if(typeof a.iInitDisplayStart!= +"undefined"&&a.iInitDisplayStart!=-1){a._iDisplayStart=a.oFeatures.bServerSide?a.iInitDisplayStart:a.iInitDisplayStart>=a.fnRecordsDisplay()?0:a.iInitDisplayStart;a.iInitDisplayStart=-1;F(a)}if(!(a.oFeatures.bServerSide&&!oa(a))){if(a.aiDisplay.length!==0){var i=a._iDisplayStart,h=a._iDisplayEnd;if(a.oFeatures.bServerSide){i=0;h=a.aoData.length}for(i=i;i<h;i++){var k=a.aoData[a.aiDisplay[i]],o=k.nTr;if(b!==0){var t=a.asStripClasses[f%b];if(k._sRowStripe!=t){j(o).removeClass(k._sRowStripe).addClass(t); +k._sRowStripe=t}}if(typeof a.fnRowCallback=="function"){o=a.fnRowCallback.call(a.oInstance,o,a.aoData[a.aiDisplay[i]]._aData,f,i);if(!o&&!e){J(a,0,"A node was not returned by fnRowCallback");e=true}}d.push(o);f++;if(c!==0)for(k=0;k<c;k++)o==a.aoOpenRows[k].nParent&&d.push(a.aoOpenRows[k].nTr)}}else{d[0]=p.createElement("tr");if(typeof a.asStripClasses[0]!="undefined")d[0].className=a.asStripClasses[0];e=p.createElement("td");e.setAttribute("valign","top");e.colSpan=T(a);e.className=a.oClasses.sRowEmpty; +e.innerHTML=typeof a.oLanguage.sEmptyTable!="undefined"&&a.fnRecordsTotal()===0?a.oLanguage.sEmptyTable:a.oLanguage.sZeroRecords.replace("_MAX_",a.fnFormatNumber(a.fnRecordsTotal()));d[f].appendChild(e)}typeof a.fnHeaderCallback=="function"&&a.fnHeaderCallback.call(a.oInstance,j(">tr",a.nTHead)[0],V(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay);typeof a.fnFooterCallback=="function"&&a.fnFooterCallback.call(a.oInstance,j(">tr",a.nTFoot)[0],V(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay);f= +p.createDocumentFragment();b=p.createDocumentFragment();if(a.nTBody){e=a.nTBody.parentNode;b.appendChild(a.nTBody);c=a.nTBody.childNodes;for(b=c.length-1;b>=0;b--)c[b].parentNode.removeChild(c[b]);b=0;for(c=d.length;b<c;b++)f.appendChild(d[b]);a.nTBody.appendChild(f);e!==null&&e.appendChild(a.nTBody)}if(typeof a._bInitComplete=="undefined"){a._bInitComplete=true;a.nTableWrapper!=a.nTable.parentNode&&j(a.nTableWrapper).width()>j(a.nTable.parentNode).width()&&U(a)}b=0;for(c=a.aoDrawCallback.length;b< +c;b++)a.aoDrawCallback[b].fn.call(a.oInstance,a);a.bSorted=false;a.bFiltered=false}}function L(a){if(a.oFeatures.bSort)O(a,a.oPreviousSearch);else if(a.oFeatures.bFilter)P(a,a.oPreviousSearch);else{F(a);D(a)}}function oa(a){if(a.bAjaxDataGet){K(a,true);var b=a.aoColumns.length,c=[],d;a.iDraw++;c.push({name:"sEcho",value:a.iDraw});c.push({name:"iColumns",value:b});c.push({name:"sColumns",value:aa(a)});c.push({name:"iDisplayStart",value:a._iDisplayStart});c.push({name:"iDisplayLength",value:a.oFeatures.bPaginate!== +false?a._iDisplayLength:-1});if(a.oFeatures.bFilter!==false){c.push({name:"sSearch",value:a.oPreviousSearch.sSearch});c.push({name:"bRegex",value:a.oPreviousSearch.bRegex});for(d=0;d<b;d++){c.push({name:"sSearch_"+d,value:a.aoPreSearchCols[d].sSearch});c.push({name:"bRegex_"+d,value:a.aoPreSearchCols[d].bRegex});c.push({name:"bSearchable_"+d,value:a.aoColumns[d].bSearchable})}}if(a.oFeatures.bSort!==false){var f=a.aaSortingFixed!==null?a.aaSortingFixed.length:0,e=a.aaSorting.length;c.push({name:"iSortingCols", +value:f+e});for(d=0;d<f;d++){c.push({name:"iSortCol_"+d,value:a.aaSortingFixed[d][0]});c.push({name:"sSortDir_"+d,value:a.aaSortingFixed[d][1]})}for(d=0;d<e;d++){c.push({name:"iSortCol_"+(d+f),value:a.aaSorting[d][0]});c.push({name:"sSortDir_"+(d+f),value:a.aaSorting[d][1]})}for(d=0;d<b;d++)c.push({name:"bSortable_"+d,value:a.aoColumns[d].bSortable})}a.fnServerData.call(a.oInstance,a.sAjaxSource,c,function(i){pa(a,i)});return false}else return true}function pa(a,b){if(typeof b.sEcho!="undefined")if(b.sEcho* +1<a.iDraw)return;else a.iDraw=b.sEcho*1;ba(a);a._iRecordsTotal=b.iTotalRecords;a._iRecordsDisplay=b.iTotalDisplayRecords;var c=aa(a);if(c=typeof b.sColumns!="undefined"&&c!==""&&b.sColumns!=c)var d=qa(a,b.sColumns);for(var f=0,e=b.aaData.length;f<e;f++)if(c){for(var i=[],h=0,k=a.aoColumns.length;h<k;h++)i.push(b.aaData[f][d[h]]);w(a,i)}else w(a,b.aaData[f]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=false;D(a);a.bAjaxDataGet=true;K(a,false)}function na(a){var b=p.createElement("div");a.nTable.parentNode.insertBefore(b, +a.nTable);a.nTableWrapper=p.createElement("div");a.nTableWrapper.className=a.oClasses.sWrapper;a.sTableId!==""&&a.nTableWrapper.setAttribute("id",a.sTableId+"_wrapper");for(var c=a.nTableWrapper,d=a.sDom.split(""),f,e,i,h,k,o,t,s=0;s<d.length;s++){e=0;i=d[s];if(i=="<"){h=p.createElement("div");k=d[s+1];if(k=="'"||k=='"'){o="";for(t=2;d[s+t]!=k;){o+=d[s+t];t++}if(o=="H")o="fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix";else if(o=="F")o="fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"; +h.className=o;s+=t}c.appendChild(h);c=h}else if(i==">")c=c.parentNode;else if(i=="l"&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange){f=ra(a);e=1}else if(i=="f"&&a.oFeatures.bFilter){f=sa(a);e=1}else if(i=="r"&&a.oFeatures.bProcessing){f=ta(a);e=1}else if(i=="t"){f=ua(a);e=1}else if(i=="i"&&a.oFeatures.bInfo){f=va(a);e=1}else if(i=="p"&&a.oFeatures.bPaginate){f=wa(a);e=1}else if(m.aoFeatures.length!==0){h=m.aoFeatures;k=0;for(o=h.length;k<o;k++)if(i==h[k].cFeature){if(f=h[k].fnInit(a))e=1;break}}if(e== +1){if(typeof a.aanFeatures[i]!="object")a.aanFeatures[i]=[];a.aanFeatures[i].push(f);c.appendChild(f)}}b.parentNode.replaceChild(a.nTableWrapper,b)}function ua(a){if(a.oScroll.sX===""&&a.oScroll.sY==="")return a.nTable;var b=p.createElement("div"),c=p.createElement("div"),d=p.createElement("div"),f=p.createElement("div"),e=p.createElement("div"),i=p.createElement("div"),h=a.nTable.cloneNode(false),k=a.nTable.cloneNode(false),o=a.nTable.getElementsByTagName("thead")[0],t=a.nTable.getElementsByTagName("tfoot").length=== +0?null:a.nTable.getElementsByTagName("tfoot")[0],s=typeof g.bJQueryUI!="undefined"&&g.bJQueryUI?m.oJUIClasses:m.oStdClasses;c.appendChild(d);e.appendChild(i);f.appendChild(a.nTable);b.appendChild(c);b.appendChild(f);d.appendChild(h);h.appendChild(o);if(t!==null){b.appendChild(e);i.appendChild(k);k.appendChild(t)}b.className=s.sScrollWrapper;c.className=s.sScrollHead;d.className=s.sScrollHeadInner;f.className=s.sScrollBody;e.className=s.sScrollFoot;i.className=s.sScrollFootInner;c.style.overflow="hidden"; +e.style.overflow="hidden";f.style.overflow="auto";c.style.border="0";e.style.border="0";d.style.width="150%";h.removeAttribute("id");h.style.marginLeft="0";a.nTable.style.marginLeft="0";if(t!==null){k.removeAttribute("id");k.style.marginLeft="0"}d=j(">caption",a.nTable);i=0;for(k=d.length;i<k;i++)h.appendChild(d[i]);if(a.oScroll.sX!==""){c.style.width=v(a.oScroll.sX);f.style.width=v(a.oScroll.sX);if(t!==null)e.style.width=v(a.oScroll.sX);j(f).scroll(function(){c.scrollLeft=this.scrollLeft;if(t!== +null)e.scrollLeft=this.scrollLeft})}if(a.oScroll.sY!=="")f.style.height=v(a.oScroll.sY);a.aoDrawCallback.push({fn:xa,sName:"scrolling"});a.nScrollHead=c;a.nScrollFoot=e;return b}function xa(a){var b=a.nScrollHead.getElementsByTagName("div")[0],c=b.getElementsByTagName("table")[0],d=a.nTable.parentNode,f,e,i,h,k,o,t,s,H=[];i=a.nTable.getElementsByTagName("thead");i.length>0&&a.nTable.removeChild(i[0]);if(a.nTFoot!==null){k=a.nTable.getElementsByTagName("tfoot");k.length>0&&a.nTable.removeChild(k[0])}i= +a.nTHead.cloneNode(true);a.nTable.insertBefore(i,a.nTable.childNodes[0]);if(a.nTFoot!==null){k=a.nTFoot.cloneNode(true);a.nTable.insertBefore(k,a.nTable.childNodes[1])}var I=ca(i);f=0;for(e=I.length;f<e;f++){t=da(a,f);I[f].style.width=a.aoColumns[t].sWidth}a.nTFoot!==null&&M(function(A){A.style.width=""},k.getElementsByTagName("tr"));f=j(a.nTable).outerWidth();if(a.oScroll.sX===""){a.nTable.style.width="100%";if(j.browser.msie&&j.browser.version<=7)a.nTable.style.width=v(j(a.nTable).outerWidth()- +a.oScroll.iBarWidth)}else if(a.oScroll.sXInner!=="")a.nTable.style.width=v(a.oScroll.sXInner);else if(f==j(d).width()&&j(d).height()<j(a.nTable).height()){a.nTable.style.width=v(f-a.oScroll.iBarWidth);if(j(a.nTable).outerWidth()>f-a.oScroll.iBarWidth)a.nTable.style.width=v(f)}else a.nTable.style.width=v(f);f=j(a.nTable).outerWidth();e=a.nTHead.getElementsByTagName("tr");i=i.getElementsByTagName("tr");M(function(A,G){o=A.style;o.paddingTop="0";o.paddingBottom="0";o.borderTopWidth="0";o.borderBottomWidth= +"0";o.height=0;s=j(A).width();G.style.width=v(s);H.push(s)},i,e);if(a.nTFoot!==null){h=k.getElementsByTagName("tr");k=a.nTFoot.getElementsByTagName("tr");M(function(A,G){o=A.style;o.paddingTop="0";o.paddingBottom="0";o.borderTopWidth="0";o.borderBottomWidth="0";s=j(A).width();G.style.width=v(s);H.push(s)},h,k)}M(function(A){A.innerHTML="";A.style.width=v(H.shift())},i);a.nTFoot!==null&&M(function(A){A.innerHTML="";A.style.width=v(H.shift())},h);if(j(a.nTable).outerWidth()<f)if(a.oScroll.sX==="")J(a, +1,"The table cannot fit into the current element which will cause column misalignment. It is suggested that you enable x-scrolling or increase the width the table has in which to be drawn");else a.oScroll.sXInner!==""&&J(a,1,"The table cannot fit into the current element which will cause column misalignment. It is suggested that you increase the sScrollXInner property to allow it to draw in a larger area, or simply remove that parameter to allow automatic calculation");if(a.oScroll.sY==="")if(j.browser.msie&& +j.browser.version<=7)d.style.height=v(a.nTable.offsetHeight+a.oScroll.iBarWidth);if(a.oScroll.sY!==""&&a.oScroll.bCollapse){d.style.height=v(a.oScroll.sY);h=a.oScroll.sX!==""&&a.nTable.offsetWidth>d.offsetWidth?a.oScroll.iBarWidth:0;if(a.nTable.offsetHeight<d.offsetHeight)d.style.height=v(j(a.nTable).height()+h)}c.style.width=v(j(a.nTable).outerWidth());b.style.width=v(j(a.nTable).outerWidth()+a.oScroll.iBarWidth);if(a.nTFoot!==null){b=a.nScrollFoot.getElementsByTagName("div")[0];c=b.getElementsByTagName("table")[0]; +b.style.width=v(a.nTable.offsetWidth+a.oScroll.iBarWidth);c.style.width=v(a.nTable.offsetWidth)}}function U(a){if(a.oFeatures.bAutoWidth===false)return false;ea(a);for(var b=0,c=a.aoColumns.length;b<c;b++)a.aoColumns[b].nTh.style.width=a.aoColumns[b].sWidth}function sa(a){var b=p.createElement("div");a.sTableId!==""&&typeof a.aanFeatures.f=="undefined"&&b.setAttribute("id",a.sTableId+"_filter");b.className=a.oClasses.sFilter;b.innerHTML=a.oLanguage.sSearch+(a.oLanguage.sSearch===""?"":" ")+'<input type="text" />'; +var c=j("input",b);c.val(a.oPreviousSearch.sSearch.replace('"',"""));c.keyup(function(){for(var d=a.aanFeatures.f,f=0,e=d.length;f<e;f++)d[f]!=this.parentNode&&j("input",d[f]).val(this.value);P(a,{sSearch:this.value,bRegex:a.oPreviousSearch.bRegex,bSmart:a.oPreviousSearch.bSmart})});c.keypress(function(d){if(d.keyCode==13)return false});return b}function P(a,b,c){ya(a,b.sSearch,c,b.bRegex,b.bSmart);for(b=0;b<a.aoPreSearchCols.length;b++)za(a,a.aoPreSearchCols[b].sSearch,b,a.aoPreSearchCols[b].bRegex, +a.aoPreSearchCols[b].bSmart);m.afnFiltering.length!==0&&Aa(a);a.bFiltered=true;a._iDisplayStart=0;F(a);D(a);Q(a,0)}function Aa(a){for(var b=m.afnFiltering,c=0,d=b.length;c<d;c++)for(var f=0,e=0,i=a.aiDisplay.length;e<i;e++){var h=a.aiDisplay[e-f];if(!b[c](a,a.aoData[h]._aData,h)){a.aiDisplay.splice(e-f,1);f++}}}function za(a,b,c,d,f){if(b!==""){var e=0;b=fa(b,d,f);for(d=a.aiDisplay.length-1;d>=0;d--){f=ga(a.aoData[a.aiDisplay[d]]._aData[c],a.aoColumns[c].sType);if(!b.test(f)){a.aiDisplay.splice(d, +1);e++}}}}function ya(a,b,c,d,f){var e=fa(b,d,f);if(typeof c=="undefined"||c===null)c=0;if(m.afnFiltering.length!==0)c=1;if(b.length<=0){a.aiDisplay.splice(0,a.aiDisplay.length);a.aiDisplay=a.aiDisplayMaster.slice()}else if(a.aiDisplay.length==a.aiDisplayMaster.length||a.oPreviousSearch.sSearch.length>b.length||c==1||b.indexOf(a.oPreviousSearch.sSearch)!==0){a.aiDisplay.splice(0,a.aiDisplay.length);Q(a,1);for(c=0;c<a.aiDisplayMaster.length;c++)e.test(a.asDataSearch[c])&&a.aiDisplay.push(a.aiDisplayMaster[c])}else{var i= +0;for(c=0;c<a.asDataSearch.length;c++)if(!e.test(a.asDataSearch[c])){a.aiDisplay.splice(c-i,1);i++}}a.oPreviousSearch.sSearch=b;a.oPreviousSearch.bRegex=d;a.oPreviousSearch.bSmart=f}function Q(a,b){a.asDataSearch.splice(0,a.asDataSearch.length);var c=p.createElement("div");b=typeof b!="undefined"&&b==1?a.aiDisplayMaster:a.aiDisplay;for(var d=0,f=b.length;d<f;d++){a.asDataSearch[d]="";for(var e=0,i=a.aoColumns.length;e<i;e++)if(a.aoColumns[e].bSearchable)a.asDataSearch[d]+=ga(a.aoData[b[d]]._aData[e], +a.aoColumns[e].sType)+" ";if(a.asDataSearch[d].indexOf("&")!==-1){c.innerHTML=a.asDataSearch[d];a.asDataSearch[d]=c.textContent?c.textContent:c.innerText}}}function fa(a,b,c){if(c){a=b?a.split(" "):ha(a).split(" ");a="^(?=.*?"+a.join(")(?=.*?")+").*$";return new RegExp(a,"i")}else{a=b?a:ha(a);return new RegExp(a,"i")}}function ga(a,b){if(typeof m.ofnSearch[b]=="function")return m.ofnSearch[b](a);else if(b=="html")return a.replace(/\n/g," ").replace(/<.*?>/g,"");else if(typeof a=="string")return a.replace(/\n/g, +" ");return a}function O(a,b){var c=[],d=m.oSort,f=a.aoData,e,i,h,k;if(!a.oFeatures.bServerSide&&(a.aaSorting.length!==0||a.aaSortingFixed!==null)){c=a.aaSortingFixed!==null?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(h=0;h<c.length;h++){e=c[h][0];i=N(a,e);k=a.aoColumns[e].sSortDataType;if(typeof m.afnSortData[k]!="undefined"){var o=m.afnSortData[k](a,e,i);i=0;for(k=f.length;i<k;i++)f[i]._aData[e]=o[i]}}if(Y.runtime){var t=[],s=c.length;for(h=0;h<s;h++){e=a.aoColumns[c[h][0]].iDataSort; +t.push([e,a.aoColumns[e].sType+"-"+c[h][1]])}a.aiDisplayMaster.sort(function(H,I){for(var A,G=0;G<s;G++){A=d[t[G][1]](f[H]._aData[t[G][0]],f[I]._aData[t[G][0]]);if(A!==0)return A}return 0})}else{this.ClosureDataTables={fn:function(){},data:f,sort:m.oSort};k="this.ClosureDataTables.fn = function(a,b){var iTest, oSort=this.ClosureDataTables.sort, aoData=this.ClosureDataTables.data;";for(h=0;h<c.length-1;h++){e=a.aoColumns[c[h][0]].iDataSort;i=a.aoColumns[e].sType;k+="iTest = oSort['"+i+"-"+c[h][1]+ +"']( aoData[a]._aData["+e+"], aoData[b]._aData["+e+"] ); if ( iTest === 0 )"}if(c.length>0){e=a.aoColumns[c[c.length-1][0]].iDataSort;i=a.aoColumns[e].sType;k+="iTest = oSort['"+i+"-"+c[c.length-1][1]+"']( aoData[a]._aData["+e+"], aoData[b]._aData["+e+"] );if (iTest===0) return oSort['numeric-"+c[c.length-1][1]+"'](a, b); return iTest;}";eval(k);a.aiDisplayMaster.sort(this.ClosureDataTables.fn)}this.ClosureDataTables=undefined}}if(typeof b=="undefined"||b)W(a);a.bSorted=true;if(a.oFeatures.bFilter)P(a, +a.oPreviousSearch,1);else{a.aiDisplay=a.aiDisplayMaster.slice();a._iDisplayStart=0;F(a);D(a)}}function $(a,b,c,d){j(b).click(function(f){if(a.aoColumns[c].bSortable!==false){var e=function(){var i,h;if(f.shiftKey){for(var k=false,o=0;o<a.aaSorting.length;o++)if(a.aaSorting[o][0]==c){k=true;i=a.aaSorting[o][0];h=a.aaSorting[o][2]+1;if(typeof a.aoColumns[i].asSorting[h]=="undefined")a.aaSorting.splice(o,1);else{a.aaSorting[o][1]=a.aoColumns[i].asSorting[h];a.aaSorting[o][2]=h}break}k===false&&a.aaSorting.push([c, +a.aoColumns[c].asSorting[0],0])}else if(a.aaSorting.length==1&&a.aaSorting[0][0]==c){i=a.aaSorting[0][0];h=a.aaSorting[0][2]+1;if(typeof a.aoColumns[i].asSorting[h]=="undefined")h=0;a.aaSorting[0][1]=a.aoColumns[i].asSorting[h];a.aaSorting[0][2]=h}else{a.aaSorting.splice(0,a.aaSorting.length);a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0])}O(a)};if(a.oFeatures.bProcessing){K(a,true);setTimeout(function(){e();a.oFeatures.bServerSide||K(a,false)},0)}else e();typeof d=="function"&&d(a)}})}function W(a){var b, +c,d,f,e,i=a.aoColumns.length,h=a.oClasses;for(b=0;b<i;b++)a.aoColumns[b].bSortable&&j(a.aoColumns[b].nTh).removeClass(h.sSortAsc+" "+h.sSortDesc+" "+a.aoColumns[b].sSortingClass);f=a.aaSortingFixed!==null?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(b=0;b<a.aoColumns.length;b++)if(a.aoColumns[b].bSortable){e=a.aoColumns[b].sSortingClass;d=-1;for(c=0;c<f.length;c++)if(f[c][0]==b){e=f[c][1]=="asc"?h.sSortAsc:h.sSortDesc;d=c;break}j(a.aoColumns[b].nTh).addClass(e);if(a.bJUI){c=j("span", +a.aoColumns[b].nTh);c.removeClass(h.sSortJUIAsc+" "+h.sSortJUIDesc+" "+h.sSortJUI+" "+h.sSortJUIAscAllowed+" "+h.sSortJUIDescAllowed);c.addClass(d==-1?a.aoColumns[b].sSortingClassJUI:f[d][1]=="asc"?h.sSortJUIAsc:h.sSortJUIDesc)}}else j(a.aoColumns[b].nTh).addClass(a.aoColumns[b].sSortingClass);e=h.sSortColumn;if(a.oFeatures.bSort&&a.oFeatures.bSortClasses){d=X(a);if(d.length>=i)for(b=0;b<i;b++)if(d[b].className.indexOf(e+"1")!=-1){c=0;for(a=d.length/i;c<a;c++)d[i*c+b].className=d[i*c+b].className.replace(" "+ +e+"1","")}else if(d[b].className.indexOf(e+"2")!=-1){c=0;for(a=d.length/i;c<a;c++)d[i*c+b].className=d[i*c+b].className.replace(" "+e+"2","")}else if(d[b].className.indexOf(e+"3")!=-1){c=0;for(a=d.length/i;c<a;c++)d[i*c+b].className=d[i*c+b].className.replace(" "+e+"3","")}h=1;var k;for(b=0;b<f.length;b++){k=parseInt(f[b][0],10);c=0;for(a=d.length/i;c<a;c++)d[i*c+k].className+=" "+e+h;h<3&&h++}}}function wa(a){var b=p.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;m.oPagination[a.sPaginationType].fnInit(a, +b,function(c){F(c);D(c)});typeof a.aanFeatures.p=="undefined"&&a.aoDrawCallback.push({fn:function(c){m.oPagination[c.sPaginationType].fnUpdate(c,function(d){F(d);D(d)})},sName:"pagination"});return b}function Ba(a,b){var c=a._iDisplayStart;if(b=="first")a._iDisplayStart=0;else if(b=="previous"){a._iDisplayStart=a._iDisplayLength>=0?a._iDisplayStart-a._iDisplayLength:0;if(a._iDisplayStart<0)a._iDisplayStart=0}else if(b=="next")if(a._iDisplayLength>=0){if(a._iDisplayStart+a._iDisplayLength<a.fnRecordsDisplay())a._iDisplayStart+= +a._iDisplayLength}else a._iDisplayStart=0;else if(b=="last")if(a._iDisplayLength>=0){b=parseInt((a.fnRecordsDisplay()-1)/a._iDisplayLength,10)+1;a._iDisplayStart=(b-1)*a._iDisplayLength}else a._iDisplayStart=0;else J(a,0,"Unknown paging action: "+b);return c!=a._iDisplayStart}function va(a){var b=p.createElement("div");b.className=a.oClasses.sInfo;if(typeof a.aanFeatures.i=="undefined"){a.aoDrawCallback.push({fn:Ca,sName:"information"});a.sTableId!==""&&b.setAttribute("id",a.sTableId+"_info")}return b} +function Ca(a){if(!(!a.oFeatures.bInfo||a.aanFeatures.i.length===0)){var b=j(a.aanFeatures.i[0]),c=a.fnFormatNumber(a.fnRecordsTotal()),d=a.fnFormatNumber(a._iDisplayStart+1),f=a.fnFormatNumber(a.fnDisplayEnd()),e=a.fnFormatNumber(a.fnRecordsDisplay());if(a.fnRecordsDisplay()===0&&a.fnRecordsDisplay()==a.fnRecordsTotal())b.html(a.oLanguage.sInfoEmpty+a.oLanguage.sInfoPostFix);else if(a.fnRecordsDisplay()===0)b.html(a.oLanguage.sInfoEmpty+" "+a.oLanguage.sInfoFiltered.replace("_MAX_",c)+a.oLanguage.sInfoPostFix); +else a.fnRecordsDisplay()==a.fnRecordsTotal()?b.html(a.oLanguage.sInfo.replace("_START_",d).replace("_END_",f).replace("_TOTAL_",e)+a.oLanguage.sInfoPostFix):b.html(a.oLanguage.sInfo.replace("_START_",d).replace("_END_",f).replace("_TOTAL_",e)+" "+a.oLanguage.sInfoFiltered.replace("_MAX_",a.fnFormatNumber(a.fnRecordsTotal()))+a.oLanguage.sInfoPostFix);a=a.aanFeatures.i;if(a.length>1){b=b.html();c=1;for(d=a.length;c<d;c++)j(a[c]).html(b)}}}function ra(a){var b='<select size="1" '+(a.sTableId===""? +"":'name="'+a.sTableId+'_length"')+">",c,d;if(a.aLengthMenu.length==2&&typeof a.aLengthMenu[0]=="object"&&typeof a.aLengthMenu[1]=="object"){c=0;for(d=a.aLengthMenu[0].length;c<d;c++)b+='<option value="'+a.aLengthMenu[0][c]+'">'+a.aLengthMenu[1][c]+"</option>"}else{c=0;for(d=a.aLengthMenu.length;c<d;c++)b+='<option value="'+a.aLengthMenu[c]+'">'+a.aLengthMenu[c]+"</option>"}b+="</select>";var f=p.createElement("div");a.sTableId!==""&&typeof a.aanFeatures.l=="undefined"&&f.setAttribute("id",a.sTableId+ +"_length");f.className=a.oClasses.sLength;f.innerHTML=a.oLanguage.sLengthMenu.replace("_MENU_",b);j('select option[value="'+a._iDisplayLength+'"]',f).attr("selected",true);j("select",f).change(function(){var e=j(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;c<d;c++)i[c]!=this.parentNode&&j("select",i[c]).val(e);a._iDisplayLength=parseInt(e,10);F(a);if(a.fnDisplayEnd()==a.fnRecordsDisplay()){a._iDisplayStart=a.fnDisplayEnd()-a._iDisplayLength;if(a._iDisplayStart<0)a._iDisplayStart=0}if(a._iDisplayLength== +-1)a._iDisplayStart=0;D(a)});return f}function ta(a){var b=p.createElement("div");a.sTableId!==""&&typeof a.aanFeatures.r=="undefined"&&b.setAttribute("id",a.sTableId+"_processing");b.innerHTML=a.oLanguage.sProcessing;b.className=a.oClasses.sProcessing;a.nTable.parentNode.insertBefore(b,a.nTable);return b}function K(a,b){if(a.oFeatures.bProcessing){a=a.aanFeatures.r;for(var c=0,d=a.length;c<d;c++)a[c].style.visibility=b?"visible":"hidden"}}function da(a,b){for(var c=-1,d=0;d<a.aoColumns.length;d++){a.aoColumns[d].bVisible=== +true&&c++;if(c==b)return d}return null}function N(a,b){for(var c=-1,d=0;d<a.aoColumns.length;d++){a.aoColumns[d].bVisible===true&&c++;if(d==b)return a.aoColumns[d].bVisible===true?c:null}return null}function R(a,b){var c,d;c=a._iDisplayStart;for(d=a._iDisplayEnd;c<d;c++)if(a.aoData[a.aiDisplay[c]].nTr==b)return a.aiDisplay[c];c=0;for(d=a.aoData.length;c<d;c++)if(a.aoData[c].nTr==b)return c;return null}function T(a){for(var b=0,c=0;c<a.aoColumns.length;c++)a.aoColumns[c].bVisible===true&&b++;return b} +function F(a){a._iDisplayEnd=a.oFeatures.bPaginate===false?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength>a.aiDisplay.length||a._iDisplayLength==-1?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a,b){if(!a||a===null||a==="")return 0;if(typeof b=="undefined")b=p.getElementsByTagName("body")[0];var c=p.createElement("div");c.style.width=a;b.appendChild(c);a=c.offsetWidth;b.removeChild(c);return a}function ea(a){var b=0,c,d=0,f=a.aoColumns.length,e,i=j("th",a.nTHead);for(e= +0;e<f;e++)if(a.aoColumns[e].bVisible){d++;if(a.aoColumns[e].sWidth!==null){c=Da(a.aoColumns[e].sWidthOrig,a.nTable.parentNode);if(c!==null)a.aoColumns[e].sWidth=v(c);b++}}if(f==i.length&&b===0&&d==f){ia(a,a.nTable);for(e=0;e<a.aoColumns.length;e++){c=j(i[e]).width();if(c!==null)a.aoColumns[e].sWidth=v(c)}}else{b=a.nTable.cloneNode(false);e=p.createElement("tbody");c=p.createElement("tr");b.removeAttribute("id");b.appendChild(a.nTHead.cloneNode(true));if(a.nTFoot!==null){b.appendChild(a.nTFoot.cloneNode(true)); +M(function(h){h.style.width=""},b.getElementsByTagName("tr"))}b.appendChild(e);e.appendChild(c);e=j("thead th",b);if(e.length===0)e=j("tbody tr:eq(0)>td",b);e.each(function(h){this.style.width="";h=da(a,h);if(h!==null&&a.aoColumns[h].sWidthOrig!=="")this.style.width=a.aoColumns[h].sWidthOrig});for(e=0;e<f;e++)if(a.aoColumns[e].bVisible){d=Ea(a,e);if(d!==null){d=d.cloneNode(true);c.appendChild(d)}}e=a.nTable.parentNode;e.appendChild(b);if(a.oScroll.sX!==""&&a.oScroll.sXInner!=="")b.style.width=v(a.oScroll.sXInner); +else if(a.oScroll.sX!==""){b.style.width="";if(j(b).width()<e.offsetWidth)b.style.width=v(e.offsetWidth)}else b.style.width=v(e.offsetWidth);b.style.visibility="hidden";ia(a,b);f=j("tbody tr:eq(0)>td",b);if(f.length===0)f=j("thead tr:eq(0)>th",b);for(e=c=0;e<a.aoColumns.length;e++)if(a.aoColumns[e].bVisible){d=j(f[c]).width();if(d!==null&&d>0)a.aoColumns[e].sWidth=v(d);c++}a.nTable.style.width=v(j(b).outerWidth());b.parentNode.removeChild(b)}}function ia(a,b){if(a.oScroll.sX===""&&a.oScroll.sY!== +""){j(b).width();b.style.width=v(j(b).outerWidth()-a.oScroll.iBarWidth)}else if(a.oScroll.sX!=="")b.style.width=v(j(b).outerWidth())}function Ea(a,b,c){if(typeof c=="undefined"||c){c=Fa(a,b);b=N(a,b);if(c<0)return null;return a.aoData[c].nTr.getElementsByTagName("td")[b]}var d=-1,f,e;c=-1;var i=p.createElement("div");i.style.visibility="hidden";i.style.position="absolute";p.body.appendChild(i);f=0;for(e=a.aoData.length;f<e;f++){i.innerHTML=a.aoData[f]._aData[b];if(i.offsetWidth>d){d=i.offsetWidth; +c=f}}p.body.removeChild(i);if(c>=0){b=N(a,b);if(a=a.aoData[c].nTr.getElementsByTagName("td")[b])return a}return null}function Fa(a,b){for(var c=0,d=-1,f=0;f<a.aoData.length;f++){var e=a.aoData[f]._aData[b];if(e.length>c){c=e.length;d=f}}return d}function v(a){if(a===null)return"0px";if(typeof a=="number")return a+"px";if(a.indexOf("em")!=-1||a.indexOf("%")!=-1||a.indexOf("ex")!=-1||a.indexOf("px")!=-1)return a;return a+"px"}function La(a,b){if(a.length!=b.length)return 1;for(var c=0;c<a.length;c++)if(a[c]!= +b[c])return 2;return 0}function Z(a){for(var b=m.aTypes,c=b.length,d=0;d<c;d++){var f=b[d](a);if(f!==null)return f}return"string"}function B(a){for(var b=0;b<E.length;b++)if(E[b].nTable==a)return E[b];return null}function V(a){for(var b=[],c=a.aoData.length,d=0;d<c;d++)b.push(a.aoData[d]._aData);return b}function S(a){for(var b=[],c=a.aoData.length,d=0;d<c;d++)b.push(a.aoData[d].nTr);return b}function X(a){var b=S(a),c=[],d,f=[],e,i,h,k;e=0;for(i=b.length;e<i;e++){c=[];h=0;for(k=b[e].childNodes.length;h< +k;h++){d=b[e].childNodes[h];d.nodeName.toUpperCase()=="TD"&&c.push(d)}h=d=0;for(k=a.aoColumns.length;h<k;h++)if(a.aoColumns[h].bVisible)f.push(c[h-d]);else{f.push(a.aoData[e]._anHidden[h]);d++}}return f}function ha(a){return a.replace(new RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^)","g"),"\\$1")}function ja(a,b){for(var c=-1,d=0,f=a.length;d<f;d++)if(a[d]==b)c=d;else a[d]>b&&a[d]--;c!=-1&&a.splice(c,1)}function qa(a,b){b=b.split(",");for(var c=[],d=0,f=a.aoColumns.length;d< +f;d++)for(var e=0;e<f;e++)if(a.aoColumns[d].sName==b[e]){c.push(e);break}return c}function aa(a){for(var b="",c=0,d=a.aoColumns.length;c<d;c++)b+=a.aoColumns[c].sName+",";if(b.length==d)return"";return b.slice(0,-1)}function J(a,b,c){a=a.sTableId===""?"DataTables warning: "+c:"DataTables warning (table id = '"+a.sTableId+"'): "+c;if(b===0)if(m.sErrMode=="alert")alert(a);else throw a;else typeof console!="undefined"&&typeof console.log!="undefined"&&console.log(a)}function ba(a){a.aoData.length=0; +a.aiDisplayMaster.length=0;a.aiDisplay.length=0;F(a)}function Ga(a){if(a.oFeatures.bStateSave){var b,c="{";c+='"iCreate": '+(new Date).getTime()+",";c+='"iStart": '+a._iDisplayStart+",";c+='"iEnd": '+a._iDisplayEnd+",";c+='"iLength": '+a._iDisplayLength+",";c+='"sFilter": "'+a.oPreviousSearch.sSearch.replace('"','\\"')+'",';c+='"sFilterEsc": '+!a.oPreviousSearch.bRegex+",";c+='"aaSorting": [ ';for(b=0;b<a.aaSorting.length;b++)c+="["+a.aaSorting[b][0]+",'"+a.aaSorting[b][1]+"'],";c=c.substring(0,c.length- +1);c+="],";c+='"aaSearchCols": [ ';for(b=0;b<a.aoPreSearchCols.length;b++)c+="['"+a.aoPreSearchCols[b].sSearch.replace("'","'")+"',"+!a.aoPreSearchCols[b].bRegex+"],";c=c.substring(0,c.length-1);c+="],";c+='"abVisCols": [ ';for(b=0;b<a.aoColumns.length;b++)c+=a.aoColumns[b].bVisible+",";c=c.substring(0,c.length-1);c+="]";c+="}";Ha(a.sCookiePrefix+a.sInstance,c,a.iCookieDuration,a.sCookiePrefix)}}function Ia(a,b){if(a.oFeatures.bStateSave){var c,d=ka(a.sCookiePrefix+a.sInstance);if(d!==null&&d!==""){try{c= +typeof JSON=="object"&&typeof JSON.parse=="function"?JSON.parse(d.replace(/'/g,'"')):eval("("+d+")")}catch(f){return}a._iDisplayStart=c.iStart;a.iInitDisplayStart=c.iStart;a._iDisplayEnd=c.iEnd;a._iDisplayLength=c.iLength;a.oPreviousSearch.sSearch=c.sFilter;a.aaSorting=c.aaSorting.slice();a.saved_aaSorting=c.aaSorting.slice();if(typeof c.sFilterEsc!="undefined")a.oPreviousSearch.bRegex=!c.sFilterEsc;if(typeof c.aaSearchCols!="undefined")for(d=0;d<c.aaSearchCols.length;d++)a.aoPreSearchCols[d]={sSearch:c.aaSearchCols[d][0], +bRegex:!c.aaSearchCols[d][1]};if(typeof c.abVisCols!="undefined"){b.saved_aoColumns=[];for(d=0;d<c.abVisCols.length;d++){b.saved_aoColumns[d]={};b.saved_aoColumns[d].bVisible=c.abVisCols[d]}}}}}function Ha(a,b,c,d){var f=new Date;f.setTime(f.getTime()+c*1E3);c=Y.location.pathname.split("/");var e=a+"_"+c.pop().replace(/[\/:]/g,"").toLowerCase();b=e+"="+encodeURIComponent(b)+"; expires="+f.toGMTString()+"; path="+c.join("/")+"/";f="";a=9999999999999;var i;if((ka(e)!==null?p.cookie.length:b.length+ +p.cookie.length)+10>4096){e=p.cookie.split(";");for(var h=0,k=e.length;h<k;h++)if(e[h].indexOf(d)!=-1){var o=e[h].split("=");try{i=eval("("+decodeURIComponent(o[1])+")")}catch(t){continue}if(typeof i.iCreate!="undefined"&&i.iCreate<a){f=o[0];a=i.iCreate}}if(f!=="")p.cookie=f+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+c.join("/")+"/"}p.cookie=b}function ka(a){var b=Y.location.pathname.split("/");a=a+"_"+b[b.length-1].replace(/[\/:]/g,"").toLowerCase()+"=";b=p.cookie.split(";");for(var c=0;c< +b.length;c++){for(var d=b[c];d.charAt(0)==" ";)d=d.substring(1,d.length);if(d.indexOf(a)===0)return decodeURIComponent(d.substring(a.length,d.length))}return null}function ca(a){a=a.getElementsByTagName("tr");if(a.length==1)return a[0].getElementsByTagName("th");var b=[],c=[],d,f,e,i,h,k,o=function(G,Ma,la){for(;typeof G[Ma][la]!="undefined";)la++;return la},t=function(G){if(typeof b[G]=="undefined")b[G]=[]};d=0;for(i=a.length;d<i;d++){t(d);var s=0,H=[];f=0;for(h=a[d].childNodes.length;f<h;f++)if(a[d].childNodes[f].nodeName.toUpperCase()== +"TD"||a[d].childNodes[f].nodeName.toUpperCase()=="TH")H.push(a[d].childNodes[f]);f=0;for(h=H.length;f<h;f++){var I=H[f].getAttribute("colspan")*1,A=H[f].getAttribute("rowspan")*1;if(!I||I===0||I===1){k=o(b,d,s);b[d][k]=H[f].nodeName.toUpperCase()=="TD"?4:H[f];if(A||A===0||A===1)for(e=1;e<A;e++){t(d+e);b[d+e][k]=2}s++}else{k=o(b,d,s);for(e=0;e<I;e++)b[d][k+e]=3;s+=I}}}d=0;for(i=b[0].length;d<i;d++){f=0;for(h=b.length;f<h;f++)typeof b[f][d]=="object"&&c.push(b[f][d])}return c}function Ja(){var a=p.createElement("p"), +b=a.style;b.width="100%";b.height="200px";var c=p.createElement("div");b=c.style;b.position="absolute";b.top="0px";b.left="0px";b.visibility="hidden";b.width="200px";b.height="150px";b.overflow="hidden";c.appendChild(a);p.body.appendChild(c);b=a.offsetWidth;c.style.overflow="scroll";a=a.offsetWidth;if(b==a)a=c.clientWidth;p.body.removeChild(c);return b-a}function M(a,b,c){for(var d=0,f=b.length;d<f;d++)for(var e=0,i=b[d].childNodes.length;e<i;e++)if(b[d].childNodes[e].nodeType==1)typeof c!="undefined"? +a(b[d].childNodes[e],c[d].childNodes[e]):a(b[d].childNodes[e])}function n(a,b,c,d){if(typeof d=="undefined")d=c;if(typeof b[c]!="undefined")a[d]=b[c]}this.oApi={};this.fnDraw=function(a){var b=B(this[m.iApiIndex]);if(typeof a!="undefined"&&a===false){F(b);D(b)}else L(b)};this.fnFilter=function(a,b,c,d,f){var e=B(this[m.iApiIndex]);if(e.oFeatures.bFilter){if(typeof c=="undefined")c=false;if(typeof d=="undefined")d=true;if(typeof f=="undefined")f=true;if(typeof b=="undefined"||b===null){P(e,{sSearch:a, +bRegex:c,bSmart:d},1);if(f&&typeof e.aanFeatures.f!="undefined"){b=e.aanFeatures.f;c=0;for(d=b.length;c<d;c++)j("input",b[c]).val(a)}}else{e.aoPreSearchCols[b].sSearch=a;e.aoPreSearchCols[b].bRegex=c;e.aoPreSearchCols[b].bSmart=d;P(e,e.oPreviousSearch,1)}}};this.fnSettings=function(){return B(this[m.iApiIndex])};this.fnVersionCheck=m.fnVersionCheck;this.fnSort=function(a){var b=B(this[m.iApiIndex]);b.aaSorting=a;O(b)};this.fnSortListener=function(a,b,c){$(B(this[m.iApiIndex]),a,b,c)};this.fnAddData= +function(a,b){if(a.length===0)return[];var c=[],d,f=B(this[m.iApiIndex]);if(typeof a[0]=="object")for(var e=0;e<a.length;e++){d=w(f,a[e]);if(d==-1)return c;c.push(d)}else{d=w(f,a);if(d==-1)return c;c.push(d)}f.aiDisplay=f.aiDisplayMaster.slice();Q(f,1);if(typeof b=="undefined"||b)L(f);return c};this.fnDeleteRow=function(a,b,c){var d=B(this[m.iApiIndex]);a=typeof a=="object"?R(d,a):a;var f=d.aoData.splice(a,1);ja(d.aiDisplayMaster,a);ja(d.aiDisplay,a);Q(d,1);typeof b=="function"&&b.call(this,d,f); +if(d._iDisplayStart>=d.aiDisplay.length){d._iDisplayStart-=d._iDisplayLength;if(d._iDisplayStart<0)d._iDisplayStart=0}if(typeof c=="undefined"||c){F(d);D(d)}return f};this.fnClearTable=function(a){var b=B(this[m.iApiIndex]);ba(b);if(typeof a=="undefined"||a)D(b)};this.fnOpen=function(a,b,c){var d=B(this[m.iApiIndex]);this.fnClose(a);var f=p.createElement("tr"),e=p.createElement("td");f.appendChild(e);e.className=c;e.colSpan=T(d);e.innerHTML=b;b=j("tr",d.nTBody);j.inArray(a,b)!=-1&&j(f).insertAfter(a); +d.aoOpenRows.push({nTr:f,nParent:a});return f};this.fnClose=function(a){for(var b=B(this[m.iApiIndex]),c=0;c<b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a){(a=b.aoOpenRows[c].nTr.parentNode)&&a.removeChild(b.aoOpenRows[c].nTr);b.aoOpenRows.splice(c,1);return 0}return 1};this.fnGetData=function(a){var b=B(this[m.iApiIndex]);if(typeof a!="undefined"){a=typeof a=="object"?R(b,a):a;return b.aoData[a]._aData}return V(b)};this.fnGetNodes=function(a){var b=B(this[m.iApiIndex]);if(typeof a!="undefined")return b.aoData[a].nTr; +return S(b)};this.fnGetPosition=function(a){var b=B(this[m.iApiIndex]);if(a.nodeName.toUpperCase()=="TR")return R(b,a);else if(a.nodeName.toUpperCase()=="TD")for(var c=R(b,a.parentNode),d=0,f=0;f<b.aoColumns.length;f++)if(b.aoColumns[f].bVisible){if(b.aoData[c].nTr.getElementsByTagName("td")[f-d]==a)return[c,f-d,f]}else d++;return null};this.fnUpdate=function(a,b,c,d,f){var e=B(this[m.iApiIndex]),i=typeof b=="object"?R(e,b):b;if(typeof a!="object"){b=a;e.aoData[i]._aData[c]=b;if(e.aoColumns[c].fnRender!== +null){b=e.aoColumns[c].fnRender({iDataRow:i,iDataColumn:c,aData:e.aoData[i]._aData,oSettings:e});if(e.aoColumns[c].bUseRendered)e.aoData[i]._aData[c]=b}c=N(e,c);if(c!==null)e.aoData[i].nTr.getElementsByTagName("td")[c].innerHTML=b}else{if(a.length!=e.aoColumns.length){J(e,0,"An array passed to fnUpdate must have the same number of columns as the table in question - in this case "+e.aoColumns.length);return 1}for(var h=0;h<a.length;h++){b=a[h];e.aoData[i]._aData[h]=b;if(e.aoColumns[h].fnRender!==null){b= +e.aoColumns[h].fnRender({iDataRow:i,iDataColumn:h,aData:e.aoData[i]._aData,oSettings:e});if(e.aoColumns[h].bUseRendered)e.aoData[i]._aData[h]=b}c=N(e,h);if(c!==null)e.aoData[i].nTr.getElementsByTagName("td")[c].innerHTML=b}}if(typeof f=="undefined"||f){Q(e,1);U(e)}if(typeof d=="undefined"||d)L(e);return 0};this.fnSetColumnVis=function(a,b){var c=B(this[m.iApiIndex]),d,f;f=c.aoColumns.length;var e,i;if(c.aoColumns[a].bVisible!=b){e=j(">tr",c.nTHead)[0];var h=j(">tr",c.nTFoot)[0],k=[],o=[];for(d=0;d< +f;d++){k.push(c.aoColumns[d].nTh);o.push(c.aoColumns[d].nTf)}if(b){for(d=b=0;d<a;d++)c.aoColumns[d].bVisible&&b++;if(b>=T(c)){e.appendChild(k[a]);h&&h.appendChild(o[a]);d=0;for(f=c.aoData.length;d<f;d++){e=c.aoData[d]._anHidden[a];c.aoData[d].nTr.appendChild(e)}}else{for(d=a;d<f;d++){i=N(c,d);if(i!==null)break}e.insertBefore(k[a],e.getElementsByTagName("th")[i]);h&&h.insertBefore(o[a],h.getElementsByTagName("th")[i]);X(c);d=0;for(f=c.aoData.length;d<f;d++){e=c.aoData[d]._anHidden[a];c.aoData[d].nTr.insertBefore(e, +j(">td:eq("+i+")",c.aoData[d].nTr)[0])}}c.aoColumns[a].bVisible=true}else{e.removeChild(k[a]);h&&h.removeChild(o[a]);i=X(c);d=0;for(f=c.aoData.length;d<f;d++){e=i[d*c.aoColumns.length+a*1];c.aoData[d]._anHidden[a]=e;e.parentNode.removeChild(e)}c.aoColumns[a].bVisible=false}d=0;for(f=c.aoOpenRows.length;d<f;d++)c.aoOpenRows[d].nTr.colSpan=T(c);U(c);D(c)}};this.fnPageChange=function(a,b){var c=B(this[m.iApiIndex]);Ba(c,a);F(c);if(typeof b=="undefined"||b)D(c)};this.fnDestroy=function(){var a=B(this[m.iApiIndex]), +b=a.nTableWrapper.parentNode,c=a.nTBody,d;a.nTable.parentNode.removeChild(a.nTable);j(a.nTableWrapper).remove();a.aaSorting=[];a.aaSortingFixed=[];W(a);j(S(a)).removeClass(a.asStripClasses.join(" "));if(a.bJUI){j("th",a.nTHead).removeClass([m.oStdClasses.sSortable,m.oJUIClasses.sSortableAsc,m.oJUIClasses.sSortableDesc,m.oJUIClasses.sSortableNone].join(" "));j("th span",a.nTHead).remove()}else j("th",a.nTHead).removeClass([m.oStdClasses.sSortable,m.oStdClasses.sSortableAsc,m.oStdClasses.sSortableDesc, +m.oStdClasses.sSortableNone].join(" "));b.appendChild(a.nTable);b=0;for(d=a.aoData.length;b<d;b++)c.appendChild(a.aoData[b].nTr);j(">tr:even",c).addClass(a.asDestoryStrips[0]);j(">tr:odd",c).addClass(a.asDestoryStrips[1]);b=0;for(d=E.length;b<d;b++)E[b]==a&&E.splice(b,1)};this.fnAdjustColumnSizing=function(a){U(B(this[m.iApiIndex]));if(typeof a=="undefined"||a)this.fnDraw(false)};for(var ma in m.oApi)if(ma)this[ma]=q(ma);this.oApi._fnExternApiFunc=q;this.oApi._fnInitalise=r;this.oApi._fnLanguageProcess= +u;this.oApi._fnAddColumn=y;this.oApi._fnColumnOptions=C;this.oApi._fnAddData=w;this.oApi._fnGatherData=x;this.oApi._fnDrawHead=z;this.oApi._fnDraw=D;this.oApi._fnReDraw=L;this.oApi._fnAjaxUpdate=oa;this.oApi._fnAjaxUpdateDraw=pa;this.oApi._fnAddOptionsHtml=na;this.oApi._fnFeatureHtmlTable=ua;this.oApi._fnScrollDraw=xa;this.oApi._fnAjustColumnSizing=U;this.oApi._fnFeatureHtmlFilter=sa;this.oApi._fnFilterComplete=P;this.oApi._fnFilterCustom=Aa;this.oApi._fnFilterColumn=za;this.oApi._fnFilter=ya;this.oApi._fnBuildSearchArray= +Q;this.oApi._fnFilterCreateSearch=fa;this.oApi._fnDataToSearch=ga;this.oApi._fnSort=O;this.oApi._fnSortAttachListener=$;this.oApi._fnSortingClasses=W;this.oApi._fnFeatureHtmlPaginate=wa;this.oApi._fnPageChange=Ba;this.oApi._fnFeatureHtmlInfo=va;this.oApi._fnUpdateInfo=Ca;this.oApi._fnFeatureHtmlLength=ra;this.oApi._fnFeatureHtmlProcessing=ta;this.oApi._fnProcessingDisplay=K;this.oApi._fnVisibleToColumnIndex=da;this.oApi._fnColumnIndexToVisible=N;this.oApi._fnNodeToDataIndex=R;this.oApi._fnVisbleColumns= +T;this.oApi._fnCalculateEnd=F;this.oApi._fnConvertToWidth=Da;this.oApi._fnCalculateColumnWidths=ea;this.oApi._fnScrollingWidthAdjust=ia;this.oApi._fnGetWidestNode=Ea;this.oApi._fnGetMaxLenString=Fa;this.oApi._fnStringToCss=v;this.oApi._fnArrayCmp=La;this.oApi._fnDetectType=Z;this.oApi._fnSettingsFromNode=B;this.oApi._fnGetDataMaster=V;this.oApi._fnGetTrNodes=S;this.oApi._fnGetTdNodes=X;this.oApi._fnEscapeRegex=ha;this.oApi._fnDeleteIndex=ja;this.oApi._fnReOrderIndex=qa;this.oApi._fnColumnOrdering= +aa;this.oApi._fnLog=J;this.oApi._fnClearTable=ba;this.oApi._fnSaveState=Ga;this.oApi._fnLoadState=Ia;this.oApi._fnCreateCookie=Ha;this.oApi._fnReadCookie=ka;this.oApi._fnGetUniqueThs=ca;this.oApi._fnScrollBarWidth=Ja;this.oApi._fnApplyToChildren=M;this.oApi._fnMap=n;var Ka=this;return this.each(function(){var a=0,b,c,d,f;a=0;for(b=E.length;a<b;a++){if(E[a].nTable==this)if(typeof g=="undefined"||typeof g.bRetrieve!="undefined"&&g.bRetrieve===true)return E[a].oInstance;else if(typeof g.bDestroy!="undefined"&& +g.bDestroy===true){E[a].oInstance.fnDestroy();break}else{J(E[a],0,"Cannot reinitialise DataTable.\n\nTo retrieve the DataTables object for this table, please pass either no arguments to the dataTable() function, or set bRetrieve to true. Alternatively, to destory the old table and create a new one, set bDestroy to true (note that a lot of changes to the configuration can be made through the API which is usually much faster).");return}if(E[a].sTableId!==""&&E[a].sTableId==this.getAttribute("id")){E.splice(a, +1);break}}var e=new l;E.push(e);var i=false,h=false;a=this.getAttribute("id");if(a!==null){e.sTableId=a;e.sInstance=a}else e.sInstance=m._oExternConfig.iNextUnique++;e.oInstance=Ka;e.nTable=this;e.oApi=Ka.oApi;if(typeof g!="undefined"&&g!==null){e.oInit=g;n(e.oFeatures,g,"bPaginate");n(e.oFeatures,g,"bLengthChange");n(e.oFeatures,g,"bFilter");n(e.oFeatures,g,"bSort");n(e.oFeatures,g,"bInfo");n(e.oFeatures,g,"bProcessing");n(e.oFeatures,g,"bAutoWidth");n(e.oFeatures,g,"bSortClasses");n(e.oFeatures, +g,"bServerSide");n(e.oScroll,g,"sScrollX","sX");n(e.oScroll,g,"sScrollXInner","sXInner");n(e.oScroll,g,"sScrollY","sY");n(e.oScroll,g,"bScrollCollapse","bCollapse");n(e,g,"asStripClasses");n(e,g,"fnRowCallback");n(e,g,"fnHeaderCallback");n(e,g,"fnFooterCallback");n(e,g,"fnInitComplete");n(e,g,"fnServerData");n(e,g,"fnFormatNumber");n(e,g,"aaSorting");n(e,g,"aaSortingFixed");n(e,g,"aLengthMenu");n(e,g,"sPaginationType");n(e,g,"sAjaxSource");n(e,g,"iCookieDuration");n(e,g,"sCookiePrefix");n(e,g,"sDom"); +n(e,g,"oSearch","oPreviousSearch");n(e,g,"aoSearchCols","aoPreSearchCols");n(e,g,"iDisplayLength","_iDisplayLength");n(e,g,"bJQueryUI","bJUI");typeof g.fnDrawCallback=="function"&&e.aoDrawCallback.push({fn:g.fnDrawCallback,sName:"user"});e.oFeatures.bServerSide&&e.oFeatures.bSort&&e.oFeatures.bSortClasses&&e.aoDrawCallback.push({fn:W,sName:"server_side_sort_classes"});if(typeof g.bJQueryUI!="undefined"&&g.bJQueryUI){e.oClasses=m.oJUIClasses;if(typeof g.sDom=="undefined")e.sDom='<"H"lfr>t<"F"ip>'}if(e.oScroll.sX!== +""||e.oScroll.sY!=="")e.oScroll.iBarWidth=Ja();if(typeof g.iDisplayStart!="undefined"&&typeof e.iInitDisplayStart=="undefined"){e.iInitDisplayStart=g.iDisplayStart;e._iDisplayStart=g.iDisplayStart}if(typeof g.bStateSave!="undefined"){e.oFeatures.bStateSave=g.bStateSave;Ia(e,g);e.aoDrawCallback.push({fn:Ga,sName:"state_save"})}if(typeof g.aaData!="undefined")h=true;if(typeof g!="undefined"&&typeof g.aoData!="undefined")g.aoColumns=g.aoData;if(typeof g.oLanguage!="undefined")if(typeof g.oLanguage.sUrl!= +"undefined"&&g.oLanguage.sUrl!==""){e.oLanguage.sUrl=g.oLanguage.sUrl;j.getJSON(e.oLanguage.sUrl,null,function(o){u(e,o,true)});i=true}else u(e,g.oLanguage,false)}else g={};if(typeof g.asStripClasses=="undefined"){e.asStripClasses.push(e.oClasses.sStripOdd);e.asStripClasses.push(e.oClasses.sStripEven)}c=false;d=j("tbody>tr",this);a=0;for(b=e.asStripClasses.length;a<b;a++)if(d.filter(":lt(2)").hasClass(e.asStripClasses[a])){c=true;break}if(c){e.asDestoryStrips=["",""];if(j(d[0]).hasClass(e.oClasses.sStripOdd))e.asDestoryStrips[0]+= +e.oClasses.sStripOdd+" ";if(j(d[0]).hasClass(e.oClasses.sStripEven))e.asDestoryStrips[0]+=e.oClasses.sStripEven;if(j(d[1]).hasClass(e.oClasses.sStripOdd))e.asDestoryStrips[1]+=e.oClasses.sStripOdd+" ";if(j(d[1]).hasClass(e.oClasses.sStripEven))e.asDestoryStrips[1]+=e.oClasses.sStripEven;d.removeClass(e.asStripClasses.join(" "))}a=this.getElementsByTagName("thead");c=a.length===0?[]:ca(a[0]);d=typeof g.aoColumns!="undefined";a=0;for(b=d?g.aoColumns.length:c.length;a<b;a++){f=d?g.aoColumns[a]:null; +var k=c?c[a]:null;if(typeof g.saved_aoColumns!="undefined"&&g.saved_aoColumns.length==b){if(f===null)f={};f.bVisible=g.saved_aoColumns[a].bVisible}y(e,k)}if(typeof g.aoColumnDefs!="undefined")for(a=g.aoColumnDefs.length-1;a>=0;a--){k=g.aoColumnDefs[a].aTargets;c=0;for(d=k.length;c<d;c++)if(typeof k[c]=="number"&&k[c]>=0){for(;e.aoColumns.length<=k[c];)y(e);C(e,k[c],g.aoColumnDefs[a])}else if(typeof k[c]=="number"&&k[c]<0)C(e,e.aoColumns.length+k[c],g.aoColumnDefs[a]);else if(typeof k[c]=="string"){b= +0;for(f=e.aoColumns.length;b<f;b++)if(k[c]=="_all"||e.aoColumns[b].nTh.className.indexOf(k[c])!=-1)C(e,b,g.aoColumnDefs[a])}}if(typeof g.aoColumns!="undefined"){a=0;for(b=g.aoColumns.length;a<b;a++)C(e,a,g.aoColumns[a])}a=0;for(b=e.aaSorting.length;a<b;a++){f=e.aoColumns[e.aaSorting[a][0]];if(typeof e.aaSorting[a][2]=="undefined")e.aaSorting[a][2]=0;if(typeof g.aaSorting=="undefined"&&typeof e.saved_aaSorting=="undefined")e.aaSorting[a][1]=f.asSorting[0];c=0;for(d=f.asSorting.length;c<d;c++)if(e.aaSorting[a][1]== +f.asSorting[c]){e.aaSorting[a][2]=c;break}}this.getElementsByTagName("thead").length===0&&this.appendChild(p.createElement("thead"));this.getElementsByTagName("tbody").length===0&&this.appendChild(p.createElement("tbody"));e.nTHead=this.getElementsByTagName("thead")[0];e.nTBody=this.getElementsByTagName("tbody")[0];if(this.getElementsByTagName("tfoot").length>0)e.nTFoot=this.getElementsByTagName("tfoot")[0];if(h)for(a=0;a<g.aaData.length;a++)w(e,g.aaData[a]);else x(e);e.aiDisplay=e.aiDisplayMaster.slice(); +e.oFeatures.bAutoWidth&&ea(e);e.bInitialised=true;i===false&&r(e)})}})(jQuery,window,document); + +jQuery.fn.dataTableExt.oSort['percent-asc'] = function(a,b) { + var x = (a == "-") ? 0 : a.replace( /%/, "" ); + var y = (b == "-") ? 0 : b.replace( /%/, "" ); + x = parseFloat( x ); + y = parseFloat( y ); + return ((x < y) ? -1 : ((x > y) ? 1 : 0)); +}; + +jQuery.fn.dataTableExt.oSort['percent-desc'] = function(a,b) { + var x = (a == "-") ? 0 : a.replace( /%/, "" ); + var y = (b == "-") ? 0 : b.replace( /%/, "" ); + x = parseFloat( x ); + y = parseFloat( y ); + return ((x < y) ? 1 : ((x > y) ? -1 : 0)); +}; +/* + * timeago: a jQuery plugin, version: 0.9 (2010-06-21) + * @requires jQuery v1.2.3 or later + * + * Timeago is a jQuery plugin that makes it easy to support automatically + * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). + * + * For usage and examples, visit: + * http://timeago.yarp.com/ + * + * Licensed under the MIT: + * http://www.opensource.org/licenses/mit-license.php + * + * Copyright (c) 2008-2010, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org) + */ + +(function($) { + $.timeago = function(timestamp) { + if (timestamp instanceof Date) return inWords(timestamp); + else if (typeof timestamp == "string") return inWords($.timeago.parse(timestamp)); + else return inWords($.timeago.datetime(timestamp)); + }; + var $t = $.timeago; + + $.extend($.timeago, { + settings: { + refreshMillis: 60000, + allowFuture: false, + strings: { + prefixAgo: null, + prefixFromNow: null, + suffixAgo: "ago", + suffixFromNow: "from now", + seconds: "less than a minute", + minute: "about a minute", + minutes: "%d minutes", + hour: "about an hour", + hours: "about %d hours", + day: "a day", + days: "%d days", + month: "about a month", + months: "%d months", + year: "about a year", + years: "%d years", + numbers: [] + } + }, + inWords: function(distanceMillis) { + var $l = this.settings.strings; + var prefix = $l.prefixAgo; + var suffix = $l.suffixAgo; + if (this.settings.allowFuture) { + if (distanceMillis < 0) { + prefix = $l.prefixFromNow; + suffix = $l.suffixFromNow; + } + distanceMillis = Math.abs(distanceMillis); + } + + var seconds = distanceMillis / 1000; + var minutes = seconds / 60; + var hours = minutes / 60; + var days = hours / 24; + var years = days / 365; + + function substitute(stringOrFunction, number) { + var string = $.isFunction(stringOrFunction) ? stringOrFunction(number) : stringOrFunction; + var value = ($l.numbers && $l.numbers[number]) || number; + return string.replace(/%d/i, value); + } + + var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || + seconds < 90 && substitute($l.minute, 1) || + minutes < 45 && substitute($l.minutes, Math.round(minutes)) || + minutes < 90 && substitute($l.hour, 1) || + hours < 24 && substitute($l.hours, Math.round(hours)) || + hours < 48 && substitute($l.day, 1) || + days < 30 && substitute($l.days, Math.floor(days)) || + days < 60 && substitute($l.month, 1) || + days < 365 && substitute($l.months, Math.floor(days / 30)) || + years < 2 && substitute($l.year, 1) || + substitute($l.years, Math.floor(years)); + + return $.trim([prefix, words, suffix].join(" ")); + }, + parse: function(iso8601) { + var s = $.trim(iso8601); + s = s.replace(/\.\d\d\d/,""); // remove milliseconds + s = s.replace(/-/,"/").replace(/-/,"/"); + s = s.replace(/T/," ").replace(/Z/," UTC"); + s = s.replace(/([\+-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 + return new Date(s); + }, + datetime: function(elem) { + // jQuery's `is()` doesn't play well with HTML5 in IE + var isTime = $(elem).get(0).tagName.toLowerCase() == "time"; // $(elem).is("time"); + var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title"); + return $t.parse(iso8601); + } + }); + + $.fn.timeago = function() { + var self = this; + self.each(refresh); + + var $s = $t.settings; + if ($s.refreshMillis > 0) { + setInterval(function() { self.each(refresh); }, $s.refreshMillis); + } + return self; + }; + + function refresh() { + var data = prepareData(this); + if (!isNaN(data.datetime)) { + $(this).text(inWords(data.datetime)); + } + return this; + } + + function prepareData(element) { + element = $(element); + if (!element.data("timeago")) { + element.data("timeago", { datetime: $t.datetime(element) }); + var text = $.trim(element.text()); + if (text.length > 0) element.attr("title", text); + } + return element.data("timeago"); + } + + function inWords(date) { + return $t.inWords(distance(date)); + } + + function distance(date) { + return (new Date().getTime() - date.getTime()); + } + + // fix for IE6 suckage + document.createElement("abbr"); + document.createElement("time"); +})(jQuery); +// JQuery URL Parser +// Written by Mark Perkins, mark@allmarkedup.com +// License: http://unlicense.org/ (i.e. do what you want with it!) + +jQuery.url = function() +{ + var segments = {}; + + var parsed = {}; + + /** + * Options object. Only the URI and strictMode values can be changed via the setters below. + */ + var options = { + + url : window.location, // default URI is the page in which the script is running + + strictMode: false, // 'loose' parsing by default + + key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], // keys available to query + + q: { + name: "queryKey", + parser: /(?:^|&)([^&=]*)=?([^&]*)/g + }, + + parser: { + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, //less intuitive, more accurate to the specs + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs + } + + }; + + /** + * Deals with the parsing of the URI according to the regex above. + * Written by Steven Levithan - see credits at top. + */ + var parseUri = function() + { + str = decodeURI( options.url ); + + var m = options.parser[ options.strictMode ? "strict" : "loose" ].exec( str ); + var uri = {}; + var i = 14; + + while ( i-- ) { + uri[ options.key[i] ] = m[i] || ""; + } + + uri[ options.q.name ] = {}; + uri[ options.key[12] ].replace( options.q.parser, function ( $0, $1, $2 ) { + if ($1) { + uri[options.q.name][$1] = $2; + } + }); + + return uri; + }; + + /** + * Returns the value of the passed in key from the parsed URI. + * + * @param string key The key whose value is required + */ + var key = function( key ) + { + if ( ! parsed.length ) + { + setUp(); // if the URI has not been parsed yet then do this first... + } + if ( key == "base" ) + { + if ( parsed.port !== null && parsed.port !== "" ) + { + return parsed.protocol+"://"+parsed.host+":"+parsed.port+"/"; + } + else + { + return parsed.protocol+"://"+parsed.host+"/"; + } + } + + return ( parsed[key] === "" ) ? null : parsed[key]; + }; + + /** + * Returns the value of the required query string parameter. + * + * @param string item The parameter whose value is required + */ + var param = function( item ) + { + if ( ! parsed.length ) + { + setUp(); // if the URI has not been parsed yet then do this first... + } + return ( parsed.queryKey[item] === null ) ? null : parsed.queryKey[item]; + }; + + /** + * 'Constructor' (not really!) function. + * Called whenever the URI changes to kick off re-parsing of the URI and splitting it up into segments. + */ + var setUp = function() + { + parsed = parseUri(); + + getSegments(); + }; + + /** + * Splits up the body of the URI into segments (i.e. sections delimited by '/') + */ + var getSegments = function() + { + var p = parsed.path; + segments = []; // clear out segments array + segments = parsed.path.length == 1 ? {} : ( p.charAt( p.length - 1 ) == "/" ? p.substring( 1, p.length - 1 ) : path = p.substring( 1 ) ).split("/"); + }; + + return { + + /** + * Sets the parsing mode - either strict or loose. Set to loose by default. + * + * @param string mode The mode to set the parser to. Anything apart from a value of 'strict' will set it to loose! + */ + setMode : function( mode ) + { + strictMode = mode == "strict" ? true : false; + return this; + }, + + /** + * Sets URI to parse if you don't want to to parse the current page's URI. + * Calling the function with no value for newUri resets it to the current page's URI. + * + * @param string newUri The URI to parse. + */ + setUrl : function( newUri ) + { + options.url = newUri === undefined ? window.location : newUri; + setUp(); + return this; + }, + + /** + * Returns the value of the specified URI segment. Segments are numbered from 1 to the number of segments. + * For example the URI http://test.com/about/company/ segment(1) would return 'about'. + * + * If no integer is passed into the function it returns the number of segments in the URI. + * + * @param int pos The position of the segment to return. Can be empty. + */ + segment : function( pos ) + { + if ( ! parsed.length ) + { + setUp(); // if the URI has not been parsed yet then do this first... + } + if ( pos === undefined ) + { + return segments.length; + } + return ( segments[pos] === "" || segments[pos] === undefined ) ? null : segments[pos]; + }, + + attr : key, // provides public access to private 'key' function - see above + + param : param // provides public access to private 'param' function - see above + + }; + +}(); + + + + +$(document).ready(function() { + // Configuration for fancy sortable tables for source file groups + $('.file_list').dataTable({ + "aaSorting": [[ 1, "asc" ]], + "bPaginate": false, + "bJQueryUI": true, + "aoColumns": [ + null, + { "sType": "percent" }, + null, + null, + null, + null, + null + ] + }); + + // Syntax highlight all files up front - deactivated + // $('.source_table pre code').each(function(i, e) {hljs.highlightBlock(e, ' ')}); + + // Syntax highlight source files on first toggle of the file view popup + $("a.src_link").click(function() { + // Get the source file element that corresponds to the clicked element + var source_table = $($(this).attr('href')); + + // If not highlighted yet, do it! + if (!source_table.hasClass('highlighted')) { + source_table.find('pre code').each(function(i, e) {hljs.highlightBlock(e, ' ')}); + source_table.addClass('highlighted'); + }; + }); + + var prev_anchor; + var curr_anchor; + + // Set-up of popup for source file views + $("a.src_link").colorbox({ + transition: "none", + inline: true, + opacity: 1, + width: "95%", + height: "95%", + onLoad: function() { + if (prev_anchor) { + prev_anchor = jQuery.url.attr('anchor'); + } + curr_anchor = this.href.split('#')[1]; + window.location.hash = curr_anchor; + }, + onCleanup: function() { + if (prev_anchor) { + $('a[href="#'+prev_anchor+'"]').click(); + curr_anchor = prev_anchor; + } else { + $('.group_tabs a:first').click(); + prev_anchor = curr_anchor; + curr_anchor = "#_AllFiles"; + } + window.location.hash = curr_anchor; + } + }); + + // Hide src files and file list container after load + $('.source_files').hide(); + $('.file_list_container').hide(); + + // Add tabs based upon existing file_list_containers + $('.file_list_container h2').each(function(){ + var container_id = $(this).parent().attr('id'); + var group_name = $(this).find('.group_name').first().html(); + var covered_percent = $(this).find('.covered_percent').first().html(); + + $('.group_tabs').append('<li><a href="#' + container_id + '">' + group_name + ' ('+ covered_percent +')</a></li>'); + }); + + $('.group_tabs a').each( function() { + $(this).addClass($(this).attr('href').replace('#', '')); + }); + + // Make sure tabs don't get ugly focus borders when active + $('.group_tabs a').live('focus', function() { $(this).blur(); }); + + var favicon_path = $('link[rel="shortcut icon"]').attr('href'); + $('.group_tabs a').live('click', function(){ + if (!$(this).parent().hasClass('active')) { + $('.group_tabs a').parent().removeClass('active'); + $(this).parent().addClass('active'); + $('.file_list_container').hide(); + $(".file_list_container" + $(this).attr('href')).show(); + window.location.href = window.location.href.split('#')[0] + $(this).attr('href').replace('#', '#_'); + + // Force favicon reload - otherwise the location change containing anchor would drop the favicon... + // Works only on firefox, but still... - Anyone know a better solution to force favicon on local file? + $('link[rel="shortcut icon"]').remove(); + $('head').append('<link rel="shortcut icon" type="image/png" href="'+ favicon_path +'" />'); + }; + return false; + }); + + if (jQuery.url.attr('anchor')) { + var anchor = jQuery.url.attr('anchor') + if (anchor.length == 40) { + $('a.src_link[href=#' + anchor + ']').click(); + } else { + $('.group_tabs a.'+anchor.replace('_', '')).click(); + } + } else { + $('.group_tabs a:first').click(); + }; + + $("abbr.timeago").timeago(); + $('#loading').fadeOut(); + $('#wrapper').show(); +}); diff --git a/.coverage/assets/0.8.0/colorbox/border.png b/.coverage/assets/0.8.0/colorbox/border.png new file mode 100644 index 00000000..df13bb6d Binary files /dev/null and b/.coverage/assets/0.8.0/colorbox/border.png differ diff --git a/.coverage/assets/0.8.0/colorbox/controls.png b/.coverage/assets/0.8.0/colorbox/controls.png new file mode 100644 index 00000000..65cfd1dc Binary files /dev/null and b/.coverage/assets/0.8.0/colorbox/controls.png differ diff --git a/.coverage/assets/0.8.0/colorbox/loading.gif b/.coverage/assets/0.8.0/colorbox/loading.gif new file mode 100644 index 00000000..b4695d81 Binary files /dev/null and b/.coverage/assets/0.8.0/colorbox/loading.gif differ diff --git a/.coverage/assets/0.8.0/colorbox/loading_background.png b/.coverage/assets/0.8.0/colorbox/loading_background.png new file mode 100644 index 00000000..9de11f46 Binary files /dev/null and b/.coverage/assets/0.8.0/colorbox/loading_background.png differ diff --git a/.coverage/assets/0.8.0/favicon_green.png b/.coverage/assets/0.8.0/favicon_green.png new file mode 100644 index 00000000..74db330c Binary files /dev/null and b/.coverage/assets/0.8.0/favicon_green.png differ diff --git a/.coverage/assets/0.8.0/favicon_red.png b/.coverage/assets/0.8.0/favicon_red.png new file mode 100644 index 00000000..fbe093a5 Binary files /dev/null and b/.coverage/assets/0.8.0/favicon_red.png differ diff --git a/.coverage/assets/0.8.0/favicon_yellow.png b/.coverage/assets/0.8.0/favicon_yellow.png new file mode 100644 index 00000000..e53847ea Binary files /dev/null and b/.coverage/assets/0.8.0/favicon_yellow.png differ diff --git a/.coverage/assets/0.8.0/loading.gif b/.coverage/assets/0.8.0/loading.gif new file mode 100644 index 00000000..3596a61f Binary files /dev/null and b/.coverage/assets/0.8.0/loading.gif differ diff --git a/.coverage/assets/0.8.0/magnify.png b/.coverage/assets/0.8.0/magnify.png new file mode 100644 index 00000000..6073b953 Binary files /dev/null and b/.coverage/assets/0.8.0/magnify.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/.coverage/assets/0.8.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 00000000..5b5dab2a Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/.coverage/assets/0.8.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 00000000..ac8b229a Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 00000000..ad3d6346 Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 00000000..42ccba26 Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 00000000..5a46b47c Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png new file mode 100644 index 00000000..86c2baa6 Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png new file mode 100644 index 00000000..4443fdc1 Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/.coverage/assets/0.8.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 00000000..7c9fa6c6 Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-icons_222222_256x240.png b/.coverage/assets/0.8.0/smoothness/images/ui-icons_222222_256x240.png new file mode 100644 index 00000000..b273ff11 Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-icons_222222_256x240.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-icons_2e83ff_256x240.png b/.coverage/assets/0.8.0/smoothness/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 00000000..09d1cdc8 Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-icons_2e83ff_256x240.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-icons_454545_256x240.png b/.coverage/assets/0.8.0/smoothness/images/ui-icons_454545_256x240.png new file mode 100644 index 00000000..59bd45b9 Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-icons_454545_256x240.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-icons_888888_256x240.png b/.coverage/assets/0.8.0/smoothness/images/ui-icons_888888_256x240.png new file mode 100644 index 00000000..6d02426c Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-icons_888888_256x240.png differ diff --git a/.coverage/assets/0.8.0/smoothness/images/ui-icons_cd0a0a_256x240.png b/.coverage/assets/0.8.0/smoothness/images/ui-icons_cd0a0a_256x240.png new file mode 100644 index 00000000..2ab019b7 Binary files /dev/null and b/.coverage/assets/0.8.0/smoothness/images/ui-icons_cd0a0a_256x240.png differ diff --git a/.coverage/index.html b/.coverage/index.html new file mode 100644 index 00000000..c8eb5f92 --- /dev/null +++ b/.coverage/index.html @@ -0,0 +1,29936 @@ +<!DOCTYPE html> +<html xmlns='http://www.w3.org/1999/xhtml'> + <head> + <title>Code coverage for Travis-api</title> + <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + <script src='./assets/0.8.0/application.js' type='text/javascript'></script> + <link href='./assets/0.8.0/application.css' media='screen, projection, print' rel='stylesheet' type='text/css'> + <link rel="shortcut icon" type="image/png" href="./assets/0.8.0/favicon_red.png" /> + <link rel="icon" type="image/png" href="./assets/0.8.0/favicon.png" /> + </head> + + <body> + <div id="loading"> + <img src="./assets/0.8.0/loading.gif" alt="loading"/> + </div> + <div id="wrapper" style="display:none;"> + <div class="timestamp">Generated <abbr class="timeago" title="2015-01-21T16:37:33+01:00">2015-01-21T16:37:33+01:00</abbr></div> + <ul class="group_tabs"></ul> + + <div id="content"> + <div class="file_list_container" id="AllFiles"> + <h2> + <span class="group_name">All Files</span> + (<span class="covered_percent"><span class="red">67.05%</span></span> + covered at + <span class="covered_strength"> + <span class="green"> + 5.33 + </span> + </span> hits/line) + </h2> + <a name="AllFiles"></a> + <div> + <b>93</b> files in total. + <b>2064</b> relevant lines. + <span class="green"><b>1384</b> lines covered</span> and + <span class="red"><b>680</b> lines missed </span> + </div> + <table class="file_list"> + <thead> + <tr> + <th>File</th> + <th>% covered</th> + <th>Lines</th> + <th>Relevant Lines</th> + <th>Lines covered</th> + <th>Lines missed</th> + <th>Avg. Hits / Line</th> + </tr> + </thead> + <tbody> + + <tr> + <td class="strong"><a href="#6a8e7022de4db451dc6c402d7b521d74b4867cec" class="src_link" title="lib/travis/api/app.rb">lib/travis/api/app.rb</a></td> + <td class="yellow strong">85.25 %</td> + <td>207</td> + <td>122</td> + <td>104</td> + <td>18</td> + <td>21.2</td> + </tr> + + <tr> + <td class="strong"><a href="#2563a9e3b6860f10bc10bc8b9abc2e0b307c3396" class="src_link" title="lib/travis/api/app/access_token.rb">lib/travis/api/app/access_token.rb</a></td> + <td class="yellow strong">87.5 %</td> + <td>105</td> + <td>64</td> + <td>56</td> + <td>8</td> + <td>4.3</td> + </tr> + + <tr> + <td class="strong"><a href="#a961b2b2494498d5ea5ba390081b58db5ba6a9ae" class="src_link" title="lib/travis/api/app/base.rb">lib/travis/api/app/base.rb</a></td> + <td class="red strong">73.08 %</td> + <td>53</td> + <td>26</td> + <td>19</td> + <td>7</td> + <td>11.0</td> + </tr> + + <tr> + <td class="strong"><a href="#d160d1d2c1e6c6e0542165ddbf75627d39b2de6f" class="src_link" title="lib/travis/api/app/cors.rb">lib/travis/api/app/cors.rb</a></td> + <td class="red strong">80.0 %</td> + <td>20</td> + <td>10</td> + <td>8</td> + <td>2</td> + <td>7.4</td> + </tr> + + <tr> + <td class="strong"><a href="#eeda47705beb665db84542493bea1c2e0ec05731" class="src_link" title="lib/travis/api/app/endpoint.rb">lib/travis/api/app/endpoint.rb</a></td> + <td class="red strong">70.0 %</td> + <td>50</td> + <td>30</td> + <td>21</td> + <td>9</td> + <td>17.9</td> + </tr> + + <tr> + <td class="strong"><a href="#b2b6630e8ce43a4e90ba2fa3f0747e7269631dd5" class="src_link" title="lib/travis/api/app/endpoint/accounts.rb">lib/travis/api/app/endpoint/accounts.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>11</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#a5a778403a26fa47d8dfe304f657adcbfa66f559" class="src_link" title="lib/travis/api/app/endpoint/authorization.rb">lib/travis/api/app/endpoint/authorization.rb</a></td> + <td class="red strong">26.45 %</td> + <td>522</td> + <td>155</td> + <td>41</td> + <td>114</td> + <td>0.3</td> + </tr> + + <tr> + <td class="strong"><a href="#2b74a2462ad5e4f3ca518f0cc6f13ddc82ee8762" class="src_link" title="lib/travis/api/app/endpoint/branches.rb">lib/travis/api/app/endpoint/branches.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>16</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#f830dba6ed178eb88e884e4ef578db0073e9384a" class="src_link" title="lib/travis/api/app/endpoint/broadcasts.rb">lib/travis/api/app/endpoint/broadcasts.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>11</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#fac69dfa06cb89c53a04099fb945fb4a805cc42c" class="src_link" title="lib/travis/api/app/endpoint/builds.rb">lib/travis/api/app/endpoint/builds.rb</a></td> + <td class="red strong">27.59 %</td> + <td>53</td> + <td>29</td> + <td>8</td> + <td>21</td> + <td>0.3</td> + </tr> + + <tr> + <td class="strong"><a href="#03dcd32988fb710bc7a3c06636a6780bce656589" class="src_link" title="lib/travis/api/app/endpoint/documentation.rb">lib/travis/api/app/endpoint/documentation.rb</a></td> + <td class="yellow strong">85.71 %</td> + <td>13</td> + <td>7</td> + <td>6</td> + <td>1</td> + <td>0.9</td> + </tr> + + <tr> + <td class="strong"><a href="#0dc46adef05fa2cbeadacf05c59276980cc25367" class="src_link" title="lib/travis/api/app/endpoint/endpoints.rb">lib/travis/api/app/endpoint/endpoints.rb</a></td> + <td class="yellow strong">86.96 %</td> + <td>68</td> + <td>23</td> + <td>20</td> + <td>3</td> + <td>19.8</td> + </tr> + + <tr> + <td class="strong"><a href="#413ff5b985954d06f57e54bae462c9380050682b" class="src_link" title="lib/travis/api/app/endpoint/env_vars.rb">lib/travis/api/app/endpoint/env_vars.rb</a></td> + <td class="red strong">44.44 %</td> + <td>31</td> + <td>18</td> + <td>8</td> + <td>10</td> + <td>0.4</td> + </tr> + + <tr> + <td class="strong"><a href="#f01f22d7534ebd190653ed0f88f71a94320108a3" class="src_link" title="lib/travis/api/app/endpoint/home.rb">lib/travis/api/app/endpoint/home.rb</a></td> + <td class="red strong">66.67 %</td> + <td>54</td> + <td>18</td> + <td>12</td> + <td>6</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#389e755e519bf86618fcf82593746fcedb9c4271" class="src_link" title="lib/travis/api/app/endpoint/hooks.rb">lib/travis/api/app/endpoint/hooks.rb</a></td> + <td class="red strong">75.0 %</td> + <td>15</td> + <td>8</td> + <td>6</td> + <td>2</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#0c26cbaa8343afc54bde5f948dbae2fe3039c766" class="src_link" title="lib/travis/api/app/endpoint/jobs.rb">lib/travis/api/app/endpoint/jobs.rb</a></td> + <td class="red strong">22.73 %</td> + <td>122</td> + <td>66</td> + <td>15</td> + <td>51</td> + <td>0.2</td> + </tr> + + <tr> + <td class="strong"><a href="#1d8c0ceda3860fb26fc34a1a770660c35db5b435" class="src_link" title="lib/travis/api/app/endpoint/lint.rb">lib/travis/api/app/endpoint/lint.rb</a></td> + <td class="red strong">61.54 %</td> + <td>19</td> + <td>13</td> + <td>8</td> + <td>5</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#5d621a9a5eb87e9eb39a114965b4bc43594c05ee" class="src_link" title="lib/travis/api/app/endpoint/logs.rb">lib/travis/api/app/endpoint/logs.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>13</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#41717bfcba400b9bc1a7add2cb84d3195cfc3565" class="src_link" title="lib/travis/api/app/endpoint/repos.rb">lib/travis/api/app/endpoint/repos.rb</a></td> + <td class="red strong">39.71 %</td> + <td>189</td> + <td>68</td> + <td>27</td> + <td>41</td> + <td>0.4</td> + </tr> + + <tr> + <td class="strong"><a href="#3542f33a7b8a282ed0436611428aa30ad3f980a1" class="src_link" title="lib/travis/api/app/endpoint/requests.rb">lib/travis/api/app/endpoint/requests.rb</a></td> + <td class="red strong">47.06 %</td> + <td>32</td> + <td>17</td> + <td>8</td> + <td>9</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#b615d4751e9fd711ed50e22c4b49c7c51f964d93" class="src_link" title="lib/travis/api/app/endpoint/setting_endpoint.rb">lib/travis/api/app/endpoint/setting_endpoint.rb</a></td> + <td class="red strong">52.73 %</td> + <td>98</td> + <td>55</td> + <td>29</td> + <td>26</td> + <td>4.6</td> + </tr> + + <tr> + <td class="strong"><a href="#c146923d5484592bc716b1adae4f3329fd9ebb1b" class="src_link" title="lib/travis/api/app/endpoint/singleton_settings_endpoint.rb">lib/travis/api/app/endpoint/singleton_settings_endpoint.rb</a></td> + <td class="red strong">57.14 %</td> + <td>46</td> + <td>28</td> + <td>16</td> + <td>12</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#3aa4c3de70a6e7203940667017613935754e19cd" class="src_link" title="lib/travis/api/app/endpoint/uptime.rb">lib/travis/api/app/endpoint/uptime.rb</a></td> + <td class="red strong">55.56 %</td> + <td>16</td> + <td>9</td> + <td>5</td> + <td>4</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#2aeec642e9353983d22c25e11bb6aee7a68ff327" class="src_link" title="lib/travis/api/app/endpoint/users.rb">lib/travis/api/app/endpoint/users.rb</a></td> + <td class="red strong">50.0 %</td> + <td>59</td> + <td>18</td> + <td>9</td> + <td>9</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#98cb249669c6e20fed930c4f814f8e6266add77c" class="src_link" title="lib/travis/api/app/extensions.rb">lib/travis/api/app/extensions.rb</a></td> + <td class="green strong">100.0 %</td> + <td>8</td> + <td>4</td> + <td>4</td> + <td>0</td> + <td>2.0</td> + </tr> + + <tr> + <td class="strong"><a href="#00c3504cff5eca9f25748185fb2bd47ad1755d92" class="src_link" title="lib/travis/api/app/extensions/expose_pattern.rb">lib/travis/api/app/extensions/expose_pattern.rb</a></td> + <td class="green strong">100.0 %</td> + <td>12</td> + <td>7</td> + <td>7</td> + <td>0</td> + <td>34.7</td> + </tr> + + <tr> + <td class="strong"><a href="#cf7268e37e643b00ddda6c99c2b8d2601a66df25" class="src_link" title="lib/travis/api/app/extensions/scoping.rb">lib/travis/api/app/extensions/scoping.rb</a></td> + <td class="red strong">41.03 %</td> + <td>69</td> + <td>39</td> + <td>16</td> + <td>23</td> + <td>9.4</td> + </tr> + + <tr> + <td class="strong"><a href="#4afdb495e463d11449413cb7fabf94f05a66ff88" class="src_link" title="lib/travis/api/app/extensions/smart_constants.rb">lib/travis/api/app/extensions/smart_constants.rb</a></td> + <td class="green strong">100.0 %</td> + <td>28</td> + <td>11</td> + <td>11</td> + <td>0</td> + <td>3.3</td> + </tr> + + <tr> + <td class="strong"><a href="#32932af295b8d816c57702d2dd3215d03df46d91" class="src_link" title="lib/travis/api/app/extensions/subclass_tracker.rb">lib/travis/api/app/extensions/subclass_tracker.rb</a></td> + <td class="green strong">100.0 %</td> + <td>25</td> + <td>13</td> + <td>13</td> + <td>0</td> + <td>113.6</td> + </tr> + + <tr> + <td class="strong"><a href="#3583b3399a71ebe7de3f253f8a6a166b5ff1450d" class="src_link" title="lib/travis/api/app/helpers.rb">lib/travis/api/app/helpers.rb</a></td> + <td class="green strong">100.0 %</td> + <td>8</td> + <td>4</td> + <td>4</td> + <td>0</td> + <td>2.5</td> + </tr> + + <tr> + <td class="strong"><a href="#d434ebb9387430acf5e4c2c6adda113f213d9a27" class="src_link" title="lib/travis/api/app/helpers/accept.rb">lib/travis/api/app/helpers/accept.rb</a></td> + <td class="red strong">49.06 %</td> + <td>93</td> + <td>53</td> + <td>26</td> + <td>27</td> + <td>1.5</td> + </tr> + + <tr> + <td class="strong"><a href="#945fc5424b8698f6c9f47bf45d950c7993fe7f7d" class="src_link" title="lib/travis/api/app/helpers/current_user.rb">lib/travis/api/app/helpers/current_user.rb</a></td> + <td class="red strong">70.0 %</td> + <td>19</td> + <td>10</td> + <td>7</td> + <td>3</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#d6d6177d6e0d49294315541845ceb6265759cdf1" class="src_link" title="lib/travis/api/app/helpers/db_follower.rb">lib/travis/api/app/helpers/db_follower.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>11</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#9b6cc591941ba41c4e94fefe940858e3353c284f" class="src_link" title="lib/travis/api/app/helpers/flash.rb">lib/travis/api/app/helpers/flash.rb</a></td> + <td class="green strong">100.0 %</td> + <td>11</td> + <td>6</td> + <td>6</td> + <td>0</td> + <td>2.5</td> + </tr> + + <tr> + <td class="strong"><a href="#4bc54455bbe2ec43bb23f5b569a91e4d444598b6" class="src_link" title="lib/travis/api/app/helpers/mime_types.rb">lib/travis/api/app/helpers/mime_types.rb</a></td> + <td class="red strong">64.29 %</td> + <td>28</td> + <td>14</td> + <td>9</td> + <td>5</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#e5ee14c5580baf7a66bac731983db9d3bdb48996" class="src_link" title="lib/travis/api/app/helpers/respond_with.rb">lib/travis/api/app/helpers/respond_with.rb</a></td> + <td class="red strong">40.54 %</td> + <td>70</td> + <td>37</td> + <td>15</td> + <td>22</td> + <td>2.5</td> + </tr> + + <tr> + <td class="strong"><a href="#abcb6fbe07ff5db52c5716e39eb648ef96550296" class="src_link" title="lib/travis/api/app/middleware.rb">lib/travis/api/app/middleware.rb</a></td> + <td class="green strong">100.0 %</td> + <td>7</td> + <td>3</td> + <td>3</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#fafd069a2bcef83fff5f536d88402c883f3cdc31" class="src_link" title="lib/travis/api/app/middleware/logging.rb">lib/travis/api/app/middleware/logging.rb</a></td> + <td class="green strong">100.0 %</td> + <td>15</td> + <td>8</td> + <td>8</td> + <td>0</td> + <td>6.6</td> + </tr> + + <tr> + <td class="strong"><a href="#7670839fd3d16bec4a807509898851298c771968" class="src_link" title="lib/travis/api/app/middleware/metriks.rb">lib/travis/api/app/middleware/metriks.rb</a></td> + <td class="red strong">77.42 %</td> + <td>48</td> + <td>31</td> + <td>24</td> + <td>7</td> + <td>12.5</td> + </tr> + + <tr> + <td class="strong"><a href="#fe2923d329420298ae0fb9e1101c22a8b601d151" class="src_link" title="lib/travis/api/app/middleware/rewrite.rb">lib/travis/api/app/middleware/rewrite.rb</a></td> + <td class="red strong">78.57 %</td> + <td>75</td> + <td>42</td> + <td>33</td> + <td>9</td> + <td>3.6</td> + </tr> + + <tr> + <td class="strong"><a href="#26dd70a212f3b2cbf26d11a0b7f29ee3dec679c3" class="src_link" title="lib/travis/api/app/middleware/scope_check.rb">lib/travis/api/app/middleware/scope_check.rb</a></td> + <td class="green strong">92.59 %</td> + <td>47</td> + <td>27</td> + <td>25</td> + <td>2</td> + <td>8.9</td> + </tr> + + <tr> + <td class="strong"><a href="#57848e06570d6ebc2e75aad01bea70082a1c55f4" class="src_link" title="lib/travis/api/app/middleware/user_agent_tracker.rb">lib/travis/api/app/middleware/user_agent_tracker.rb</a></td> + <td class="red strong">40.0 %</td> + <td>62</td> + <td>35</td> + <td>14</td> + <td>21</td> + <td>1.7</td> + </tr> + + <tr> + <td class="strong"><a href="#866d316bcfc64963406986d03c50d1280b8fe34d" class="src_link" title="lib/travis/api/app/services/schedule_request.rb">lib/travis/api/app/services/schedule_request.rb</a></td> + <td class="red strong">51.61 %</td> + <td>52</td> + <td>31</td> + <td>16</td> + <td>15</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#d04c5eced516ab14b9065b4d34d0af855835a730" class="src_link" title="lib/travis/api/serializer.rb">lib/travis/api/serializer.rb</a></td> + <td class="red strong">66.67 %</td> + <td>23</td> + <td>12</td> + <td>8</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#babe3ce05ce1d657f847b2e01c64437b8e58b014" class="src_link" title="lib/travis/api/v2.rb">lib/travis/api/v2.rb</a></td> + <td class="green strong">100.0 %</td> + <td>8</td> + <td>4</td> + <td>4</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#1c817b9839dda1170aec2560bad5a09065552de6" class="src_link" title="lib/travis/api/v2/http.rb">lib/travis/api/v2/http.rb</a></td> + <td class="green strong">100.0 %</td> + <td>33</td> + <td>28</td> + <td>28</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#c48990e0accf6ba7189617a1b67f9c86eecfc562" class="src_link" title="lib/travis/api/v2/http/accounts.rb">lib/travis/api/v2/http/accounts.rb</a></td> + <td class="red strong">68.75 %</td> + <td>38</td> + <td>16</td> + <td>11</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#65342af497e7edc515415235ed81e3bbaccc6979" class="src_link" title="lib/travis/api/v2/http/annotations.rb">lib/travis/api/v2/http/annotations.rb</a></td> + <td class="red strong">71.43 %</td> + <td>34</td> + <td>14</td> + <td>10</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#e48076813d88d2c6e10c03686156a6f19429e60e" class="src_link" title="lib/travis/api/v2/http/branch.rb">lib/travis/api/v2/http/branch.rb</a></td> + <td class="red strong">71.43 %</td> + <td>28</td> + <td>14</td> + <td>10</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#58933f40c3a13ad2f3470bedf8880494dabc2b2d" class="src_link" title="lib/travis/api/v2/http/branches.rb">lib/travis/api/v2/http/branches.rb</a></td> + <td class="red strong">54.55 %</td> + <td>60</td> + <td>22</td> + <td>12</td> + <td>10</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#c46347e1a0d259fc446170187bf8517d99d49177" class="src_link" title="lib/travis/api/v2/http/broadcasts.rb">lib/travis/api/v2/http/broadcasts.rb</a></td> + <td class="red strong">66.67 %</td> + <td>32</td> + <td>15</td> + <td>10</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#8c4ac5c4e74342720580a492f7c3aa9d4d384e43" class="src_link" title="lib/travis/api/v2/http/build.rb">lib/travis/api/v2/http/build.rb</a></td> + <td class="red strong">60.87 %</td> + <td>87</td> + <td>23</td> + <td>14</td> + <td>9</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#1abcacda27e1da4c1f9879072dc5eb5d0a6f1eab" class="src_link" title="lib/travis/api/v2/http/builds.rb">lib/travis/api/v2/http/builds.rb</a></td> + <td class="red strong">59.09 %</td> + <td>66</td> + <td>22</td> + <td>13</td> + <td>9</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#b7d8a575e84049f0f7983320c9ad1737cc7619a1" class="src_link" title="lib/travis/api/v2/http/caches.rb">lib/travis/api/v2/http/caches.rb</a></td> + <td class="red strong">73.33 %</td> + <td>33</td> + <td>15</td> + <td>11</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#452e1e09b24321c66a631e743b6a84331da9bd13" class="src_link" title="lib/travis/api/v2/http/env_var.rb">lib/travis/api/v2/http/env_var.rb</a></td> + <td class="red strong">61.54 %</td> + <td>23</td> + <td>13</td> + <td>8</td> + <td>5</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#f91e8a59d86280d6f7eb63939f3a080ab5f82e0f" class="src_link" title="lib/travis/api/v2/http/env_vars.rb">lib/travis/api/v2/http/env_vars.rb</a></td> + <td class="green strong">100.0 %</td> + <td>2</td> + <td>1</td> + <td>1</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#16f73e884ddd5d7c35925c636e1981fa77cb5467" class="src_link" title="lib/travis/api/v2/http/hooks.rb">lib/travis/api/v2/http/hooks.rb</a></td> + <td class="red strong">66.67 %</td> + <td>37</td> + <td>15</td> + <td>10</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#7bb06459f99796e92585a0613514a4dc10a3b4e6" class="src_link" title="lib/travis/api/v2/http/job.rb">lib/travis/api/v2/http/job.rb</a></td> + <td class="red strong">70.59 %</td> + <td>63</td> + <td>17</td> + <td>12</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#28a544a6de90280731859574fbbbcf82c3b12b13" class="src_link" title="lib/travis/api/v2/http/jobs.rb">lib/travis/api/v2/http/jobs.rb</a></td> + <td class="red strong">63.16 %</td> + <td>61</td> + <td>19</td> + <td>12</td> + <td>7</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#305e989221ff7819ee74c2690fb3d9b4d6366b86" class="src_link" title="lib/travis/api/v2/http/log.rb">lib/travis/api/v2/http/log.rb</a></td> + <td class="red strong">50.0 %</td> + <td>68</td> + <td>28</td> + <td>14</td> + <td>14</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#87c289727e6a92299bc4a9407f685b69ca6eb426" class="src_link" title="lib/travis/api/v2/http/permissions.rb">lib/travis/api/v2/http/permissions.rb</a></td> + <td class="red strong">58.33 %</td> + <td>50</td> + <td>24</td> + <td>14</td> + <td>10</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#8ff46500e36176862b05aa7513e20da8d68dc208" class="src_link" title="lib/travis/api/v2/http/repositories.rb">lib/travis/api/v2/http/repositories.rb</a></td> + <td class="red strong">68.75 %</td> + <td>43</td> + <td>16</td> + <td>11</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#eff78d14dee73bdad5c2af8b49e3b528390c9207" class="src_link" title="lib/travis/api/v2/http/repository.rb">lib/travis/api/v2/http/repository.rb</a></td> + <td class="red strong">78.57 %</td> + <td>43</td> + <td>14</td> + <td>11</td> + <td>3</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#0438b13b58bbb8a610c81181e35ca9c4273df442" class="src_link" title="lib/travis/api/v2/http/request.rb">lib/travis/api/v2/http/request.rb</a></td> + <td class="red strong">52.17 %</td> + <td>71</td> + <td>23</td> + <td>12</td> + <td>11</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#3409238a742e733e8cc83123cd42c5d119a08c09" class="src_link" title="lib/travis/api/v2/http/requests.rb">lib/travis/api/v2/http/requests.rb</a></td> + <td class="red strong">54.55 %</td> + <td>68</td> + <td>22</td> + <td>12</td> + <td>10</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#5b078e65cda2e46c4754334f975a5362fd4e47ac" class="src_link" title="lib/travis/api/v2/http/ssh_key.rb">lib/travis/api/v2/http/ssh_key.rb</a></td> + <td class="red strong">66.67 %</td> + <td>26</td> + <td>15</td> + <td>10</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#f9da561db1b52264c76f56f7164b6394902c3a2e" class="src_link" title="lib/travis/api/v2/http/ssl_key.rb">lib/travis/api/v2/http/ssl_key.rb</a></td> + <td class="red strong">75.0 %</td> + <td>27</td> + <td>12</td> + <td>9</td> + <td>3</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#4fe5f748a2411310c3bf861101420669e9a8812e" class="src_link" title="lib/travis/api/v2/http/user.rb">lib/travis/api/v2/http/user.rb</a></td> + <td class="red strong">73.33 %</td> + <td>43</td> + <td>15</td> + <td>11</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#dd52431f41a7d9215be3e7f466926538b62b434a" class="src_link" title="lib/travis/api/v2/http/validation_error.rb">lib/travis/api/v2/http/validation_error.rb</a></td> + <td class="red strong">47.37 %</td> + <td>39</td> + <td>19</td> + <td>9</td> + <td>10</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#ec916e10f6af10305ba62ae14eb26968f828b52d" class="src_link" title="lib/travis/api/v3.rb">lib/travis/api/v3.rb</a></td> + <td class="green strong">100.0 %</td> + <td>27</td> + <td>18</td> + <td>18</td> + <td>0</td> + <td>10.1</td> + </tr> + + <tr> + <td class="strong"><a href="#130cf32796ab3cf4d5781313e44244a58973bbf8" class="src_link" title="lib/travis/api/v3/access_control.rb">lib/travis/api/v3/access_control.rb</a></td> + <td class="green strong">100.0 %</td> + <td>15</td> + <td>11</td> + <td>11</td> + <td>0</td> + <td>17.1</td> + </tr> + + <tr> + <td class="strong"><a href="#0c37cbeb8112d8c673c2de5e8d4a0bc4a54debad" class="src_link" title="lib/travis/api/v3/access_control/anonymous.rb">lib/travis/api/v3/access_control/anonymous.rb</a></td> + <td class="green strong">100.0 %</td> + <td>12</td> + <td>6</td> + <td>6</td> + <td>0</td> + <td>3.0</td> + </tr> + + <tr> + <td class="strong"><a href="#0a4dcd743492bb72a7b2e02c986303e9b6a5f680" class="src_link" title="lib/travis/api/v3/access_control/application.rb">lib/travis/api/v3/access_control/application.rb</a></td> + <td class="green strong">93.33 %</td> + <td>25</td> + <td>15</td> + <td>14</td> + <td>1</td> + <td>2.8</td> + </tr> + + <tr> + <td class="strong"><a href="#3e4c532be49003dde82e2f143a6ec6abac0c0fa4" class="src_link" title="lib/travis/api/v3/access_control/generic.rb">lib/travis/api/v3/access_control/generic.rb</a></td> + <td class="green strong">100.0 %</td> + <td>48</td> + <td>25</td> + <td>25</td> + <td>0</td> + <td>6.7</td> + </tr> + + <tr> + <td class="strong"><a href="#cc06bcaeb6af4b5039cc7be04f2dcf7d8cbc1656" class="src_link" title="lib/travis/api/v3/access_control/legacy_token.rb">lib/travis/api/v3/access_control/legacy_token.rb</a></td> + <td class="green strong">100.0 %</td> + <td>27</td> + <td>15</td> + <td>15</td> + <td>0</td> + <td>2.2</td> + </tr> + + <tr> + <td class="strong"><a href="#53595a642e443774649a7e171c5987c76711acd2" class="src_link" title="lib/travis/api/v3/access_control/scoped.rb">lib/travis/api/v3/access_control/scoped.rb</a></td> + <td class="green strong">100.0 %</td> + <td>19</td> + <td>11</td> + <td>11</td> + <td>0</td> + <td>2.1</td> + </tr> + + <tr> + <td class="strong"><a href="#79c75a7a3afdda48d239b26bfbce537aac5c7e87" class="src_link" title="lib/travis/api/v3/access_control/signature.rb">lib/travis/api/v3/access_control/signature.rb</a></td> + <td class="yellow strong">81.25 %</td> + <td>58</td> + <td>32</td> + <td>26</td> + <td>6</td> + <td>3.8</td> + </tr> + + <tr> + <td class="strong"><a href="#8ed530d2fb0e1b23faa65b796edd40391a551aff" class="src_link" title="lib/travis/api/v3/access_control/user.rb">lib/travis/api/v3/access_control/user.rb</a></td> + <td class="green strong">100.0 %</td> + <td>24</td> + <td>14</td> + <td>14</td> + <td>0</td> + <td>2.3</td> + </tr> + + <tr> + <td class="strong"><a href="#e7d3951ce9217b83d561dc22cebb4194095eba79" class="src_link" title="lib/travis/api/v3/error.rb">lib/travis/api/v3/error.rb</a></td> + <td class="yellow strong">85.71 %</td> + <td>38</td> + <td>21</td> + <td>18</td> + <td>3</td> + <td>5.4</td> + </tr> + + <tr> + <td class="strong"><a href="#31a1a8c991fef1e18b15080ccfcb0e9ba1d8c1a4" class="src_link" title="lib/travis/api/v3/opt_in.rb">lib/travis/api/v3/opt_in.rb</a></td> + <td class="green strong">97.22 %</td> + <td>64</td> + <td>36</td> + <td>35</td> + <td>1</td> + <td>13.0</td> + </tr> + + <tr> + <td class="strong"><a href="#8705c480fd77b20d19558856194eeee048030a20" class="src_link" title="lib/travis/api/v3/renderer.rb">lib/travis/api/v3/renderer.rb</a></td> + <td class="green strong">100.0 %</td> + <td>14</td> + <td>8</td> + <td>8</td> + <td>0</td> + <td>7.1</td> + </tr> + + <tr> + <td class="strong"><a href="#1b1a35fbaa7ca2749c8e0b8b9c270d2424fa0183" class="src_link" title="lib/travis/api/v3/renderer/error.rb">lib/travis/api/v3/renderer/error.rb</a></td> + <td class="green strong">100.0 %</td> + <td>14</td> + <td>5</td> + <td>5</td> + <td>0</td> + <td>2.8</td> + </tr> + + <tr> + <td class="strong"><a href="#cca5ed5e9f0a0d7cd46bb5427220ee36042a9e9c" class="src_link" title="lib/travis/api/v3/renderer/repository.rb">lib/travis/api/v3/renderer/repository.rb</a></td> + <td class="green strong">100.0 %</td> + <td>33</td> + <td>10</td> + <td>10</td> + <td>0</td> + <td>7.9</td> + </tr> + + <tr> + <td class="strong"><a href="#74ddbe2707d65e192759c48049f9527b65ce82db" class="src_link" title="lib/travis/api/v3/result.rb">lib/travis/api/v3/result.rb</a></td> + <td class="green strong">93.75 %</td> + <td>28</td> + <td>16</td> + <td>15</td> + <td>1</td> + <td>3.5</td> + </tr> + + <tr> + <td class="strong"><a href="#31c7c96fc03fbcc205b874d99b9af9102c3400d7" class="src_link" title="lib/travis/api/v3/router.rb">lib/travis/api/v3/router.rb</a></td> + <td class="green strong">90.32 %</td> + <td>49</td> + <td>31</td> + <td>28</td> + <td>3</td> + <td>10.5</td> + </tr> + + <tr> + <td class="strong"><a href="#0e450b71a9d314b9765473a9783eafbc6ad24b88" class="src_link" title="lib/travis/api/v3/routes.rb">lib/travis/api/v3/routes.rb</a></td> + <td class="green strong">100.0 %</td> + <td>11</td> + <td>7</td> + <td>7</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#2e298b60191a32090a5982c87b6a53c75d24cb8c" class="src_link" title="lib/travis/api/v3/routes/dsl.rb">lib/travis/api/v3/routes/dsl.rb</a></td> + <td class="green strong">97.22 %</td> + <td>63</td> + <td>36</td> + <td>35</td> + <td>1</td> + <td>12.3</td> + </tr> + + <tr> + <td class="strong"><a href="#f17bf0ade034477bfdb62ad253c6d587b77e5214" class="src_link" title="lib/travis/api/v3/routes/resource.rb">lib/travis/api/v3/routes/resource.rb</a></td> + <td class="green strong">100.0 %</td> + <td>21</td> + <td>12</td> + <td>12</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#847a0c89fe4c592228989215bbeb1143051d97b6" class="src_link" title="lib/travis/api/v3/service.rb">lib/travis/api/v3/service.rb</a></td> + <td class="yellow strong">85.0 %</td> + <td>33</td> + <td>20</td> + <td>17</td> + <td>3</td> + <td>4.8</td> + </tr> + + <tr> + <td class="strong"><a href="#63648861eabe7693b10dd0f87b899dfb0a4ff38f" class="src_link" title="lib/travis/api/v3/service_index.rb">lib/travis/api/v3/service_index.rb</a></td> + <td class="green strong">91.53 %</td> + <td>90</td> + <td>59</td> + <td>54</td> + <td>5</td> + <td>1.9</td> + </tr> + + <tr> + <td class="strong"><a href="#4fa3e7e42191523754efec186ec8bfce3291040f" class="src_link" title="lib/travis/api/v3/services.rb">lib/travis/api/v3/services.rb</a></td> + <td class="green strong">100.0 %</td> + <td>8</td> + <td>5</td> + <td>5</td> + <td>0</td> + <td>11.4</td> + </tr> + + <tr> + <td class="strong"><a href="#a6bb60f0c77473ac7b1a29920833a93a5c2cd7f7" class="src_link" title="lib/travis/api/v3/services/find_repository.rb">lib/travis/api/v3/services/find_repository.rb</a></td> + <td class="red strong">78.57 %</td> + <td>22</td> + <td>14</td> + <td>11</td> + <td>3</td> + <td>9.6</td> + </tr> + + <tr> + <td class="strong"><a href="#dc5349ac13a7e081565d2ad293a276d468fd8b0b" class="src_link" title="lib/travis/private_key.rb">lib/travis/private_key.rb</a></td> + <td class="red strong">50.0 %</td> + <td>16</td> + <td>10</td> + <td>5</td> + <td>5</td> + <td>0.5</td> + </tr> + + </tbody> + </table> +</div> + + + + <div class="file_list_container" id="v3"> + <h2> + <span class="group_name">v3</span> + (<span class="covered_percent"><span class="green">93.68%</span></span> + covered at + <span class="covered_strength"> + <span class="green"> + 6.51 + </span> + </span> hits/line) + </h2> + <a name="v3"></a> + <div> + <b>23</b> files in total. + <b>427</b> relevant lines. + <span class="green"><b>400</b> lines covered</span> and + <span class="red"><b>27</b> lines missed </span> + </div> + <table class="file_list"> + <thead> + <tr> + <th>File</th> + <th>% covered</th> + <th>Lines</th> + <th>Relevant Lines</th> + <th>Lines covered</th> + <th>Lines missed</th> + <th>Avg. Hits / Line</th> + </tr> + </thead> + <tbody> + + <tr> + <td class="strong"><a href="#ec916e10f6af10305ba62ae14eb26968f828b52d" class="src_link" title="lib/travis/api/v3.rb">lib/travis/api/v3.rb</a></td> + <td class="green strong">100.0 %</td> + <td>27</td> + <td>18</td> + <td>18</td> + <td>0</td> + <td>10.1</td> + </tr> + + <tr> + <td class="strong"><a href="#130cf32796ab3cf4d5781313e44244a58973bbf8" class="src_link" title="lib/travis/api/v3/access_control.rb">lib/travis/api/v3/access_control.rb</a></td> + <td class="green strong">100.0 %</td> + <td>15</td> + <td>11</td> + <td>11</td> + <td>0</td> + <td>17.1</td> + </tr> + + <tr> + <td class="strong"><a href="#0c37cbeb8112d8c673c2de5e8d4a0bc4a54debad" class="src_link" title="lib/travis/api/v3/access_control/anonymous.rb">lib/travis/api/v3/access_control/anonymous.rb</a></td> + <td class="green strong">100.0 %</td> + <td>12</td> + <td>6</td> + <td>6</td> + <td>0</td> + <td>3.0</td> + </tr> + + <tr> + <td class="strong"><a href="#0a4dcd743492bb72a7b2e02c986303e9b6a5f680" class="src_link" title="lib/travis/api/v3/access_control/application.rb">lib/travis/api/v3/access_control/application.rb</a></td> + <td class="green strong">93.33 %</td> + <td>25</td> + <td>15</td> + <td>14</td> + <td>1</td> + <td>2.8</td> + </tr> + + <tr> + <td class="strong"><a href="#3e4c532be49003dde82e2f143a6ec6abac0c0fa4" class="src_link" title="lib/travis/api/v3/access_control/generic.rb">lib/travis/api/v3/access_control/generic.rb</a></td> + <td class="green strong">100.0 %</td> + <td>48</td> + <td>25</td> + <td>25</td> + <td>0</td> + <td>6.7</td> + </tr> + + <tr> + <td class="strong"><a href="#cc06bcaeb6af4b5039cc7be04f2dcf7d8cbc1656" class="src_link" title="lib/travis/api/v3/access_control/legacy_token.rb">lib/travis/api/v3/access_control/legacy_token.rb</a></td> + <td class="green strong">100.0 %</td> + <td>27</td> + <td>15</td> + <td>15</td> + <td>0</td> + <td>2.2</td> + </tr> + + <tr> + <td class="strong"><a href="#53595a642e443774649a7e171c5987c76711acd2" class="src_link" title="lib/travis/api/v3/access_control/scoped.rb">lib/travis/api/v3/access_control/scoped.rb</a></td> + <td class="green strong">100.0 %</td> + <td>19</td> + <td>11</td> + <td>11</td> + <td>0</td> + <td>2.1</td> + </tr> + + <tr> + <td class="strong"><a href="#79c75a7a3afdda48d239b26bfbce537aac5c7e87" class="src_link" title="lib/travis/api/v3/access_control/signature.rb">lib/travis/api/v3/access_control/signature.rb</a></td> + <td class="yellow strong">81.25 %</td> + <td>58</td> + <td>32</td> + <td>26</td> + <td>6</td> + <td>3.8</td> + </tr> + + <tr> + <td class="strong"><a href="#8ed530d2fb0e1b23faa65b796edd40391a551aff" class="src_link" title="lib/travis/api/v3/access_control/user.rb">lib/travis/api/v3/access_control/user.rb</a></td> + <td class="green strong">100.0 %</td> + <td>24</td> + <td>14</td> + <td>14</td> + <td>0</td> + <td>2.3</td> + </tr> + + <tr> + <td class="strong"><a href="#e7d3951ce9217b83d561dc22cebb4194095eba79" class="src_link" title="lib/travis/api/v3/error.rb">lib/travis/api/v3/error.rb</a></td> + <td class="yellow strong">85.71 %</td> + <td>38</td> + <td>21</td> + <td>18</td> + <td>3</td> + <td>5.4</td> + </tr> + + <tr> + <td class="strong"><a href="#31a1a8c991fef1e18b15080ccfcb0e9ba1d8c1a4" class="src_link" title="lib/travis/api/v3/opt_in.rb">lib/travis/api/v3/opt_in.rb</a></td> + <td class="green strong">97.22 %</td> + <td>64</td> + <td>36</td> + <td>35</td> + <td>1</td> + <td>13.0</td> + </tr> + + <tr> + <td class="strong"><a href="#8705c480fd77b20d19558856194eeee048030a20" class="src_link" title="lib/travis/api/v3/renderer.rb">lib/travis/api/v3/renderer.rb</a></td> + <td class="green strong">100.0 %</td> + <td>14</td> + <td>8</td> + <td>8</td> + <td>0</td> + <td>7.1</td> + </tr> + + <tr> + <td class="strong"><a href="#1b1a35fbaa7ca2749c8e0b8b9c270d2424fa0183" class="src_link" title="lib/travis/api/v3/renderer/error.rb">lib/travis/api/v3/renderer/error.rb</a></td> + <td class="green strong">100.0 %</td> + <td>14</td> + <td>5</td> + <td>5</td> + <td>0</td> + <td>2.8</td> + </tr> + + <tr> + <td class="strong"><a href="#cca5ed5e9f0a0d7cd46bb5427220ee36042a9e9c" class="src_link" title="lib/travis/api/v3/renderer/repository.rb">lib/travis/api/v3/renderer/repository.rb</a></td> + <td class="green strong">100.0 %</td> + <td>33</td> + <td>10</td> + <td>10</td> + <td>0</td> + <td>7.9</td> + </tr> + + <tr> + <td class="strong"><a href="#74ddbe2707d65e192759c48049f9527b65ce82db" class="src_link" title="lib/travis/api/v3/result.rb">lib/travis/api/v3/result.rb</a></td> + <td class="green strong">93.75 %</td> + <td>28</td> + <td>16</td> + <td>15</td> + <td>1</td> + <td>3.5</td> + </tr> + + <tr> + <td class="strong"><a href="#31c7c96fc03fbcc205b874d99b9af9102c3400d7" class="src_link" title="lib/travis/api/v3/router.rb">lib/travis/api/v3/router.rb</a></td> + <td class="green strong">90.32 %</td> + <td>49</td> + <td>31</td> + <td>28</td> + <td>3</td> + <td>10.5</td> + </tr> + + <tr> + <td class="strong"><a href="#0e450b71a9d314b9765473a9783eafbc6ad24b88" class="src_link" title="lib/travis/api/v3/routes.rb">lib/travis/api/v3/routes.rb</a></td> + <td class="green strong">100.0 %</td> + <td>11</td> + <td>7</td> + <td>7</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#2e298b60191a32090a5982c87b6a53c75d24cb8c" class="src_link" title="lib/travis/api/v3/routes/dsl.rb">lib/travis/api/v3/routes/dsl.rb</a></td> + <td class="green strong">97.22 %</td> + <td>63</td> + <td>36</td> + <td>35</td> + <td>1</td> + <td>12.3</td> + </tr> + + <tr> + <td class="strong"><a href="#f17bf0ade034477bfdb62ad253c6d587b77e5214" class="src_link" title="lib/travis/api/v3/routes/resource.rb">lib/travis/api/v3/routes/resource.rb</a></td> + <td class="green strong">100.0 %</td> + <td>21</td> + <td>12</td> + <td>12</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#847a0c89fe4c592228989215bbeb1143051d97b6" class="src_link" title="lib/travis/api/v3/service.rb">lib/travis/api/v3/service.rb</a></td> + <td class="yellow strong">85.0 %</td> + <td>33</td> + <td>20</td> + <td>17</td> + <td>3</td> + <td>4.8</td> + </tr> + + <tr> + <td class="strong"><a href="#63648861eabe7693b10dd0f87b899dfb0a4ff38f" class="src_link" title="lib/travis/api/v3/service_index.rb">lib/travis/api/v3/service_index.rb</a></td> + <td class="green strong">91.53 %</td> + <td>90</td> + <td>59</td> + <td>54</td> + <td>5</td> + <td>1.9</td> + </tr> + + <tr> + <td class="strong"><a href="#4fa3e7e42191523754efec186ec8bfce3291040f" class="src_link" title="lib/travis/api/v3/services.rb">lib/travis/api/v3/services.rb</a></td> + <td class="green strong">100.0 %</td> + <td>8</td> + <td>5</td> + <td>5</td> + <td>0</td> + <td>11.4</td> + </tr> + + <tr> + <td class="strong"><a href="#a6bb60f0c77473ac7b1a29920833a93a5c2cd7f7" class="src_link" title="lib/travis/api/v3/services/find_repository.rb">lib/travis/api/v3/services/find_repository.rb</a></td> + <td class="red strong">78.57 %</td> + <td>22</td> + <td>14</td> + <td>11</td> + <td>3</td> + <td>9.6</td> + </tr> + + </tbody> + </table> +</div> + + + <div class="file_list_container" id="Ungrouped"> + <h2> + <span class="group_name">Ungrouped</span> + (<span class="covered_percent"><span class="red">60.11%</span></span> + covered at + <span class="covered_strength"> + <span class="green"> + 5.02 + </span> + </span> hits/line) + </h2> + <a name="Ungrouped"></a> + <div> + <b>70</b> files in total. + <b>1637</b> relevant lines. + <span class="green"><b>984</b> lines covered</span> and + <span class="red"><b>653</b> lines missed </span> + </div> + <table class="file_list"> + <thead> + <tr> + <th>File</th> + <th>% covered</th> + <th>Lines</th> + <th>Relevant Lines</th> + <th>Lines covered</th> + <th>Lines missed</th> + <th>Avg. Hits / Line</th> + </tr> + </thead> + <tbody> + + <tr> + <td class="strong"><a href="#6a8e7022de4db451dc6c402d7b521d74b4867cec" class="src_link" title="lib/travis/api/app.rb">lib/travis/api/app.rb</a></td> + <td class="yellow strong">85.25 %</td> + <td>207</td> + <td>122</td> + <td>104</td> + <td>18</td> + <td>21.2</td> + </tr> + + <tr> + <td class="strong"><a href="#2563a9e3b6860f10bc10bc8b9abc2e0b307c3396" class="src_link" title="lib/travis/api/app/access_token.rb">lib/travis/api/app/access_token.rb</a></td> + <td class="yellow strong">87.5 %</td> + <td>105</td> + <td>64</td> + <td>56</td> + <td>8</td> + <td>4.3</td> + </tr> + + <tr> + <td class="strong"><a href="#a961b2b2494498d5ea5ba390081b58db5ba6a9ae" class="src_link" title="lib/travis/api/app/base.rb">lib/travis/api/app/base.rb</a></td> + <td class="red strong">73.08 %</td> + <td>53</td> + <td>26</td> + <td>19</td> + <td>7</td> + <td>11.0</td> + </tr> + + <tr> + <td class="strong"><a href="#d160d1d2c1e6c6e0542165ddbf75627d39b2de6f" class="src_link" title="lib/travis/api/app/cors.rb">lib/travis/api/app/cors.rb</a></td> + <td class="red strong">80.0 %</td> + <td>20</td> + <td>10</td> + <td>8</td> + <td>2</td> + <td>7.4</td> + </tr> + + <tr> + <td class="strong"><a href="#eeda47705beb665db84542493bea1c2e0ec05731" class="src_link" title="lib/travis/api/app/endpoint.rb">lib/travis/api/app/endpoint.rb</a></td> + <td class="red strong">70.0 %</td> + <td>50</td> + <td>30</td> + <td>21</td> + <td>9</td> + <td>17.9</td> + </tr> + + <tr> + <td class="strong"><a href="#b2b6630e8ce43a4e90ba2fa3f0747e7269631dd5" class="src_link" title="lib/travis/api/app/endpoint/accounts.rb">lib/travis/api/app/endpoint/accounts.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>11</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#a5a778403a26fa47d8dfe304f657adcbfa66f559" class="src_link" title="lib/travis/api/app/endpoint/authorization.rb">lib/travis/api/app/endpoint/authorization.rb</a></td> + <td class="red strong">26.45 %</td> + <td>522</td> + <td>155</td> + <td>41</td> + <td>114</td> + <td>0.3</td> + </tr> + + <tr> + <td class="strong"><a href="#2b74a2462ad5e4f3ca518f0cc6f13ddc82ee8762" class="src_link" title="lib/travis/api/app/endpoint/branches.rb">lib/travis/api/app/endpoint/branches.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>16</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#f830dba6ed178eb88e884e4ef578db0073e9384a" class="src_link" title="lib/travis/api/app/endpoint/broadcasts.rb">lib/travis/api/app/endpoint/broadcasts.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>11</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#fac69dfa06cb89c53a04099fb945fb4a805cc42c" class="src_link" title="lib/travis/api/app/endpoint/builds.rb">lib/travis/api/app/endpoint/builds.rb</a></td> + <td class="red strong">27.59 %</td> + <td>53</td> + <td>29</td> + <td>8</td> + <td>21</td> + <td>0.3</td> + </tr> + + <tr> + <td class="strong"><a href="#03dcd32988fb710bc7a3c06636a6780bce656589" class="src_link" title="lib/travis/api/app/endpoint/documentation.rb">lib/travis/api/app/endpoint/documentation.rb</a></td> + <td class="yellow strong">85.71 %</td> + <td>13</td> + <td>7</td> + <td>6</td> + <td>1</td> + <td>0.9</td> + </tr> + + <tr> + <td class="strong"><a href="#0dc46adef05fa2cbeadacf05c59276980cc25367" class="src_link" title="lib/travis/api/app/endpoint/endpoints.rb">lib/travis/api/app/endpoint/endpoints.rb</a></td> + <td class="yellow strong">86.96 %</td> + <td>68</td> + <td>23</td> + <td>20</td> + <td>3</td> + <td>19.8</td> + </tr> + + <tr> + <td class="strong"><a href="#413ff5b985954d06f57e54bae462c9380050682b" class="src_link" title="lib/travis/api/app/endpoint/env_vars.rb">lib/travis/api/app/endpoint/env_vars.rb</a></td> + <td class="red strong">44.44 %</td> + <td>31</td> + <td>18</td> + <td>8</td> + <td>10</td> + <td>0.4</td> + </tr> + + <tr> + <td class="strong"><a href="#f01f22d7534ebd190653ed0f88f71a94320108a3" class="src_link" title="lib/travis/api/app/endpoint/home.rb">lib/travis/api/app/endpoint/home.rb</a></td> + <td class="red strong">66.67 %</td> + <td>54</td> + <td>18</td> + <td>12</td> + <td>6</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#389e755e519bf86618fcf82593746fcedb9c4271" class="src_link" title="lib/travis/api/app/endpoint/hooks.rb">lib/travis/api/app/endpoint/hooks.rb</a></td> + <td class="red strong">75.0 %</td> + <td>15</td> + <td>8</td> + <td>6</td> + <td>2</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#0c26cbaa8343afc54bde5f948dbae2fe3039c766" class="src_link" title="lib/travis/api/app/endpoint/jobs.rb">lib/travis/api/app/endpoint/jobs.rb</a></td> + <td class="red strong">22.73 %</td> + <td>122</td> + <td>66</td> + <td>15</td> + <td>51</td> + <td>0.2</td> + </tr> + + <tr> + <td class="strong"><a href="#1d8c0ceda3860fb26fc34a1a770660c35db5b435" class="src_link" title="lib/travis/api/app/endpoint/lint.rb">lib/travis/api/app/endpoint/lint.rb</a></td> + <td class="red strong">61.54 %</td> + <td>19</td> + <td>13</td> + <td>8</td> + <td>5</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#5d621a9a5eb87e9eb39a114965b4bc43594c05ee" class="src_link" title="lib/travis/api/app/endpoint/logs.rb">lib/travis/api/app/endpoint/logs.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>13</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#41717bfcba400b9bc1a7add2cb84d3195cfc3565" class="src_link" title="lib/travis/api/app/endpoint/repos.rb">lib/travis/api/app/endpoint/repos.rb</a></td> + <td class="red strong">39.71 %</td> + <td>189</td> + <td>68</td> + <td>27</td> + <td>41</td> + <td>0.4</td> + </tr> + + <tr> + <td class="strong"><a href="#3542f33a7b8a282ed0436611428aa30ad3f980a1" class="src_link" title="lib/travis/api/app/endpoint/requests.rb">lib/travis/api/app/endpoint/requests.rb</a></td> + <td class="red strong">47.06 %</td> + <td>32</td> + <td>17</td> + <td>8</td> + <td>9</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#b615d4751e9fd711ed50e22c4b49c7c51f964d93" class="src_link" title="lib/travis/api/app/endpoint/setting_endpoint.rb">lib/travis/api/app/endpoint/setting_endpoint.rb</a></td> + <td class="red strong">52.73 %</td> + <td>98</td> + <td>55</td> + <td>29</td> + <td>26</td> + <td>4.6</td> + </tr> + + <tr> + <td class="strong"><a href="#c146923d5484592bc716b1adae4f3329fd9ebb1b" class="src_link" title="lib/travis/api/app/endpoint/singleton_settings_endpoint.rb">lib/travis/api/app/endpoint/singleton_settings_endpoint.rb</a></td> + <td class="red strong">57.14 %</td> + <td>46</td> + <td>28</td> + <td>16</td> + <td>12</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#3aa4c3de70a6e7203940667017613935754e19cd" class="src_link" title="lib/travis/api/app/endpoint/uptime.rb">lib/travis/api/app/endpoint/uptime.rb</a></td> + <td class="red strong">55.56 %</td> + <td>16</td> + <td>9</td> + <td>5</td> + <td>4</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#2aeec642e9353983d22c25e11bb6aee7a68ff327" class="src_link" title="lib/travis/api/app/endpoint/users.rb">lib/travis/api/app/endpoint/users.rb</a></td> + <td class="red strong">50.0 %</td> + <td>59</td> + <td>18</td> + <td>9</td> + <td>9</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#98cb249669c6e20fed930c4f814f8e6266add77c" class="src_link" title="lib/travis/api/app/extensions.rb">lib/travis/api/app/extensions.rb</a></td> + <td class="green strong">100.0 %</td> + <td>8</td> + <td>4</td> + <td>4</td> + <td>0</td> + <td>2.0</td> + </tr> + + <tr> + <td class="strong"><a href="#00c3504cff5eca9f25748185fb2bd47ad1755d92" class="src_link" title="lib/travis/api/app/extensions/expose_pattern.rb">lib/travis/api/app/extensions/expose_pattern.rb</a></td> + <td class="green strong">100.0 %</td> + <td>12</td> + <td>7</td> + <td>7</td> + <td>0</td> + <td>34.7</td> + </tr> + + <tr> + <td class="strong"><a href="#cf7268e37e643b00ddda6c99c2b8d2601a66df25" class="src_link" title="lib/travis/api/app/extensions/scoping.rb">lib/travis/api/app/extensions/scoping.rb</a></td> + <td class="red strong">41.03 %</td> + <td>69</td> + <td>39</td> + <td>16</td> + <td>23</td> + <td>9.4</td> + </tr> + + <tr> + <td class="strong"><a href="#4afdb495e463d11449413cb7fabf94f05a66ff88" class="src_link" title="lib/travis/api/app/extensions/smart_constants.rb">lib/travis/api/app/extensions/smart_constants.rb</a></td> + <td class="green strong">100.0 %</td> + <td>28</td> + <td>11</td> + <td>11</td> + <td>0</td> + <td>3.3</td> + </tr> + + <tr> + <td class="strong"><a href="#32932af295b8d816c57702d2dd3215d03df46d91" class="src_link" title="lib/travis/api/app/extensions/subclass_tracker.rb">lib/travis/api/app/extensions/subclass_tracker.rb</a></td> + <td class="green strong">100.0 %</td> + <td>25</td> + <td>13</td> + <td>13</td> + <td>0</td> + <td>113.6</td> + </tr> + + <tr> + <td class="strong"><a href="#3583b3399a71ebe7de3f253f8a6a166b5ff1450d" class="src_link" title="lib/travis/api/app/helpers.rb">lib/travis/api/app/helpers.rb</a></td> + <td class="green strong">100.0 %</td> + <td>8</td> + <td>4</td> + <td>4</td> + <td>0</td> + <td>2.5</td> + </tr> + + <tr> + <td class="strong"><a href="#d434ebb9387430acf5e4c2c6adda113f213d9a27" class="src_link" title="lib/travis/api/app/helpers/accept.rb">lib/travis/api/app/helpers/accept.rb</a></td> + <td class="red strong">49.06 %</td> + <td>93</td> + <td>53</td> + <td>26</td> + <td>27</td> + <td>1.5</td> + </tr> + + <tr> + <td class="strong"><a href="#945fc5424b8698f6c9f47bf45d950c7993fe7f7d" class="src_link" title="lib/travis/api/app/helpers/current_user.rb">lib/travis/api/app/helpers/current_user.rb</a></td> + <td class="red strong">70.0 %</td> + <td>19</td> + <td>10</td> + <td>7</td> + <td>3</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#d6d6177d6e0d49294315541845ceb6265759cdf1" class="src_link" title="lib/travis/api/app/helpers/db_follower.rb">lib/travis/api/app/helpers/db_follower.rb</a></td> + <td class="yellow strong">83.33 %</td> + <td>11</td> + <td>6</td> + <td>5</td> + <td>1</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#9b6cc591941ba41c4e94fefe940858e3353c284f" class="src_link" title="lib/travis/api/app/helpers/flash.rb">lib/travis/api/app/helpers/flash.rb</a></td> + <td class="green strong">100.0 %</td> + <td>11</td> + <td>6</td> + <td>6</td> + <td>0</td> + <td>2.5</td> + </tr> + + <tr> + <td class="strong"><a href="#4bc54455bbe2ec43bb23f5b569a91e4d444598b6" class="src_link" title="lib/travis/api/app/helpers/mime_types.rb">lib/travis/api/app/helpers/mime_types.rb</a></td> + <td class="red strong">64.29 %</td> + <td>28</td> + <td>14</td> + <td>9</td> + <td>5</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#e5ee14c5580baf7a66bac731983db9d3bdb48996" class="src_link" title="lib/travis/api/app/helpers/respond_with.rb">lib/travis/api/app/helpers/respond_with.rb</a></td> + <td class="red strong">40.54 %</td> + <td>70</td> + <td>37</td> + <td>15</td> + <td>22</td> + <td>2.5</td> + </tr> + + <tr> + <td class="strong"><a href="#abcb6fbe07ff5db52c5716e39eb648ef96550296" class="src_link" title="lib/travis/api/app/middleware.rb">lib/travis/api/app/middleware.rb</a></td> + <td class="green strong">100.0 %</td> + <td>7</td> + <td>3</td> + <td>3</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#fafd069a2bcef83fff5f536d88402c883f3cdc31" class="src_link" title="lib/travis/api/app/middleware/logging.rb">lib/travis/api/app/middleware/logging.rb</a></td> + <td class="green strong">100.0 %</td> + <td>15</td> + <td>8</td> + <td>8</td> + <td>0</td> + <td>6.6</td> + </tr> + + <tr> + <td class="strong"><a href="#7670839fd3d16bec4a807509898851298c771968" class="src_link" title="lib/travis/api/app/middleware/metriks.rb">lib/travis/api/app/middleware/metriks.rb</a></td> + <td class="red strong">77.42 %</td> + <td>48</td> + <td>31</td> + <td>24</td> + <td>7</td> + <td>12.5</td> + </tr> + + <tr> + <td class="strong"><a href="#fe2923d329420298ae0fb9e1101c22a8b601d151" class="src_link" title="lib/travis/api/app/middleware/rewrite.rb">lib/travis/api/app/middleware/rewrite.rb</a></td> + <td class="red strong">78.57 %</td> + <td>75</td> + <td>42</td> + <td>33</td> + <td>9</td> + <td>3.6</td> + </tr> + + <tr> + <td class="strong"><a href="#26dd70a212f3b2cbf26d11a0b7f29ee3dec679c3" class="src_link" title="lib/travis/api/app/middleware/scope_check.rb">lib/travis/api/app/middleware/scope_check.rb</a></td> + <td class="green strong">92.59 %</td> + <td>47</td> + <td>27</td> + <td>25</td> + <td>2</td> + <td>8.9</td> + </tr> + + <tr> + <td class="strong"><a href="#57848e06570d6ebc2e75aad01bea70082a1c55f4" class="src_link" title="lib/travis/api/app/middleware/user_agent_tracker.rb">lib/travis/api/app/middleware/user_agent_tracker.rb</a></td> + <td class="red strong">40.0 %</td> + <td>62</td> + <td>35</td> + <td>14</td> + <td>21</td> + <td>1.7</td> + </tr> + + <tr> + <td class="strong"><a href="#866d316bcfc64963406986d03c50d1280b8fe34d" class="src_link" title="lib/travis/api/app/services/schedule_request.rb">lib/travis/api/app/services/schedule_request.rb</a></td> + <td class="red strong">51.61 %</td> + <td>52</td> + <td>31</td> + <td>16</td> + <td>15</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#d04c5eced516ab14b9065b4d34d0af855835a730" class="src_link" title="lib/travis/api/serializer.rb">lib/travis/api/serializer.rb</a></td> + <td class="red strong">66.67 %</td> + <td>23</td> + <td>12</td> + <td>8</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#babe3ce05ce1d657f847b2e01c64437b8e58b014" class="src_link" title="lib/travis/api/v2.rb">lib/travis/api/v2.rb</a></td> + <td class="green strong">100.0 %</td> + <td>8</td> + <td>4</td> + <td>4</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#1c817b9839dda1170aec2560bad5a09065552de6" class="src_link" title="lib/travis/api/v2/http.rb">lib/travis/api/v2/http.rb</a></td> + <td class="green strong">100.0 %</td> + <td>33</td> + <td>28</td> + <td>28</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#c48990e0accf6ba7189617a1b67f9c86eecfc562" class="src_link" title="lib/travis/api/v2/http/accounts.rb">lib/travis/api/v2/http/accounts.rb</a></td> + <td class="red strong">68.75 %</td> + <td>38</td> + <td>16</td> + <td>11</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#65342af497e7edc515415235ed81e3bbaccc6979" class="src_link" title="lib/travis/api/v2/http/annotations.rb">lib/travis/api/v2/http/annotations.rb</a></td> + <td class="red strong">71.43 %</td> + <td>34</td> + <td>14</td> + <td>10</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#e48076813d88d2c6e10c03686156a6f19429e60e" class="src_link" title="lib/travis/api/v2/http/branch.rb">lib/travis/api/v2/http/branch.rb</a></td> + <td class="red strong">71.43 %</td> + <td>28</td> + <td>14</td> + <td>10</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#58933f40c3a13ad2f3470bedf8880494dabc2b2d" class="src_link" title="lib/travis/api/v2/http/branches.rb">lib/travis/api/v2/http/branches.rb</a></td> + <td class="red strong">54.55 %</td> + <td>60</td> + <td>22</td> + <td>12</td> + <td>10</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#c46347e1a0d259fc446170187bf8517d99d49177" class="src_link" title="lib/travis/api/v2/http/broadcasts.rb">lib/travis/api/v2/http/broadcasts.rb</a></td> + <td class="red strong">66.67 %</td> + <td>32</td> + <td>15</td> + <td>10</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#8c4ac5c4e74342720580a492f7c3aa9d4d384e43" class="src_link" title="lib/travis/api/v2/http/build.rb">lib/travis/api/v2/http/build.rb</a></td> + <td class="red strong">60.87 %</td> + <td>87</td> + <td>23</td> + <td>14</td> + <td>9</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#1abcacda27e1da4c1f9879072dc5eb5d0a6f1eab" class="src_link" title="lib/travis/api/v2/http/builds.rb">lib/travis/api/v2/http/builds.rb</a></td> + <td class="red strong">59.09 %</td> + <td>66</td> + <td>22</td> + <td>13</td> + <td>9</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#b7d8a575e84049f0f7983320c9ad1737cc7619a1" class="src_link" title="lib/travis/api/v2/http/caches.rb">lib/travis/api/v2/http/caches.rb</a></td> + <td class="red strong">73.33 %</td> + <td>33</td> + <td>15</td> + <td>11</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#452e1e09b24321c66a631e743b6a84331da9bd13" class="src_link" title="lib/travis/api/v2/http/env_var.rb">lib/travis/api/v2/http/env_var.rb</a></td> + <td class="red strong">61.54 %</td> + <td>23</td> + <td>13</td> + <td>8</td> + <td>5</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#f91e8a59d86280d6f7eb63939f3a080ab5f82e0f" class="src_link" title="lib/travis/api/v2/http/env_vars.rb">lib/travis/api/v2/http/env_vars.rb</a></td> + <td class="green strong">100.0 %</td> + <td>2</td> + <td>1</td> + <td>1</td> + <td>0</td> + <td>1.0</td> + </tr> + + <tr> + <td class="strong"><a href="#16f73e884ddd5d7c35925c636e1981fa77cb5467" class="src_link" title="lib/travis/api/v2/http/hooks.rb">lib/travis/api/v2/http/hooks.rb</a></td> + <td class="red strong">66.67 %</td> + <td>37</td> + <td>15</td> + <td>10</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#7bb06459f99796e92585a0613514a4dc10a3b4e6" class="src_link" title="lib/travis/api/v2/http/job.rb">lib/travis/api/v2/http/job.rb</a></td> + <td class="red strong">70.59 %</td> + <td>63</td> + <td>17</td> + <td>12</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#28a544a6de90280731859574fbbbcf82c3b12b13" class="src_link" title="lib/travis/api/v2/http/jobs.rb">lib/travis/api/v2/http/jobs.rb</a></td> + <td class="red strong">63.16 %</td> + <td>61</td> + <td>19</td> + <td>12</td> + <td>7</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#305e989221ff7819ee74c2690fb3d9b4d6366b86" class="src_link" title="lib/travis/api/v2/http/log.rb">lib/travis/api/v2/http/log.rb</a></td> + <td class="red strong">50.0 %</td> + <td>68</td> + <td>28</td> + <td>14</td> + <td>14</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#87c289727e6a92299bc4a9407f685b69ca6eb426" class="src_link" title="lib/travis/api/v2/http/permissions.rb">lib/travis/api/v2/http/permissions.rb</a></td> + <td class="red strong">58.33 %</td> + <td>50</td> + <td>24</td> + <td>14</td> + <td>10</td> + <td>0.6</td> + </tr> + + <tr> + <td class="strong"><a href="#8ff46500e36176862b05aa7513e20da8d68dc208" class="src_link" title="lib/travis/api/v2/http/repositories.rb">lib/travis/api/v2/http/repositories.rb</a></td> + <td class="red strong">68.75 %</td> + <td>43</td> + <td>16</td> + <td>11</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#eff78d14dee73bdad5c2af8b49e3b528390c9207" class="src_link" title="lib/travis/api/v2/http/repository.rb">lib/travis/api/v2/http/repository.rb</a></td> + <td class="red strong">78.57 %</td> + <td>43</td> + <td>14</td> + <td>11</td> + <td>3</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#0438b13b58bbb8a610c81181e35ca9c4273df442" class="src_link" title="lib/travis/api/v2/http/request.rb">lib/travis/api/v2/http/request.rb</a></td> + <td class="red strong">52.17 %</td> + <td>71</td> + <td>23</td> + <td>12</td> + <td>11</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#3409238a742e733e8cc83123cd42c5d119a08c09" class="src_link" title="lib/travis/api/v2/http/requests.rb">lib/travis/api/v2/http/requests.rb</a></td> + <td class="red strong">54.55 %</td> + <td>68</td> + <td>22</td> + <td>12</td> + <td>10</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#5b078e65cda2e46c4754334f975a5362fd4e47ac" class="src_link" title="lib/travis/api/v2/http/ssh_key.rb">lib/travis/api/v2/http/ssh_key.rb</a></td> + <td class="red strong">66.67 %</td> + <td>26</td> + <td>15</td> + <td>10</td> + <td>5</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#f9da561db1b52264c76f56f7164b6394902c3a2e" class="src_link" title="lib/travis/api/v2/http/ssl_key.rb">lib/travis/api/v2/http/ssl_key.rb</a></td> + <td class="red strong">75.0 %</td> + <td>27</td> + <td>12</td> + <td>9</td> + <td>3</td> + <td>0.8</td> + </tr> + + <tr> + <td class="strong"><a href="#4fe5f748a2411310c3bf861101420669e9a8812e" class="src_link" title="lib/travis/api/v2/http/user.rb">lib/travis/api/v2/http/user.rb</a></td> + <td class="red strong">73.33 %</td> + <td>43</td> + <td>15</td> + <td>11</td> + <td>4</td> + <td>0.7</td> + </tr> + + <tr> + <td class="strong"><a href="#dd52431f41a7d9215be3e7f466926538b62b434a" class="src_link" title="lib/travis/api/v2/http/validation_error.rb">lib/travis/api/v2/http/validation_error.rb</a></td> + <td class="red strong">47.37 %</td> + <td>39</td> + <td>19</td> + <td>9</td> + <td>10</td> + <td>0.5</td> + </tr> + + <tr> + <td class="strong"><a href="#dc5349ac13a7e081565d2ad293a276d468fd8b0b" class="src_link" title="lib/travis/private_key.rb">lib/travis/private_key.rb</a></td> + <td class="red strong">50.0 %</td> + <td>16</td> + <td>10</td> + <td>5</td> + <td>5</td> + <td>0.5</td> + </tr> + + </tbody> + </table> +</div> + + + </div> + + <div id="footer"> + Generated by <a href="http://github.com/colszowka/simplecov">simplecov</a> v0.9.1 + and simplecov-html v0.8.0<br/> + using RSpec + </div> + + <div class="source_files"> + + <div class="source_table" id="6a8e7022de4db451dc6c402d7b521d74b4867cec"> + <div class="header"> + <h3>lib/travis/api/app.rb</h3> + <h4><span class="yellow">85.25 %</span> covered</h4> + <div> + <b>122</b> relevant lines. + <span class="green"><b>104</b> lines covered</span> and + <span class="red"><b>18</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/model'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/support/amqp'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/states_cache'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby">require 'rack'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby">require 'rack/protection'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby">require 'rack/contrib'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby">require 'dalli'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby">require 'memcachier'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby">require 'rack/cache'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby">require 'rack/attack'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby">require 'active_record'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby">require 'redis'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby">require 'gh'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby">require 'raven'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby">require 'sidekiq'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby">require 'metriks/reporter/logger'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby">require 'metriks/librato_metrics_reporter'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/support/log_subscriber/active_record_metrics'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby">require 'fileutils'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v2/http'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v3'</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"># Rack class implementing the HTTP API.</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"># Instances respond to #call.</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby">#</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"># run Travis::Api::App.new</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby">#</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"># Requires TLS in production.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="30"> + <span class="hits">1</span> + + <code class="ruby">module Travis::Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="31"> + <span class="hits">1</span> + + <code class="ruby"> class App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="32"> + <span class="hits">1</span> + + <code class="ruby"> autoload :AccessToken, 'travis/api/app/access_token'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="33"> + <span class="hits">1</span> + + <code class="ruby"> autoload :Base, 'travis/api/app/base'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="34"> + <span class="hits">1</span> + + <code class="ruby"> autoload :Endpoint, 'travis/api/app/endpoint'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="35"> + <span class="hits">1</span> + + <code class="ruby"> autoload :Extensions, 'travis/api/app/extensions'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="36"> + <span class="hits">1</span> + + <code class="ruby"> autoload :Helpers, 'travis/api/app/helpers'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="37"> + <span class="hits">1</span> + + <code class="ruby"> autoload :Middleware, 'travis/api/app/middleware'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="38"> + <span class="hits">1</span> + + <code class="ruby"> autoload :Responders, 'travis/api/app/responders'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="39"> + <span class="hits">1</span> + + <code class="ruby"> autoload :Cors, 'travis/api/app/cors'</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="41"> + <span class="hits">1</span> + + <code class="ruby"> Rack.autoload :SSL, 'rack/ssl'</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="43"> + <span class="hits">1</span> + + <code class="ruby"> ERROR_RESPONSE = JSON.generate(error: 'Travis encountered an error, sorry :(')</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> # Used to track if setup already ran.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="46"> + <span class="hits">1</span> + + <code class="ruby"> def self.setup?</code> + </li> + + <li class="covered" data-hits="28" data-linenumber="47"> + <span class="hits">28</span> + + <code class="ruby"> @setup ||= false</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> # Loads all endpoints and middleware and hooks them up properly.</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> # Calls #setup on any middleware and endpoint.</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> # This method is not threadsafe, but called when loading</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> # the environment, so no biggy.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="55"> + <span class="hits">1</span> + + <code class="ruby"> def self.setup(options = {})</code> + </li> + + <li class="covered" data-hits="28" data-linenumber="56"> + <span class="hits">28</span> + + <code class="ruby"> setup! unless setup?</code> + </li> + + <li class="covered" data-hits="28" data-linenumber="57"> + <span class="hits">28</span> + + <code class="ruby"> Endpoint.set(options) if options</code> + </li> + + <li class="covered" data-hits="28" data-linenumber="58"> + <span class="hits">28</span> + + <code class="ruby"> FileUtils.touch('/tmp/app-initialized') if ENV['DYNO'] # Heroku</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="61"> + <span class="hits">1</span> + + <code class="ruby"> def self.new(options = {})</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="62"> + <span class="hits">27</span> + + <code class="ruby"> setup(options)</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="63"> + <span class="hits">27</span> + + <code class="ruby"> super()</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="66"> + <span class="hits">1</span> + + <code class="ruby"> def self.deploy_sha</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="67"> + + + <code class="ruby"> @deploy_sha ||= File.exist?(deploy_sha_path) ? File.read(deploy_sha_path)[0..7] : 'deploy-sha'</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="69"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="70"> + <span class="hits">1</span> + + <code class="ruby"> def self.deploy_sha_path</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="71"> + + + <code class="ruby"> File.expand_path('../../../../.deploy-sha', __FILE__)</code> + </li> + + <li class="never" data-hits="" data-linenumber="72"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="73"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="74"> + <span class="hits">1</span> + + <code class="ruby"> attr_accessor :app</code> + </li> + + <li class="never" data-hits="" data-linenumber="75"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="76"> + <span class="hits">1</span> + + <code class="ruby"> def initialize</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="77"> + <span class="hits">27</span> + + <code class="ruby"> @app = Rack::Builder.app do</code> + </li> + + <li class="covered" data-hits="50" data-linenumber="78"> + <span class="hits">50</span> + + <code class="ruby"> use(Rack::Config) { |env| env['metriks.request.start'] ||= Time.now.utc }</code> + </li> + + <li class="never" data-hits="" data-linenumber="79"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="27" data-linenumber="80"> + <span class="hits">27</span> + + <code class="ruby"> Rack::Utils::HTTP_STATUS_CODES[420] = "Enhance Your Calm"</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="81"> + <span class="hits">27</span> + + <code class="ruby"> use Rack::Attack</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="82"> + <span class="hits">27</span> + + <code class="ruby"> Rack::Attack.blacklist('block client requesting ruby builds') do |req|</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="83"> + <span class="hits">23</span> + + <code class="ruby"> req.ip == "130.15.4.210"</code> + </li> + + <li class="never" data-hits="" data-linenumber="84"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="85"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="27" data-linenumber="86"> + <span class="hits">27</span> + + <code class="ruby"> Rack::Attack.blacklisted_response = lambda do |env|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="87"> + + + <code class="ruby"> [ 420, {}, ['Enhance Your Calm']]</code> + </li> + + <li class="never" data-hits="" data-linenumber="88"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="89"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="27" data-linenumber="90"> + <span class="hits">27</span> + + <code class="ruby"> use Travis::Api::App::Cors # if Travis.env == 'development' ???</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="91"> + <span class="hits">27</span> + + <code class="ruby"> use Raven::Rack if Endpoint.production? && Travis.config.sentry.dsn</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="92"> + <span class="hits">27</span> + + <code class="ruby"> use Rack::Protection::PathTraversal</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="93"> + <span class="hits">27</span> + + <code class="ruby"> use Rack::SSL if Endpoint.production?</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="94"> + <span class="hits">27</span> + + <code class="ruby"> use ActiveRecord::ConnectionAdapters::ConnectionManagement</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="95"> + <span class="hits">27</span> + + <code class="ruby"> use ActiveRecord::QueryCache</code> + </li> + + <li class="never" data-hits="" data-linenumber="96"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="27" data-linenumber="97"> + <span class="hits">27</span> + + <code class="ruby"> memcache_servers = ENV['MEMCACHIER_SERVERS']</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="98"> + <span class="hits">27</span> + + <code class="ruby"> if Travis::Features.feature_active?(:use_rack_cache) && memcache_servers</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="99"> + + + <code class="ruby"> use Rack::Cache,</code> + </li> + + <li class="never" data-hits="" data-linenumber="100"> + + + <code class="ruby"> metastore: "memcached://#{memcache_servers}/meta-#{Travis::Api::App.deploy_sha}",</code> + </li> + + <li class="never" data-hits="" data-linenumber="101"> + + + <code class="ruby"> entitystore: "memcached://#{memcache_servers}/body-#{Travis::Api::App.deploy_sha}"</code> + </li> + + <li class="never" data-hits="" data-linenumber="102"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="103"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="27" data-linenumber="104"> + <span class="hits">27</span> + + <code class="ruby"> use Rack::Deflater</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="105"> + <span class="hits">27</span> + + <code class="ruby"> use Rack::PostBodyContentTypeParser</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="106"> + <span class="hits">27</span> + + <code class="ruby"> use Rack::JSONP</code> + </li> + + <li class="never" data-hits="" data-linenumber="107"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="27" data-linenumber="108"> + <span class="hits">27</span> + + <code class="ruby"> use Rack::Config do |env|</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="109"> + <span class="hits">23</span> + + <code class="ruby"> env['SCRIPT_NAME'] = env['HTTP_X_SCRIPT_NAME'].to_s + env['SCRIPT_NAME'].to_s</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="110"> + <span class="hits">23</span> + + <code class="ruby"> env['travis.global_prefix'] = env['SCRIPT_NAME']</code> + </li> + + <li class="never" data-hits="" data-linenumber="111"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="112"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="113"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="27" data-linenumber="114"> + <span class="hits">27</span> + + <code class="ruby"> use Travis::Api::App::Middleware::Logging</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="115"> + <span class="hits">27</span> + + <code class="ruby"> use Travis::Api::App::Middleware::ScopeCheck</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="116"> + <span class="hits">27</span> + + <code class="ruby"> use Travis::Api::App::Middleware::UserAgentTracker</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="117"> + <span class="hits">27</span> + + <code class="ruby"> use Travis::Api::App::Middleware::Metriks</code> + </li> + + <li class="never" data-hits="" data-linenumber="118"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="119"> + + + <code class="ruby"> # if this is a v3 API request, ignore everything after</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="120"> + <span class="hits">27</span> + + <code class="ruby"> use Travis::API::V3::OptIn</code> + </li> + + <li class="never" data-hits="" data-linenumber="121"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="122"> + + + <code class="ruby"> # rewrite should come after V3 hook</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="123"> + <span class="hits">27</span> + + <code class="ruby"> use Travis::Api::App::Middleware::Rewrite</code> + </li> + + <li class="never" data-hits="" data-linenumber="124"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="27" data-linenumber="125"> + <span class="hits">27</span> + + <code class="ruby"> SettingsEndpoint.subclass :env_vars</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="126"> + <span class="hits">27</span> + + <code class="ruby"> if Travis.config.endpoints.ssh_key</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="127"> + <span class="hits">27</span> + + <code class="ruby"> SingletonSettingsEndpoint.subclass :ssh_key</code> + </li> + + <li class="never" data-hits="" data-linenumber="128"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="129"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="27" data-linenumber="130"> + <span class="hits">27</span> + + <code class="ruby"> Endpoint.subclasses.each do |e|</code> + </li> + + <li class="covered" data-hits="486" data-linenumber="131"> + <span class="hits">486</span> + + <code class="ruby"> next if e == SettingsEndpoint # TODO: add something like abstract? method to check if</code> + </li> + + <li class="never" data-hits="" data-linenumber="132"> + + + <code class="ruby"> # class should be registered</code> + </li> + + <li class="covered" data-hits="972" data-linenumber="133"> + <span class="hits">972</span> + + <code class="ruby"> map(e.prefix) { run(e.new) }</code> + </li> + + <li class="never" data-hits="" data-linenumber="134"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="135"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="136"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="137"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="138"> + + + <code class="ruby"> # Rack protocol</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="139"> + <span class="hits">1</span> + + <code class="ruby"> def call(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="140"> + <span class="hits">23</span> + + <code class="ruby"> app.call(env)</code> + </li> + + <li class="never" data-hits="" data-linenumber="141"> + + + <code class="ruby"> rescue</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="142"> + + + <code class="ruby"> if Endpoint.production?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="143"> + + + <code class="ruby"> [500, {'Content-Type' => 'application/json'}, [ERROR_RESPONSE]]</code> + </li> + + <li class="never" data-hits="" data-linenumber="144"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="145"> + + + <code class="ruby"> raise</code> + </li> + + <li class="never" data-hits="" data-linenumber="146"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="147"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="148"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="149"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="150"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="151"> + <span class="hits">1</span> + + <code class="ruby"> def self.console?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="152"> + + + <code class="ruby"> defined? Travis::Console</code> + </li> + + <li class="never" data-hits="" data-linenumber="153"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="154"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="155"> + <span class="hits">1</span> + + <code class="ruby"> def self.setup!</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="156"> + <span class="hits">1</span> + + <code class="ruby"> setup_travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="157"> + <span class="hits">1</span> + + <code class="ruby"> load_endpoints</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="158"> + <span class="hits">1</span> + + <code class="ruby"> setup_endpoints</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="159"> + <span class="hits">1</span> + + <code class="ruby"> @setup = true</code> + </li> + + <li class="never" data-hits="" data-linenumber="160"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="161"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="162"> + <span class="hits">1</span> + + <code class="ruby"> def self.setup_travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="163"> + <span class="hits">1</span> + + <code class="ruby"> Travis::Async.enabled = true</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="164"> + <span class="hits">1</span> + + <code class="ruby"> Travis::Amqp.config = Travis.config.amqp</code> + </li> + + <li class="never" data-hits="" data-linenumber="165"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="166"> + <span class="hits">1</span> + + <code class="ruby"> setup_database_connections</code> + </li> + + <li class="never" data-hits="" data-linenumber="167"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="168"> + <span class="hits">1</span> + + <code class="ruby"> if Travis.env == 'production' || Travis.env == 'staging'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="169"> + + + <code class="ruby"> Sidekiq.configure_client do |config|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="170"> + + + <code class="ruby"> config.redis = Travis.config.redis.merge(size: 1, namespace: Travis.config.sidekiq.namespace)</code> + </li> + + <li class="never" data-hits="" data-linenumber="171"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="172"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="173"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="174"> + <span class="hits">1</span> + + <code class="ruby"> if (Travis.env == 'production' || Travis.env == 'staging') and not console?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="175"> + + + <code class="ruby"> setup_monitoring</code> + </li> + + <li class="never" data-hits="" data-linenumber="176"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="177"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="178"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="179"> + <span class="hits">1</span> + + <code class="ruby"> def self.setup_database_connections</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="180"> + <span class="hits">1</span> + + <code class="ruby"> Travis::Database.connect</code> + </li> + + <li class="never" data-hits="" data-linenumber="181"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="182"> + <span class="hits">1</span> + + <code class="ruby"> if Travis.config.logs_database</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="183"> + + + <code class="ruby"> Log.establish_connection 'logs_database'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="184"> + + + <code class="ruby"> Log::Part.establish_connection 'logs_database'</code> + </li> + + <li class="never" data-hits="" data-linenumber="185"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="186"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="187"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="188"> + <span class="hits">1</span> + + <code class="ruby"> def self.setup_monitoring</code> + </li> + + <li class="never" data-hits="" data-linenumber="189"> + + + <code class="ruby"> Raven.configure do |config|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="190"> + + + <code class="ruby"> config.dsn = Travis.config.sentry.dsn</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="191"> + + + <code class="ruby"> end if Travis.config.sentry.dsn</code> + </li> + + <li class="never" data-hits="" data-linenumber="192"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="193"> + + + <code class="ruby"> Travis::LogSubscriber::ActiveRecordMetrics.attach</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="194"> + + + <code class="ruby"> Travis::Notification.setup(instrumentation: false)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="195"> + + + <code class="ruby"> Travis::Metrics.setup</code> + </li> + + <li class="never" data-hits="" data-linenumber="196"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="197"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="198"> + <span class="hits">1</span> + + <code class="ruby"> def self.load_endpoints</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="199"> + <span class="hits">6</span> + + <code class="ruby"> Dir.glob("#{__dir__}/app/middleware/*.rb").each { |f| require f[%r[(?<=lib/).+(?=\.rb$)]] }</code> + </li> + + <li class="covered" data-hits="20" data-linenumber="200"> + <span class="hits">20</span> + + <code class="ruby"> Dir.glob("#{__dir__}/app/endpoint/*.rb").each { |f| require f[%r[(?<=lib/).+(?=\.rb$)]] }</code> + </li> + + <li class="never" data-hits="" data-linenumber="201"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="202"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="203"> + <span class="hits">1</span> + + <code class="ruby"> def self.setup_endpoints</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="204"> + <span class="hits">1</span> + + <code class="ruby"> Base.subclasses.each(&:setup)</code> + </li> + + <li class="never" data-hits="" data-linenumber="205"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="206"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="207"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="2563a9e3b6860f10bc10bc8b9abc2e0b307c3396"> + <div class="header"> + <h3>lib/travis/api/app/access_token.rb</h3> + <h4><span class="yellow">87.5 %</span> covered</h4> + <div> + <b>64</b> relevant lines. + <span class="green"><b>56</b> lines covered</span> and + <span class="red"><b>8</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'securerandom'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class AccessToken</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> DEFAULT_SCOPES = [:public, :private]</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :token, :scopes, :user_id, :app_id, :expires_in, :extra</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> def self.create(options = {})</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="10"> + <span class="hits">4</span> + + <code class="ruby"> new(options).tap(&:save)</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def self.for_travis_token(travis_token, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="14"> + + + <code class="ruby"> travis_token = Token.find_by_token(travis_token) unless travis_token.respond_to? :user</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> new(scope: :travis_token, app_id: 1, user: travis_token.user).tap(&:save) if travis_token</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> def self.find_by_token(token)</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="19"> + <span class="hits">8</span> + + <code class="ruby"> return token if token.is_a? self</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="20"> + <span class="hits">8</span> + + <code class="ruby"> user_id, app_id, *scopes = redis.lrange(key(token), 0, -1)</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="21"> + <span class="hits">8</span> + + <code class="ruby"> extra = decode_json(scopes.pop) if scopes.last && scopes.last =~ /^json:/</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="22"> + <span class="hits">8</span> + + <code class="ruby"> new(token: token, scopes: scopes, user_id: user_id, app_id: app_id, extra: extra) if user_id</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(options = {})</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="26"> + <span class="hits">12</span> + + <code class="ruby"> raise ArgumentError, 'must supply either user_id or user' unless options.key?(:user) ^ options.key?(:user_id)</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="27"> + <span class="hits">12</span> + + <code class="ruby"> raise ArgumentError, 'must supply app_id' unless options.key?(:app_id)</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="12" data-linenumber="29"> + <span class="hits">12</span> + + <code class="ruby"> begin</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="30"> + <span class="hits">12</span> + + <code class="ruby"> @expires_in = Integer(options[:expires_in]) if options[:expires_in]</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> rescue ArgumentError</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="32"> + + + <code class="ruby"> raise ArgumentError, 'expires_in must be of integer type'</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="12" data-linenumber="35"> + <span class="hits">12</span> + + <code class="ruby"> @app_id = Integer(options[:app_id])</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="36"> + <span class="hits">12</span> + + <code class="ruby"> @scopes = Array(options[:scopes] || options[:scope] || DEFAULT_SCOPES).map(&:to_sym)</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="37"> + <span class="hits">12</span> + + <code class="ruby"> @user = options[:user]</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="38"> + <span class="hits">12</span> + + <code class="ruby"> @user_id = Integer(options[:user_id] || @user.id)</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="39"> + <span class="hits">12</span> + + <code class="ruby"> @token = options[:token] || reuse_token || SecureRandom.urlsafe_base64(16)</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="40"> + <span class="hits">12</span> + + <code class="ruby"> @extra = options[:extra]</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="43"> + <span class="hits">1</span> + + <code class="ruby"> def save</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="44"> + <span class="hits">4</span> + + <code class="ruby"> key = key(token)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="45"> + <span class="hits">4</span> + + <code class="ruby"> redis.del(key)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="46"> + <span class="hits">4</span> + + <code class="ruby"> data = [user_id, app_id, *scopes]</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="47"> + <span class="hits">4</span> + + <code class="ruby"> data << encode_json(extra) if extra</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="48"> + <span class="hits">4</span> + + <code class="ruby"> redis.rpush(key, data.map(&:to_s))</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="49"> + <span class="hits">4</span> + + <code class="ruby"> redis.set(reuse_key, token)</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="4" data-linenumber="51"> + <span class="hits">4</span> + + <code class="ruby"> if expires_in</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="52"> + + + <code class="ruby"> redis.expire(reuse_key, expires_in)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="53"> + + + <code class="ruby"> redis.expire(key, expires_in)</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="57"> + <span class="hits">1</span> + + <code class="ruby"> def user</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="58"> + <span class="hits">4</span> + + <code class="ruby"> @user ||= User.find(user_id) if user_id</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="61"> + <span class="hits">1</span> + + <code class="ruby"> def user?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="62"> + + + <code class="ruby"> !!user</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="65"> + <span class="hits">1</span> + + <code class="ruby"> def to_s</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="66"> + <span class="hits">4</span> + + <code class="ruby"> token</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="69"> + <span class="hits">1</span> + + <code class="ruby"> module Helpers</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="70"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="71"> + <span class="hits">1</span> + + <code class="ruby"> def redis</code> + </li> + + <li class="covered" data-hits="24" data-linenumber="72"> + <span class="hits">24</span> + + <code class="ruby"> Thread.current[:redis] ||= ::Redis.connect(url: Travis.config.redis.url)</code> + </li> + + <li class="never" data-hits="" data-linenumber="73"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="74"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="75"> + <span class="hits">1</span> + + <code class="ruby"> def key(token)</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="76"> + <span class="hits">12</span> + + <code class="ruby"> "t:#{token}"</code> + </li> + + <li class="never" data-hits="" data-linenumber="77"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="78"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="79"> + <span class="hits">1</span> + + <code class="ruby"> def encode_json(hash)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="80"> + + + <code class="ruby"> 'json:' + Base64.encode64(hash.to_json)</code> + </li> + + <li class="never" data-hits="" data-linenumber="81"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="82"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="83"> + <span class="hits">1</span> + + <code class="ruby"> def decode_json(json)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="84"> + + + <code class="ruby"> JSON.parse(Base64.decode64(json.gsub(/^json:/, '')))</code> + </li> + + <li class="never" data-hits="" data-linenumber="85"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="86"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="87"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="88"> + <span class="hits">1</span> + + <code class="ruby"> include Helpers</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="89"> + <span class="hits">1</span> + + <code class="ruby"> extend Helpers</code> + </li> + + <li class="never" data-hits="" data-linenumber="90"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="91"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="92"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="93"> + <span class="hits">1</span> + + <code class="ruby"> def reuse_token</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="94"> + <span class="hits">4</span> + + <code class="ruby"> redis.get(reuse_key) unless expires_in</code> + </li> + + <li class="never" data-hits="" data-linenumber="95"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="96"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="97"> + <span class="hits">1</span> + + <code class="ruby"> def reuse_key</code> + </li> + + <li class="never" data-hits="" data-linenumber="98"> + + + <code class="ruby"> @reuse_key ||= begin</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="99"> + <span class="hits">4</span> + + <code class="ruby"> keys = ["r", user_id, app_id]</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="100"> + <span class="hits">4</span> + + <code class="ruby"> keys.append(scopes.map(&:to_s).sort) if scopes != DEFAULT_SCOPES</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="101"> + <span class="hits">4</span> + + <code class="ruby"> keys.join(':')</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="102"> + <span class="hits">8</span> + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="103"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="104"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="105"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="a961b2b2494498d5ea5ba390081b58db5ba6a9ae"> + <div class="header"> + <h3>lib/travis/api/app/base.rb</h3> + <h4><span class="red">73.08 %</span> covered</h4> + <div> + <b>26</b> relevant lines. + <span class="green"><b>19</b> lines covered</span> and + <span class="red"><b>7</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'sinatra/base'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">require 'mustermann'</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> # Superclass for any endpoint and middleware.</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> # Pulls in relevant helpers and extensions.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> class Base < Sinatra::Base</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> register Extensions::SmartConstants</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> register Mustermann</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> error NotImplementedError do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> content_type :txt</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="14"> + + + <code class="ruby"> status 501</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> "This feature has not yet been implemented. Sorry :(\n\nPull Requests welcome!"</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> error JSON::ParserError do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> status 400</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> "Invalid JSON in request body"</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> # hotfix??</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="24"> + <span class="hits">1</span> + + <code class="ruby"> def route_missing</code> + </li> + + <li class="covered" data-hits="135" data-linenumber="25"> + <span class="hits">135</span> + + <code class="ruby"> @app ? forward : halt(404)</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="28"> + <span class="hits">1</span> + + <code class="ruby"> def call(env)</code> + </li> + + <li class="covered" data-hits="135" data-linenumber="29"> + <span class="hits">135</span> + + <code class="ruby"> super</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> rescue Sinatra::NotFound</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="31"> + + + <code class="ruby"> [404, {'Content-Type' => 'text/plain'}, ['Tell Konstantin to fix this!']]</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="34"> + <span class="hits">1</span> + + <code class="ruby"> configure do</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> # We pull in certain protection middleware in App.</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> # Being token based makes us invulnerable to common</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> # CSRF attack.</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> # Logging is set up by custom middleware</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="40"> + <span class="hits">1</span> + + <code class="ruby"> disable :protection, :logging, :setup</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="41"> + <span class="hits">1</span> + + <code class="ruby"> enable :raise_errors</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"> # disable :dump_errors</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="43"> + <span class="hits">1</span> + + <code class="ruby"> register :subclass_tracker, :expose_pattern</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="44"> + <span class="hits">1</span> + + <code class="ruby"> helpers :respond_with, :mime_types</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="47"> + <span class="hits">1</span> + + <code class="ruby"> configure :development do</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> # We want error pages in development, but only</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> # when we don't have an error handler specified</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> set :show_exceptions, :after_handler</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="d160d1d2c1e6c6e0542165ddbf75627d39b2de6f"> + <div class="header"> + <h3>lib/travis/api/app/cors.rb</h3> + <h4><span class="red">80.0 %</span> covered</h4> + <div> + <b>10</b> relevant lines. + <span class="green"><b>8</b> lines covered</span> and + <span class="red"><b>2</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"> # Implements Cross-Origin Resource Sharing. Supported by all major browsers.</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # See http://www.w3.org/TR/cors/</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> # TODO: Be smarter about origin.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> class Cors < Base</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> before do</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="10"> + <span class="hits">23</span> + + <code class="ruby"> headers['Access-Control-Allow-Origin'] = "*"</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="11"> + <span class="hits">23</span> + + <code class="ruby"> headers['Access-Control-Allow-Credentials'] = "true"</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="12"> + <span class="hits">23</span> + + <code class="ruby"> headers['Access-Control-Expose-Headers'] = "Content-Type, Cache-Control, Expires, Etag, Last-Modified"</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> options // do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> headers['Access-Control-Allow-Methods'] = "HEAD, GET, POST, PATCH, PUT, DELETE"</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> headers['Access-Control-Allow-Headers'] = "Content-Type, Authorization, Accept, If-None-Match, If-Modified-Since, X-User-Agent"</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="eeda47705beb665db84542493bea1c2e0ec05731"> + <div class="header"> + <h3>lib/travis/api/app/endpoint.rb</h3> + <h4><span class="red">70.0 %</span> covered</h4> + <div> + <b>30</b> relevant lines. + <span class="green"><b>21</b> lines covered</span> and + <span class="red"><b>9</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'addressable/uri'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">require 'active_record/base'</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> # Superclass for HTTP endpoints. Takes care of prefixing.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint < Base</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> include Travis::Services::Helpers</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="471" data-linenumber="10"> + <span class="hits">471</span> + + <code class="ruby"> set(:prefix) { "/" << name[/[^:]+$/].underscore }</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> set disable_root_endpoint: false</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> register :scoping</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> helpers :current_user, :flash, :db_follower</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> # TODO hmmm?</code> + </li> + + <li class="covered" data-hits="11" data-linenumber="16"> + <span class="hits">11</span> + + <code class="ruby"> before { flash.clear }</code> + </li> + + <li class="covered" data-hits="11" data-linenumber="17"> + <span class="hits">11</span> + + <code class="ruby"> after { content_type :json unless content_type }</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby"> error(ActiveRecord::RecordNotFound, Sinatra::NotFound) { not_found }</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby"> not_found {</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="21"> + <span class="hits">10</span> + + <code class="ruby"> if content_type =~ /json/</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="22"> + <span class="hits">10</span> + + <code class="ruby"> if body && !body.empty?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> body</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> else</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="25"> + <span class="hits">10</span> + + <code class="ruby"> { 'file' => 'not found' }</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="28"> + + + <code class="ruby"> 'file not found'</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="32"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="34"> + <span class="hits">1</span> + + <code class="ruby"> def redis</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="35"> + + + <code class="ruby"> Thread.current[:redis] ||= ::Redis.connect(url: Travis.config.redis.url)</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="38"> + <span class="hits">1</span> + + <code class="ruby"> def endpoint(link, query_values = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="39"> + + + <code class="ruby"> link = url(File.join(env['travis.global_prefix'], link), true, false)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="40"> + + + <code class="ruby"> uri = Addressable::URI.parse(link)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="41"> + + + <code class="ruby"> query_values = query_values.merge(uri.query_values) if uri.query_values</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> uri.query_values = query_values</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> uri.to_s</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="46"> + <span class="hits">1</span> + + <code class="ruby"> def safe_redirect(url)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="47"> + + + <code class="ruby"> redirect(endpoint('/redirect', to: url), 301)</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="b2b6630e8ce43a4e90ba2fa3f0747e7269631dd5"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/accounts.rb</h3> + <h4><span class="yellow">83.33 %</span> covered</h4> + <div> + <b>6</b> relevant lines. + <span class="green"><b>5</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Accounts < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> get '/', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> respond_with service(:find_user_accounts, params), type: :accounts</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="a5a778403a26fa47d8dfe304f657adcbfa66f559"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/authorization.rb</h3> + <h4><span class="red">26.45 %</span> covered</h4> + <div> + <b>155</b> relevant lines. + <span class="green"><b>41</b> lines covered</span> and + <span class="red"><b>114</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'addressable/uri'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">require 'faraday'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">require 'securerandom'</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> # You need to get hold of an access token in order to reach any</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> # endpoint requiring authorization.</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> # There are three ways to get hold of such a token: OAuth2, via a GitHub</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> # token you may already have or with Cross-Origin Window Messages.</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> # ## OAuth2</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> # API authorization is done via a subset of OAuth2 and is largely compatible</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> # with the [GitHub process](http://developer.github.com/v3/oauth/).</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> # Be aware that Travis CI will in turn use OAuth2 to authenticate (and</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> # authorize) against GitHub.</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> # This is the recommended way for third-party web apps.</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> # The entry point is [/auth/authorize](#/auth/authorize).</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> # ## GitHub Token</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> # If you already have a GitHub token with the same or greater scope than</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> # the tokens used by Travis CI, you can easily exchange it for a access</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> # token. Travis will not store the GitHub token and only use it for a single</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> # request to resolve the associated user and scopes.</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> # This is the recommended way for GitHub applications that also want Travis</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> # integration.</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> # The entry point is [/auth/github](#POST /auth/github).</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> # ## Cross-Origin Window Messages</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> # This is the recommended way for the official client. We might improve the</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> # authorization flow to support third-party clients in the future, too.</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> # The entry point is [/auth/post_message](#/auth/post_message).</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="41"> + <span class="hits">1</span> + + <code class="ruby"> class Authorization < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="42"> + <span class="hits">1</span> + + <code class="ruby"> enable :inline_templates</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="43"> + <span class="hits">1</span> + + <code class="ruby"> set prefix: '/auth'</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> # Endpoint for retrieving an authorization code, which in turn can be used</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> # to generate an access token.</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> # NOTE: This endpoint is not yet implemented.</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> # Parameters:</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> # * **client_id**: your App's client id (required)</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> # * **redirect_uri**: URL to redirect to</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> # * **scope**: requested access scope</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> # * **state**: should be random string to prevent CSRF attacks</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="56"> + <span class="hits">1</span> + + <code class="ruby"> get '/authorize' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="57"> + + + <code class="ruby"> raise NotImplementedError</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"> # Endpoint for generating an access token from an authorization code.</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> # NOTE: This endpoint is not yet implemented.</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"> # Parameters:</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> # * **client_id**: your App's client id (required)</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> # * **client_secret**: your App's client secret (required)</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"> # * **code**: code retrieved from redirect from [/auth/authorize](#/auth/authorize) (required)</code> + </li> + + <li class="never" data-hits="" data-linenumber="69"> + + + <code class="ruby"> # * **redirect_uri**: URL to redirect to</code> + </li> + + <li class="never" data-hits="" data-linenumber="70"> + + + <code class="ruby"> # * **state**: same value sent to [/auth/authorize](#/auth/authorize)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="71"> + <span class="hits">1</span> + + <code class="ruby"> post '/access_token' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="72"> + + + <code class="ruby"> raise NotImplementedError</code> + </li> + + <li class="never" data-hits="" data-linenumber="73"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="74"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="75"> + + + <code class="ruby"> # Endpoint for generating an access token from a GitHub access token.</code> + </li> + + <li class="never" data-hits="" data-linenumber="76"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="77"> + + + <code class="ruby"> # Parameters:</code> + </li> + + <li class="never" data-hits="" data-linenumber="78"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="79"> + + + <code class="ruby"> # * **github_token**: GitHub token for checking authorization (required)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="80"> + <span class="hits">1</span> + + <code class="ruby"> post '/github' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="81"> + + + <code class="ruby"> unless params[:github_token]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="82"> + + + <code class="ruby"> halt 422, { "error" => "Must pass 'github_token' parameter" }</code> + </li> + + <li class="never" data-hits="" data-linenumber="83"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="84"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="85"> + + + <code class="ruby"> { 'access_token' => github_to_travis(params[:github_token], app_id: 1, drop_token: true) }</code> + </li> + + <li class="never" data-hits="" data-linenumber="86"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="87"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="88"> + + + <code class="ruby"> # Endpoint for making sure user authorized Travis CI to access GitHub.</code> + </li> + + <li class="never" data-hits="" data-linenumber="89"> + + + <code class="ruby"> # There are no restrictions on where to redirect to after handshake.</code> + </li> + + <li class="never" data-hits="" data-linenumber="90"> + + + <code class="ruby"> # However, no information whatsoever is being sent with the redirect.</code> + </li> + + <li class="never" data-hits="" data-linenumber="91"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="92"> + + + <code class="ruby"> # Parameters:</code> + </li> + + <li class="never" data-hits="" data-linenumber="93"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="94"> + + + <code class="ruby"> # * **redirect_uri**: URI to redirect to after handshake.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="95"> + <span class="hits">1</span> + + <code class="ruby"> get '/handshake' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="96"> + + + <code class="ruby"> handshake do |user, token, redirect_uri|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="97"> + + + <code class="ruby"> if target_ok? redirect_uri</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="98"> + + + <code class="ruby"> content_type :html</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="99"> + + + <code class="ruby"> data = { user: user, token: token, uri: redirect_uri }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="100"> + + + <code class="ruby"> erb(:post_payload, locals: data)</code> + </li> + + <li class="never" data-hits="" data-linenumber="101"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="102"> + + + <code class="ruby"> safe_redirect redirect_uri</code> + </li> + + <li class="never" data-hits="" data-linenumber="103"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="104"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="105"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="106"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="107"> + + + <code class="ruby"> # This endpoint is meant to be embedded in an iframe, popup window or</code> + </li> + + <li class="never" data-hits="" data-linenumber="108"> + + + <code class="ruby"> # similar. It will perform the handshake and, once done, will send an</code> + </li> + + <li class="never" data-hits="" data-linenumber="109"> + + + <code class="ruby"> # access token and user payload to the parent window via postMessage.</code> + </li> + + <li class="never" data-hits="" data-linenumber="110"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="111"> + + + <code class="ruby"> # However, the endpoint to send the payload to has to be explicitely</code> + </li> + + <li class="never" data-hits="" data-linenumber="112"> + + + <code class="ruby"> # whitelisted in production, as this is endpoint is only meant to be used</code> + </li> + + <li class="never" data-hits="" data-linenumber="113"> + + + <code class="ruby"> # with the official Travis CI client at the moment.</code> + </li> + + <li class="never" data-hits="" data-linenumber="114"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="115"> + + + <code class="ruby"> # Example usage:</code> + </li> + + <li class="never" data-hits="" data-linenumber="116"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="117"> + + + <code class="ruby"> # window.addEventListener("message", function(event) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="118"> + + + <code class="ruby"> # console.log("received token: " + event.data.token);</code> + </li> + + <li class="never" data-hits="" data-linenumber="119"> + + + <code class="ruby"> # });</code> + </li> + + <li class="never" data-hits="" data-linenumber="120"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="121"> + + + <code class="ruby"> # var iframe = $('<iframe />').hide();</code> + </li> + + <li class="never" data-hits="" data-linenumber="122"> + + + <code class="ruby"> # iframe.appendTo('body');</code> + </li> + + <li class="never" data-hits="" data-linenumber="123"> + + + <code class="ruby"> # iframe.attr('src', "https://api.travis-ci.org/auth/post_message");</code> + </li> + + <li class="never" data-hits="" data-linenumber="124"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="125"> + + + <code class="ruby"> # Note that embedding it in an iframe will only work for users that are</code> + </li> + + <li class="never" data-hits="" data-linenumber="126"> + + + <code class="ruby"> # logged in at GitHub and already authorized Travis CI. It is therefore</code> + </li> + + <li class="never" data-hits="" data-linenumber="127"> + + + <code class="ruby"> # recommended to redirect to [/auth/handshake](#/auth/handshake) if no</code> + </li> + + <li class="never" data-hits="" data-linenumber="128"> + + + <code class="ruby"> # token is being received.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="129"> + <span class="hits">1</span> + + <code class="ruby"> get '/post_message', scope: :public do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="130"> + + + <code class="ruby"> content_type :html</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="131"> + + + <code class="ruby"> data = { check_third_party_cookies: !Travis.config.auth.disable_third_party_cookies_check }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="132"> + + + <code class="ruby"> erb(:container, locals: data)</code> + </li> + + <li class="never" data-hits="" data-linenumber="133"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="134"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="135"> + <span class="hits">1</span> + + <code class="ruby"> get '/post_message/iframe', scope: :public do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="136"> + + + <code class="ruby"> handshake do |user, token, target_origin|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="137"> + + + <code class="ruby"> halt 403, invalid_target(target_origin) unless target_ok? target_origin</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="138"> + + + <code class="ruby"> post_message(token: token, user: user, target_origin: target_origin)</code> + </li> + + <li class="never" data-hits="" data-linenumber="139"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="140"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="141"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="142"> + <span class="hits">1</span> + + <code class="ruby"> error Faraday::Error::ClientError do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="143"> + + + <code class="ruby"> halt 401, 'could not resolve github token'</code> + </li> + + <li class="never" data-hits="" data-linenumber="144"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="145"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="146"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="147"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="148"> + <span class="hits">1</span> + + <code class="ruby"> def serialize_user(user)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="149"> + + + <code class="ruby"> rendered = Travis::Api.data(user, version: :v2)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="150"> + + + <code class="ruby"> rendered['user'].merge('token' => user.tokens.first.try(:token).to_s)</code> + </li> + + <li class="never" data-hits="" data-linenumber="151"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="152"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="153"> + <span class="hits">1</span> + + <code class="ruby"> def oauth_endpoint</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="154"> + + + <code class="ruby"> proxy = Travis.config.oauth2.proxy</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="155"> + + + <code class="ruby"> proxy ? File.join(proxy, request.fullpath) : url</code> + </li> + + <li class="never" data-hits="" data-linenumber="156"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="157"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="158"> + <span class="hits">1</span> + + <code class="ruby"> def handshake</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="159"> + + + <code class="ruby"> config = Travis.config.oauth2</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="160"> + + + <code class="ruby"> endpoint = Addressable::URI.parse(config.authorization_server)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="161"> + + + <code class="ruby"> values = {</code> + </li> + + <li class="never" data-hits="" data-linenumber="162"> + + + <code class="ruby"> client_id: config.client_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="163"> + + + <code class="ruby"> scope: config.scope,</code> + </li> + + <li class="never" data-hits="" data-linenumber="164"> + + + <code class="ruby"> redirect_uri: oauth_endpoint</code> + </li> + + <li class="never" data-hits="" data-linenumber="165"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="166"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="167"> + + + <code class="ruby"> if params[:code]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="168"> + + + <code class="ruby"> halt 400, 'state mismatch' unless state_ok?(params[:state])</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="169"> + + + <code class="ruby"> endpoint.path = config.access_token_path</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="170"> + + + <code class="ruby"> values[:state] = params[:state]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="171"> + + + <code class="ruby"> values[:code] = params[:code]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="172"> + + + <code class="ruby"> values[:client_secret] = config.client_secret</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="173"> + + + <code class="ruby"> github_token = get_token(endpoint.to_s, values)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="174"> + + + <code class="ruby"> user = user_for_github_token(github_token)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="175"> + + + <code class="ruby"> token = generate_token(user: user, app_id: 0)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="176"> + + + <code class="ruby"> payload = params[:state].split(":::", 2)[1]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="177"> + + + <code class="ruby"> yield serialize_user(user), token, payload</code> + </li> + + <li class="never" data-hits="" data-linenumber="178"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="179"> + + + <code class="ruby"> values[:state] = create_state</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="180"> + + + <code class="ruby"> endpoint.path = config.authorize_path</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="181"> + + + <code class="ruby"> endpoint.query_values = values</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="182"> + + + <code class="ruby"> redirect to(endpoint.to_s)</code> + </li> + + <li class="never" data-hits="" data-linenumber="183"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="184"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="185"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="186"> + <span class="hits">1</span> + + <code class="ruby"> def create_state</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="187"> + + + <code class="ruby"> state = SecureRandom.urlsafe_base64(16)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="188"> + + + <code class="ruby"> redis.sadd('github:states', state)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="189"> + + + <code class="ruby"> redis.expire('github:states', 1800)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="190"> + + + <code class="ruby"> payload = params[:origin] || params[:redirect_uri]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="191"> + + + <code class="ruby"> state << ":::" << payload if payload</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="192"> + + + <code class="ruby"> response.set_cookie('travis.state', state)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="193"> + + + <code class="ruby"> state</code> + </li> + + <li class="never" data-hits="" data-linenumber="194"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="195"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="196"> + <span class="hits">1</span> + + <code class="ruby"> def state_ok?(state)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="197"> + + + <code class="ruby"> cookie_state = request.cookies['travis.state']</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="198"> + + + <code class="ruby"> state == cookie_state and redis.srem('github:states', state.to_s.split(":::", 1))</code> + </li> + + <li class="never" data-hits="" data-linenumber="199"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="200"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="201"> + <span class="hits">1</span> + + <code class="ruby"> def github_to_travis(token, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="202"> + + + <code class="ruby"> drop_token = options.delete(:drop_token)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="203"> + + + <code class="ruby"> generate_token options.merge(user: user_for_github_token(token, drop_token))</code> + </li> + + <li class="never" data-hits="" data-linenumber="204"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="205"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="206"> + <span class="hits">1</span> + + <code class="ruby"> class UserManager < Struct.new(:data, :token, :drop_token)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="207"> + <span class="hits">1</span> + + <code class="ruby"> include User::Renaming</code> + </li> + + <li class="never" data-hits="" data-linenumber="208"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="209"> + <span class="hits">1</span> + + <code class="ruby"> attr_accessor :user</code> + </li> + + <li class="never" data-hits="" data-linenumber="210"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="211"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(*)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="212"> + + + <code class="ruby"> super</code> + </li> + + <li class="never" data-hits="" data-linenumber="213"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="214"> + + + <code class="ruby"> @user = ::User.find_by_github_id(data['id'])</code> + </li> + + <li class="never" data-hits="" data-linenumber="215"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="216"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="217"> + <span class="hits">1</span> + + <code class="ruby"> def info(attributes = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="218"> + + + <code class="ruby"> info = data.to_hash.slice('name', 'login', 'gravatar_id')</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="219"> + + + <code class="ruby"> info.merge! attributes.stringify_keys</code> + </li> + + <li class="never" data-hits="" data-linenumber="220"> + + + <code class="ruby"> if Travis::Features.feature_active?(:education_data_sync) ||</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="221"> + + + <code class="ruby"> (user && Travis::Features.owner_active?(:education_data_sync, user))</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="222"> + + + <code class="ruby"> info['education'] = education</code> + </li> + + <li class="never" data-hits="" data-linenumber="223"> + + + <code class="ruby"> end</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="224"> + + + <code class="ruby"> info['github_id'] ||= data['id']</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="225"> + + + <code class="ruby"> info</code> + </li> + + <li class="never" data-hits="" data-linenumber="226"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="227"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="228"> + <span class="hits">1</span> + + <code class="ruby"> def user_exists?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="229"> + + + <code class="ruby"> user</code> + </li> + + <li class="never" data-hits="" data-linenumber="230"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="231"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="232"> + <span class="hits">1</span> + + <code class="ruby"> def education</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="233"> + + + <code class="ruby"> Travis::Github::Education.new(token.to_s).student?</code> + </li> + + <li class="never" data-hits="" data-linenumber="234"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="235"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="236"> + <span class="hits">1</span> + + <code class="ruby"> def fetch</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="237"> + + + <code class="ruby"> retried ||= false</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="238"> + + + <code class="ruby"> info = drop_token ? self.info : self.info(github_oauth_token: token)</code> + </li> + + <li class="never" data-hits="" data-linenumber="239"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="240"> + + + <code class="ruby"> ActiveRecord::Base.transaction do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="241"> + + + <code class="ruby"> if user</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="242"> + + + <code class="ruby"> rename_repos_owner(user.login, info['login'])</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="243"> + + + <code class="ruby"> user.update_attributes info</code> + </li> + + <li class="never" data-hits="" data-linenumber="244"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="245"> + + + <code class="ruby"> self.user = ::User.create! info</code> + </li> + + <li class="never" data-hits="" data-linenumber="246"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="247"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="248"> + + + <code class="ruby"> nullify_logins(user.github_id, user.login)</code> + </li> + + <li class="never" data-hits="" data-linenumber="249"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="250"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="251"> + + + <code class="ruby"> user</code> + </li> + + <li class="never" data-hits="" data-linenumber="252"> + + + <code class="ruby"> rescue ActiveRecord::RecordNotUnique</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="253"> + + + <code class="ruby"> unless retried</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="254"> + + + <code class="ruby"> retried = true</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="255"> + + + <code class="ruby"> retry</code> + </li> + + <li class="never" data-hits="" data-linenumber="256"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="257"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="258"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="259"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="260"> + <span class="hits">1</span> + + <code class="ruby"> def user_for_github_token(token, drop_token = false)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="261"> + + + <code class="ruby"> data = GH.with(token: token.to_s, client_id: nil) { GH['user'] }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="262"> + + + <code class="ruby"> scopes = parse_scopes data.headers['x-oauth-scopes']</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="263"> + + + <code class="ruby"> manager = UserManager.new(data, token, drop_token)</code> + </li> + + <li class="never" data-hits="" data-linenumber="264"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="265"> + + + <code class="ruby"> unless acceptable?(scopes, drop_token)</code> + </li> + + <li class="never" data-hits="" data-linenumber="266"> + + + <code class="ruby"> # TODO: we should probably only redirect if this is a web</code> + </li> + + <li class="never" data-hits="" data-linenumber="267"> + + + <code class="ruby"> # oauth request, are there any other possibilities to</code> + </li> + + <li class="never" data-hits="" data-linenumber="268"> + + + <code class="ruby"> # consider?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="269"> + + + <code class="ruby"> url = Travis.config.oauth2.insufficient_access_redirect_url</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="270"> + + + <code class="ruby"> url += "#existing-user" if manager.user_exists?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="271"> + + + <code class="ruby"> redirect to(url)</code> + </li> + + <li class="never" data-hits="" data-linenumber="272"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="273"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="274"> + + + <code class="ruby"> user = manager.fetch</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="275"> + + + <code class="ruby"> halt 403, 'not a Travis user' if user.nil?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="276"> + + + <code class="ruby"> user</code> + </li> + + <li class="never" data-hits="" data-linenumber="277"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="278"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="279"> + <span class="hits">1</span> + + <code class="ruby"> def get_token(endpoint, values)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="280"> + + + <code class="ruby"> response = Faraday.new(ssl: Travis.config.github.ssl).post(endpoint, values)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="281"> + + + <code class="ruby"> parameters = Addressable::URI.form_unencode(response.body)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="282"> + + + <code class="ruby"> token_info = parameters.assoc("access_token")</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="283"> + + + <code class="ruby"> halt 401, 'could not resolve github token' unless token_info</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="284"> + + + <code class="ruby"> token_info.last</code> + </li> + + <li class="never" data-hits="" data-linenumber="285"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="286"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="287"> + <span class="hits">1</span> + + <code class="ruby"> def parse_scopes(data)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="288"> + + + <code class="ruby"> data.gsub(/\s/,'').split(',') if data</code> + </li> + + <li class="never" data-hits="" data-linenumber="289"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="290"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="291"> + <span class="hits">1</span> + + <code class="ruby"> def generate_token(options)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="292"> + + + <code class="ruby"> AccessToken.create(options).token</code> + </li> + + <li class="never" data-hits="" data-linenumber="293"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="294"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="295"> + <span class="hits">1</span> + + <code class="ruby"> def acceptable?(scopes, lossy = false)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="296"> + + + <code class="ruby"> User::Oauth.wanted_scopes.all? do |scope|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="297"> + + + <code class="ruby"> acceptable_scopes_for(scope, lossy).any? { |s| scopes.include? s }</code> + </li> + + <li class="never" data-hits="" data-linenumber="298"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="299"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="300"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="301"> + <span class="hits">1</span> + + <code class="ruby"> def acceptable_scopes_for(scope, lossy = false)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="302"> + + + <code class="ruby"> scopes = case scope = scope.to_s</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="303"> + + + <code class="ruby"> when /^(.+):/ then [$1, scope]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="304"> + + + <code class="ruby"> when 'public_repo' then [scope, 'repo']</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="305"> + + + <code class="ruby"> else [scope]</code> + </li> + + <li class="never" data-hits="" data-linenumber="306"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="307"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="308"> + + + <code class="ruby"> if lossy</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="309"> + + + <code class="ruby"> scopes << 'repo'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="310"> + + + <code class="ruby"> scopes << 'public_repo' if lossy and scope != 'repo'</code> + </li> + + <li class="never" data-hits="" data-linenumber="311"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="312"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="313"> + + + <code class="ruby"> scopes</code> + </li> + + <li class="never" data-hits="" data-linenumber="314"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="315"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="316"> + <span class="hits">1</span> + + <code class="ruby"> def post_message(payload)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="317"> + + + <code class="ruby"> content_type :html</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="318"> + + + <code class="ruby"> erb(:post_message, locals: payload)</code> + </li> + + <li class="never" data-hits="" data-linenumber="319"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="320"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="321"> + <span class="hits">1</span> + + <code class="ruby"> def invalid_target(target_origin)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="322"> + + + <code class="ruby"> content_type :html</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="323"> + + + <code class="ruby"> erb(:invalid_target, {}, target_origin: target_origin)</code> + </li> + + <li class="never" data-hits="" data-linenumber="324"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="325"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="326"> + <span class="hits">1</span> + + <code class="ruby"> def target_ok?(target_origin)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="327"> + + + <code class="ruby"> return unless uri = Addressable::URI.parse(target_origin)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="328"> + + + <code class="ruby"> if allowed_https_targets.include?(uri.host)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="329"> + + + <code class="ruby"> uri.scheme == 'https'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="330"> + + + <code class="ruby"> elsif uri.host =~ /\A(.+\.)?travis-ci\.(com|org)\Z/</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="331"> + + + <code class="ruby"> uri.scheme == 'https'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="332"> + + + <code class="ruby"> elsif uri.host =~ /\A(.+\.)?travis-lite\.com\Z/</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="333"> + + + <code class="ruby"> uri.scheme == 'https'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="334"> + + + <code class="ruby"> elsif uri.host == 'localhost' or uri.host == '127.0.0.1'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="335"> + + + <code class="ruby"> uri.port > 1023</code> + </li> + + <li class="never" data-hits="" data-linenumber="336"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="337"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="338"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="339"> + <span class="hits">1</span> + + <code class="ruby"> def allowed_https_targets</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="340"> + + + <code class="ruby"> @allowed_https_targets ||= Travis.config.auth.target_origin.to_s.split(',')</code> + </li> + + <li class="never" data-hits="" data-linenumber="341"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="342"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="343"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="344"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="345"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="346"> + + + <code class="ruby">__END__</code> + </li> + + <li class="never" data-hits="" data-linenumber="347"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="348"> + + + <code class="ruby">@@ invalid_target</code> + </li> + + <li class="never" data-hits="" data-linenumber="349"> + + + <code class="ruby"><script></code> + </li> + + <li class="never" data-hits="" data-linenumber="350"> + + + <code class="ruby">console.log('refusing to send a token to <%= target_origin.inspect %>, not whitelisted!');</code> + </li> + + <li class="never" data-hits="" data-linenumber="351"> + + + <code class="ruby"></script></code> + </li> + + <li class="never" data-hits="" data-linenumber="352"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="353"> + + + <code class="ruby">@@ common</code> + </li> + + <li class="never" data-hits="" data-linenumber="354"> + + + <code class="ruby">function tellEveryone(msg, win) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="355"> + + + <code class="ruby"> if(win == undefined) win = window;</code> + </li> + + <li class="never" data-hits="" data-linenumber="356"> + + + <code class="ruby"> win.postMessage(msg, '*');</code> + </li> + + <li class="never" data-hits="" data-linenumber="357"> + + + <code class="ruby"> if(win.parent != win) tellEveryone(msg, win.parent);</code> + </li> + + <li class="never" data-hits="" data-linenumber="358"> + + + <code class="ruby"> if(win.opener) tellEveryone(msg, win.opener);</code> + </li> + + <li class="never" data-hits="" data-linenumber="359"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="360"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="361"> + + + <code class="ruby">@@ container</code> + </li> + + <li class="never" data-hits="" data-linenumber="362"> + + + <code class="ruby"><!DOCTYPE html></code> + </li> + + <li class="never" data-hits="" data-linenumber="363"> + + + <code class="ruby"><html><body><script></code> + </li> + + <li class="never" data-hits="" data-linenumber="364"> + + + <code class="ruby">// === THE FLOW ===</code> + </li> + + <li class="never" data-hits="" data-linenumber="365"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="366"> + + + <code class="ruby">// every serious program has a main function</code> + </li> + + <li class="never" data-hits="" data-linenumber="367"> + + + <code class="ruby">function main() {</code> + </li> + + <li class="never" data-hits="" data-linenumber="368"> + + + <code class="ruby"> doYouHave(thirdPartyCookies,</code> + </li> + + <li class="never" data-hits="" data-linenumber="369"> + + + <code class="ruby"> yesIndeed("third party cookies enabled, creating iframe",</code> + </li> + + <li class="never" data-hits="" data-linenumber="370"> + + + <code class="ruby"> doYouHave(iframe(after(5)),</code> + </li> + + <li class="never" data-hits="" data-linenumber="371"> + + + <code class="ruby"> yesIndeed("iframe succeeded", done),</code> + </li> + + <li class="never" data-hits="" data-linenumber="372"> + + + <code class="ruby"> nopeSorry("iframe taking too long, creating pop-up",</code> + </li> + + <li class="never" data-hits="" data-linenumber="373"> + + + <code class="ruby"> doYouHave(popup(after(5)),</code> + </li> + + <li class="never" data-hits="" data-linenumber="374"> + + + <code class="ruby"> yesIndeed("pop-up succeeded", done),</code> + </li> + + <li class="never" data-hits="" data-linenumber="375"> + + + <code class="ruby"> nopeSorry("pop-up failed, redirecting", redirect))))),</code> + </li> + + <li class="never" data-hits="" data-linenumber="376"> + + + <code class="ruby"> nopeSorry("third party cookies disabled, creating pop-up",</code> + </li> + + <li class="never" data-hits="" data-linenumber="377"> + + + <code class="ruby"> doYouHave(popup(after(8)),</code> + </li> + + <li class="never" data-hits="" data-linenumber="378"> + + + <code class="ruby"> yesIndeed("popup succeeded", done),</code> + </li> + + <li class="never" data-hits="" data-linenumber="379"> + + + <code class="ruby"> nopeSorry("popup failed", redirect))))();</code> + </li> + + <li class="never" data-hits="" data-linenumber="380"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="381"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="382"> + + + <code class="ruby">// === THE LOGIC ===</code> + </li> + + <li class="never" data-hits="" data-linenumber="383"> + + + <code class="ruby">var url = window.location.pathname + '/iframe' + window.location.search;</code> + </li> + + <li class="never" data-hits="" data-linenumber="384"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="385"> + + + <code class="ruby">function thirdPartyCookies(yes, no) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="386"> + + + <code class="ruby"> <%= "return no();" unless check_third_party_cookies %></code> + </li> + + <li class="never" data-hits="" data-linenumber="387"> + + + <code class="ruby"> window.cookiesCheckCallback = function(enabled) { enabled ? yes() : no() };</code> + </li> + + <li class="never" data-hits="" data-linenumber="388"> + + + <code class="ruby"> var img = document.createElement('img');</code> + </li> + + <li class="never" data-hits="" data-linenumber="389"> + + + <code class="ruby"> img.src = "https://third-party-cookies.herokuapp.com/set";</code> + </li> + + <li class="never" data-hits="" data-linenumber="390"> + + + <code class="ruby"> img.onload = function() {</code> + </li> + + <li class="never" data-hits="" data-linenumber="391"> + + + <code class="ruby"> var script = document.createElement('script');</code> + </li> + + <li class="never" data-hits="" data-linenumber="392"> + + + <code class="ruby"> script.src = "https://third-party-cookies.herokuapp.com/check";</code> + </li> + + <li class="never" data-hits="" data-linenumber="393"> + + + <code class="ruby"> window.document.body.appendChild(script);</code> + </li> + + <li class="never" data-hits="" data-linenumber="394"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="395"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="396"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="397"> + + + <code class="ruby">function iframe(time) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="398"> + + + <code class="ruby"> return function(yes, no) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="399"> + + + <code class="ruby"> var iframe = document.createElement('iframe');</code> + </li> + + <li class="never" data-hits="" data-linenumber="400"> + + + <code class="ruby"> iframe.src = url;</code> + </li> + + <li class="never" data-hits="" data-linenumber="401"> + + + <code class="ruby"> timeout(time, yes, no);</code> + </li> + + <li class="never" data-hits="" data-linenumber="402"> + + + <code class="ruby"> window.document.body.appendChild(iframe);</code> + </li> + + <li class="never" data-hits="" data-linenumber="403"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="404"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="405"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="406"> + + + <code class="ruby">function popup(time) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="407"> + + + <code class="ruby"> return function(yes, no) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="408"> + + + <code class="ruby"> if(popupWindow) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="409"> + + + <code class="ruby"> timeout(time, yes, function() {</code> + </li> + + <li class="never" data-hits="" data-linenumber="410"> + + + <code class="ruby"> if(popupWindow.closed || popupWindow.innerHeight < 1) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="411"> + + + <code class="ruby"> no()</code> + </li> + + <li class="never" data-hits="" data-linenumber="412"> + + + <code class="ruby"> } else {</code> + </li> + + <li class="never" data-hits="" data-linenumber="413"> + + + <code class="ruby"> try {</code> + </li> + + <li class="never" data-hits="" data-linenumber="414"> + + + <code class="ruby"> popupWindow.focus();</code> + </li> + + <li class="never" data-hits="" data-linenumber="415"> + + + <code class="ruby"> popupWindow.resizeTo(900, 500);</code> + </li> + + <li class="never" data-hits="" data-linenumber="416"> + + + <code class="ruby"> } catch(err) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="417"> + + + <code class="ruby"> no()</code> + </li> + + <li class="never" data-hits="" data-linenumber="418"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="419"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="420"> + + + <code class="ruby"> });</code> + </li> + + <li class="never" data-hits="" data-linenumber="421"> + + + <code class="ruby"> } else {</code> + </li> + + <li class="never" data-hits="" data-linenumber="422"> + + + <code class="ruby"> no()</code> + </li> + + <li class="never" data-hits="" data-linenumber="423"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="424"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="425"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="426"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="427"> + + + <code class="ruby">function done() {</code> + </li> + + <li class="never" data-hits="" data-linenumber="428"> + + + <code class="ruby"> if(popupWindow && !popupWindow.closed) popupWindow.close();</code> + </li> + + <li class="never" data-hits="" data-linenumber="429"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="430"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="431"> + + + <code class="ruby">function redirect() {</code> + </li> + + <li class="never" data-hits="" data-linenumber="432"> + + + <code class="ruby"> tellEveryone('redirect');</code> + </li> + + <li class="never" data-hits="" data-linenumber="433"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="434"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="435"> + + + <code class="ruby">function createPopup() {</code> + </li> + + <li class="never" data-hits="" data-linenumber="436"> + + + <code class="ruby"> if(!popupWindow) popupWindow = window.open(url, 'Signing in...', 'height=50,width=50');</code> + </li> + + <li class="never" data-hits="" data-linenumber="437"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="438"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="439"> + + + <code class="ruby">// === THE PLUMBING ===</code> + </li> + + <li class="never" data-hits="" data-linenumber="440"> + + + <code class="ruby"><%= erb :common %></code> + </li> + + <li class="never" data-hits="" data-linenumber="441"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="442"> + + + <code class="ruby">function timeout(time, yes, no) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="443"> + + + <code class="ruby"> var timeout = setTimeout(no, time);</code> + </li> + + <li class="never" data-hits="" data-linenumber="444"> + + + <code class="ruby"> onSuccess(function() {</code> + </li> + + <li class="never" data-hits="" data-linenumber="445"> + + + <code class="ruby"> clearTimeout(timeout);</code> + </li> + + <li class="never" data-hits="" data-linenumber="446"> + + + <code class="ruby"> yes()</code> + </li> + + <li class="never" data-hits="" data-linenumber="447"> + + + <code class="ruby"> });</code> + </li> + + <li class="never" data-hits="" data-linenumber="448"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="449"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="450"> + + + <code class="ruby">function onSuccess(callback) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="451"> + + + <code class="ruby"> succeeded ? callback() : callbacks.push(callback)</code> + </li> + + <li class="never" data-hits="" data-linenumber="452"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="453"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="454"> + + + <code class="ruby">function doYouHave(feature, yes, no) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="455"> + + + <code class="ruby"> return function() { feature(yes, no) };</code> + </li> + + <li class="never" data-hits="" data-linenumber="456"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="457"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="458"> + + + <code class="ruby">function yesIndeed(msg, callback) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="459"> + + + <code class="ruby"> return function() {</code> + </li> + + <li class="never" data-hits="" data-linenumber="460"> + + + <code class="ruby"> if(console && console.log) console.log(msg);</code> + </li> + + <li class="never" data-hits="" data-linenumber="461"> + + + <code class="ruby"> return callback();</code> + </li> + + <li class="never" data-hits="" data-linenumber="462"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="463"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="464"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="465"> + + + <code class="ruby">function after(value) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="466"> + + + <code class="ruby"> return value*1000;</code> + </li> + + <li class="never" data-hits="" data-linenumber="467"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="468"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="469"> + + + <code class="ruby">var nopeSorry = yesIndeed;</code> + </li> + + <li class="never" data-hits="" data-linenumber="470"> + + + <code class="ruby">var timeoutes = [];</code> + </li> + + <li class="never" data-hits="" data-linenumber="471"> + + + <code class="ruby">var callbacks = [];</code> + </li> + + <li class="never" data-hits="" data-linenumber="472"> + + + <code class="ruby">var seconds = 1000;</code> + </li> + + <li class="never" data-hits="" data-linenumber="473"> + + + <code class="ruby">var succeeded = false;</code> + </li> + + <li class="never" data-hits="" data-linenumber="474"> + + + <code class="ruby">var popupWindow;</code> + </li> + + <li class="never" data-hits="" data-linenumber="475"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="476"> + + + <code class="ruby">window.addEventListener("message", function(event) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="477"> + + + <code class="ruby"> if(event.data === "done") {</code> + </li> + + <li class="never" data-hits="" data-linenumber="478"> + + + <code class="ruby"> succeeded = true</code> + </li> + + <li class="never" data-hits="" data-linenumber="479"> + + + <code class="ruby"> for(var i = 0; i < callbacks.length; i++) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="480"> + + + <code class="ruby"> (callbacks[i])();</code> + </li> + + <li class="never" data-hits="" data-linenumber="481"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="482"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="483"> + + + <code class="ruby">});</code> + </li> + + <li class="never" data-hits="" data-linenumber="484"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="485"> + + + <code class="ruby">// === READY? GO! ===</code> + </li> + + <li class="never" data-hits="" data-linenumber="486"> + + + <code class="ruby">main();</code> + </li> + + <li class="never" data-hits="" data-linenumber="487"> + + + <code class="ruby"></script></code> + </li> + + <li class="never" data-hits="" data-linenumber="488"> + + + <code class="ruby"></body></code> + </li> + + <li class="never" data-hits="" data-linenumber="489"> + + + <code class="ruby"></html></code> + </li> + + <li class="never" data-hits="" data-linenumber="490"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="491"> + + + <code class="ruby">@@ post_message</code> + </li> + + <li class="never" data-hits="" data-linenumber="492"> + + + <code class="ruby"><script></code> + </li> + + <li class="never" data-hits="" data-linenumber="493"> + + + <code class="ruby"><%= erb :common %></code> + </li> + + <li class="never" data-hits="" data-linenumber="494"> + + + <code class="ruby">function uberParent(win) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="495"> + + + <code class="ruby"> return win.parent === win ? win : uberParent(win.parent);</code> + </li> + + <li class="never" data-hits="" data-linenumber="496"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="497"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="498"> + + + <code class="ruby">function sendPayload(win) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="499"> + + + <code class="ruby"> var payload = {</code> + </li> + + <li class="never" data-hits="" data-linenumber="500"> + + + <code class="ruby"> 'user': <%= user.to_json %>,</code> + </li> + + <li class="never" data-hits="" data-linenumber="501"> + + + <code class="ruby"> 'token': <%= token.inspect %></code> + </li> + + <li class="never" data-hits="" data-linenumber="502"> + + + <code class="ruby"> };</code> + </li> + + <li class="never" data-hits="" data-linenumber="503"> + + + <code class="ruby"> uberParent(win).postMessage(payload, <%= target_origin.inspect %>);</code> + </li> + + <li class="never" data-hits="" data-linenumber="504"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="505"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="506"> + + + <code class="ruby">if(window.parent == window) {</code> + </li> + + <li class="never" data-hits="" data-linenumber="507"> + + + <code class="ruby"> sendPayload(window.opener);</code> + </li> + + <li class="never" data-hits="" data-linenumber="508"> + + + <code class="ruby"> window.close();</code> + </li> + + <li class="never" data-hits="" data-linenumber="509"> + + + <code class="ruby">} else {</code> + </li> + + <li class="never" data-hits="" data-linenumber="510"> + + + <code class="ruby"> tellEveryone('done');</code> + </li> + + <li class="never" data-hits="" data-linenumber="511"> + + + <code class="ruby"> sendPayload(window.parent);</code> + </li> + + <li class="never" data-hits="" data-linenumber="512"> + + + <code class="ruby">}</code> + </li> + + <li class="never" data-hits="" data-linenumber="513"> + + + <code class="ruby"></script></code> + </li> + + <li class="never" data-hits="" data-linenumber="514"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="515"> + + + <code class="ruby">@@ post_payload</code> + </li> + + <li class="never" data-hits="" data-linenumber="516"> + + + <code class="ruby"><body onload='document.forms[0].submit()'></code> + </li> + + <li class="never" data-hits="" data-linenumber="517"> + + + <code class="ruby"> <form action="<%= uri %>" method='post'></code> + </li> + + <li class="never" data-hits="" data-linenumber="518"> + + + <code class="ruby"> <input type='hidden' name='token' value='<%= token %>'></code> + </li> + + <li class="never" data-hits="" data-linenumber="519"> + + + <code class="ruby"> <input type='hidden' name='user' value="<%= user.to_json.gsub('"', '&quot;') %>"></code> + </li> + + <li class="never" data-hits="" data-linenumber="520"> + + + <code class="ruby"> <input type='hidden' name='storage' value='localStorage'></code> + </li> + + <li class="never" data-hits="" data-linenumber="521"> + + + <code class="ruby"> </form></code> + </li> + + <li class="never" data-hits="" data-linenumber="522"> + + + <code class="ruby"></body></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="2b74a2462ad5e4f3ca518f0cc6f13ddc82ee8762"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/branches.rb</h3> + <h4><span class="yellow">83.33 %</span> covered</h4> + <div> + <b>6</b> relevant lines. + <span class="green"><b>5</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Branches < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> get '/' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> respond_with service(:find_branches, params), type: :branches</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> # get '/:owner_name/:name/branches' do # v1</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> # get '/repos/:owner_name/:name/branches' do # v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> # respond_with service(:branches, :find_all, params), type: :branches</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> # end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="f830dba6ed178eb88e884e4ef578db0073e9384a"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/broadcasts.rb</h3> + <h4><span class="yellow">83.33 %</span> covered</h4> + <div> + <b>6</b> relevant lines. + <span class="green"><b>5</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Broadcasts < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> get '/', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> respond_with service(:find_user_broadcasts, params), type: :broadcasts</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="fac69dfa06cb89c53a04099fb945fb4a805cc42c"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/builds.rb</h3> + <h4><span class="red">27.59 %</span> covered</h4> + <div> + <b>29</b> relevant lines. + <span class="green"><b>8</b> lines covered</span> and + <span class="red"><b>21</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Builds < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> get '/' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> prefer_follower do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="8"> + + + <code class="ruby"> name = params[:branches] ? :find_branches : :find_builds</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> params['ids'] = params['ids'].split(',') if params['ids'].respond_to?(:split)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> respond_with service(name, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> get '/:id' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> respond_with service(:find_build, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> post '/:id/cancel' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> Metriks.meter("api.request.cancel_build").mark</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> service = self.service(:cancel_build, params.merge(source: 'api'))</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> if !service.authorized?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> json = { error: {</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> message: "You don't have access to cancel build(#{params[:id]})"</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> } }</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="27"> + + + <code class="ruby"> Metriks.meter("api.request.cancel_build.unauthorized").mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="28"> + + + <code class="ruby"> status 403</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="29"> + + + <code class="ruby"> respond_with json</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> elsif !service.can_cancel?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="31"> + + + <code class="ruby"> json = { error: {</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> message: "The build(#{params[:id]}) can't be canceled",</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> code: 'cant_cancel'</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> } }</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> Metriks.meter("api.request.cancel_build.cant_cancel").mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="37"> + + + <code class="ruby"> status 422</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="38"> + + + <code class="ruby"> respond_with json</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="40"> + + + <code class="ruby"> service.run</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> Metriks.meter("api.request.cancel_build.success").mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> status 204</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="47"> + <span class="hits">1</span> + + <code class="ruby"> post '/:id/restart' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="48"> + + + <code class="ruby"> Metriks.meter("api.request.restart_build").mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> respond_with service(:reset_model, build_id: params[:id])</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="03dcd32988fb710bc7a3c06636a6780bce656589"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/documentation.rb</h3> + <h4><span class="yellow">85.71 %</span> covered</h4> + <div> + <b>7</b> relevant lines. + <span class="green"><b>6</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Documentation < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> set prefix: '/docs'</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> get '/' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> redirect "http://docs.travis-ci.com/api"</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="0dc46adef05fa2cbeadacf05c59276980cc25367"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/endpoints.rb</h3> + <h4><span class="yellow">86.96 %</span> covered</h4> + <div> + <b>23</b> relevant lines. + <span class="green"><b>20</b> lines covered</span> and + <span class="red"><b>3</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'yard/sinatra'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> # Documents all available API endpoints for the currently deployed version.</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> # Text is actually parsed from the source code upon server start.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoints < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> set :endpoints, {}</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> set :setup do</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> endpoint_files = Dir.glob(File.expand_path("../*.rb", __FILE__))</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> YARD::Registry.load(endpoint_files, true)</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> YARD::Sinatra.routes.each do |route|</code> + </li> + + <li class="covered" data-hits="68" data-linenumber="16"> + <span class="hits">68</span> + + <code class="ruby"> namespace = route.namespace</code> + </li> + + <li class="covered" data-hits="68" data-linenumber="17"> + <span class="hits">68</span> + + <code class="ruby"> controller = namespace.to_s.constantize</code> + </li> + + <li class="covered" data-hits="68" data-linenumber="18"> + <span class="hits">68</span> + + <code class="ruby"> route_info = {</code> + </li> + + <li class="covered" data-hits="68" data-linenumber="19"> + <span class="hits">68</span> + + <code class="ruby"> 'uri' => (controller.prefix + route.http_path).gsub('//', '/'),</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> 'verb' => route.http_verb,</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> 'doc' => route.docstring,</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> 'scope' => /scope\W+(\w+)/.match(route.source).try(:[], 1) || controller.default_scope.to_s</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> }</code> + </li> + + <li class="covered" data-hits="68" data-linenumber="24"> + <span class="hits">68</span> + + <code class="ruby"> endpoint = endpoints[controller.prefix] ||= {</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> 'name' => namespace.name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'doc' => namespace.docstring,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'prefix' => controller.prefix,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'routes' => []</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> }</code> + </li> + + <li class="covered" data-hits="68" data-linenumber="30"> + <span class="hits">68</span> + + <code class="ruby"> endpoint['routes'] << route_info</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="18" data-linenumber="33"> + <span class="hits">18</span> + + <code class="ruby"> set :json, endpoints.keys.sort.map { |k| endpoints[k] }.to_json</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="34"> + <span class="hits">18</span> + + <code class="ruby"> endpoints.each_value { |r| r[:json] = r.to_json if r.respond_to? :to_hash }</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> # Lists all available API endpoints by URI prefix.</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> # Values in the resulting array correspond to return values of</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> # [`/endpoints/:prefix`](#/endpoints/:prefix).</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="41"> + <span class="hits">1</span> + + <code class="ruby"> get '/' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> settings.json</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> # Infos about a specific controller.</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> # Example response:</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> # {</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> # name: "Endpoints",</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> # doc: "Documents all available API endpoints...",</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> # prefix: "/endpoints",</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> # routes: [</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> # {</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> # uri: "/endpoints/:prefix",</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> # verb: "GET",</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> # doc: "Infos about...",</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> # scope: "public"</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> # }</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"> # ]</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> # }</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="62"> + <span class="hits">1</span> + + <code class="ruby"> get '/:prefix' do |prefix|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="63"> + + + <code class="ruby"> pass unless endpoint = settings.endpoints["/#{prefix}"]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="64"> + + + <code class="ruby"> endpoint[:json]</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="413ff5b985954d06f57e54bae462c9380050682b"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/env_vars.rb</h3> + <h4><span class="red">44.44 %</span> covered</h4> + <div> + <b>18</b> relevant lines. + <span class="green"><b>8</b> lines covered</span> and + <span class="red"><b>10</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app/endpoint/setting_endpoint'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class EnvVars < SettingsEndpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> define_method(:name) { :env_vars }</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> define_routes!</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def update</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> data = JSON.parse(request.body.read)[singular_name]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> previously_public = record.public?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> record.update(data)</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> # if we update from private to public reset value</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> if !previously_public && record.public? && data['value'].nil?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> record.value = nil</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> if record.valid?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> repo_settings.save</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> respond_with(record, type: singular_name, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="24"> + + + <code class="ruby"> status 422</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="25"> + + + <code class="ruby"> respond_with(record, type: :validation_error, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="f01f22d7534ebd190653ed0f88f71a94320108a3"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/home.rb</h3> + <h4><span class="red">66.67 %</span> covered</h4> + <div> + <b>18</b> relevant lines. + <span class="green"><b>12</b> lines covered</span> and + <span class="red"><b>6</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Home < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> host = Travis.config.client_domain || Travis.config.host</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> fail "Travis.config.client_domain is not set" unless host or test?</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> set :prefix, '/'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> set :client_config,</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> host: host,</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> shorten_host: Travis.config.shorten_host,</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> assets: Travis.config.assets,</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> pusher: (Travis.config.pusher_ws || Travis.config.pusher || {}).to_hash.slice(:scheme, :host, :port, :path, :key),</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> github: { api_url: GH.current.api_host.to_s, scopes: Travis.config.oauth2.try(:scope).to_s.split(?,) }</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> # Landing point. Redirects web browsers to [API documentation](#/docs/).</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> get '/' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> pass if settings.disable_root_endpoint?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> redirect to('/docs/') if request.preferred_type('application/json', 'application/json-home', 'text/html') == 'text/html'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> { 'hello' => 'world' }</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> # Simple endpoints that redirects somewhere else, to make sure we don't</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> # send a referrer.</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> # Parameters:</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> # * **to**: URI to redirect to after handshake.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="30"> + <span class="hits">1</span> + + <code class="ruby"> get '/redirect' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="31"> + + + <code class="ruby"> halt 400 unless params[:to] =~ %r{^https?://}</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="32"> + + + <code class="ruby"> redirect params[:to]</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> # Provides you with system info:</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> # {</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> # config: {</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> # host: "travis-ci.org",</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> # shorten_host: "trvs.io",</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> # pusher: { key: "dd3f11c013317df48b50" },</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"> # assets: {</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> # host: "localhost:3000",</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> # version: "asset-id",</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> # interval: 15</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> # }</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> # }</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> # }</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="49"> + <span class="hits">1</span> + + <code class="ruby"> get '/config' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> { config: settings.client_config }</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="389e755e519bf86618fcf82593746fcedb9c4271"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/hooks.rb</h3> + <h4><span class="red">75.0 %</span> covered</h4> + <div> + <b>8</b> relevant lines. + <span class="green"><b>6</b> lines covered</span> and + <span class="red"><b>2</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Hooks < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> get '/', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> respond_with service(:find_hooks, params), type: :hooks</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> put '/:id?', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> respond_with service(:update_hook, id: params[:id] || params[:hook][:id], active: params[:hook][:active])</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="0c26cbaa8343afc54bde5f948dbae2fe3039c766"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/jobs.rb</h3> + <h4><span class="red">22.73 %</span> covered</h4> + <div> + <b>66</b> relevant lines. + <span class="green"><b>15</b> lines covered</span> and + <span class="red"><b>51</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Jobs < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Helpers::Accept</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> get '/' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> prefer_follower do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> respond_with service(:find_jobs, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> get '/:id' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> job = service(:find_job, params).run</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> if job && job.repository</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> respond_with job</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> json = { error: { message: "The job(#{params[:id]}) couldn't be found" } }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> status 404</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> respond_with json</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> post '/:id/cancel' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="26"> + + + <code class="ruby"> Metriks.meter("api.request.cancel_job").mark</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="28"> + + + <code class="ruby"> service = self.service(:cancel_job, params.merge(source: 'api'))</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="29"> + + + <code class="ruby"> if !service.authorized?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="30"> + + + <code class="ruby"> json = { error: {</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> message: "You don't have access to cancel job(#{params[:id]})"</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> } }</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="34"> + + + <code class="ruby"> Metriks.meter("api.request.cancel_job.unauthorized").mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="35"> + + + <code class="ruby"> status 403</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> respond_with json</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> elsif !service.can_cancel?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="38"> + + + <code class="ruby"> json = { error: {</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> message: "The job(#{params[:id]}) can't be canceled",</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> code: 'cant_cancel'</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> } }</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> Metriks.meter("api.request.cancel_job.cant_cancel").mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="44"> + + + <code class="ruby"> status 422</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="45"> + + + <code class="ruby"> respond_with json</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="47"> + + + <code class="ruby"> service.run</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> Metriks.meter("api.request.cancel_job.success").mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> status 204</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="54"> + <span class="hits">1</span> + + <code class="ruby"> post '/:id/restart' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="55"> + + + <code class="ruby"> Metriks.meter("api.request.restart_job").mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="56"> + + + <code class="ruby"> respond_with service(:reset_model, job_id: params[:id])</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="59"> + <span class="hits">1</span> + + <code class="ruby"> get '/:job_id/log' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="60"> + + + <code class="ruby"> resource = service(:find_log, params).run</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="61"> + + + <code class="ruby"> if (!resource || resource.archived?)</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> # the way we use responders makes it hard to validate proper format</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> # automatically here, so we need to check it explicitly</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="64"> + + + <code class="ruby"> if accepts?('text/plain')</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="65"> + + + <code class="ruby"> archived_log_path = archive_url("/jobs/#{params[:job_id]}/log.txt")</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="67"> + + + <code class="ruby"> if params[:cors_hax]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="68"> + + + <code class="ruby"> status 204</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="69"> + + + <code class="ruby"> headers['Access-Control-Expose-Headers'] = 'Location'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="70"> + + + <code class="ruby"> headers['Location'] = archived_log_path</code> + </li> + + <li class="never" data-hits="" data-linenumber="71"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="72"> + + + <code class="ruby"> redirect archived_log_path, 307</code> + </li> + + <li class="never" data-hits="" data-linenumber="73"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="74"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="75"> + + + <code class="ruby"> status 406</code> + </li> + + <li class="never" data-hits="" data-linenumber="76"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="77"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="78"> + + + <code class="ruby"> respond_with resource</code> + </li> + + <li class="never" data-hits="" data-linenumber="79"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="80"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="81"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="82"> + <span class="hits">1</span> + + <code class="ruby"> patch '/:id/log', scope: :private do |id|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="83"> + + + <code class="ruby"> begin</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="84"> + + + <code class="ruby"> self.service(:remove_log, params).run</code> + </li> + + <li class="never" data-hits="" data-linenumber="85"> + + + <code class="ruby"> rescue Travis::AuthorizationDenied => ade</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="86"> + + + <code class="ruby"> status 401</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="87"> + + + <code class="ruby"> { error: { message: ade.message } }</code> + </li> + + <li class="never" data-hits="" data-linenumber="88"> + + + <code class="ruby"> rescue Travis::JobUnfinished, Travis::LogAlreadyRemoved => e</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="89"> + + + <code class="ruby"> status 409</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="90"> + + + <code class="ruby"> { error: { message: e.message } }</code> + </li> + + <li class="never" data-hits="" data-linenumber="91"> + + + <code class="ruby"> rescue => e</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="92"> + + + <code class="ruby"> status 500</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="93"> + + + <code class="ruby"> { error: { message: "Unexpected error occurred: #{e.message}" } }</code> + </li> + + <li class="never" data-hits="" data-linenumber="94"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="95"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="96"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="97"> + <span class="hits">1</span> + + <code class="ruby"> get "/:job_id/annotations" do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="98"> + + + <code class="ruby"> respond_with service(:find_annotations, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="99"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="100"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="101"> + <span class="hits">1</span> + + <code class="ruby"> post "/:job_id/annotations" do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="102"> + + + <code class="ruby"> if params[:status] && params[:description]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="103"> + + + <code class="ruby"> annotation = service(:update_annotation, params).run</code> + </li> + + <li class="never" data-hits="" data-linenumber="104"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="105"> + + + <code class="ruby"> status annotation ? 204 : 401</code> + </li> + + <li class="never" data-hits="" data-linenumber="106"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="107"> + + + <code class="ruby"> status 422</code> + </li> + + <li class="never" data-hits="" data-linenumber="108"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="109"> + + + <code class="ruby"> { "error" => "Must include status and description" }</code> + </li> + + <li class="never" data-hits="" data-linenumber="110"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="111"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="112"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="113"> + <span class="hits">1</span> + + <code class="ruby"> def archive_url(path)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="114"> + + + <code class="ruby"> "https://s3.amazonaws.com/#{hostname('archive')}#{path}"</code> + </li> + + <li class="never" data-hits="" data-linenumber="115"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="116"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="117"> + <span class="hits">1</span> + + <code class="ruby"> def hostname(name)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="118"> + + + <code class="ruby"> "#{name}#{'-staging' if Travis.env == 'staging'}.#{Travis.config.host.split('.')[-2, 2].join('.')}"</code> + </li> + + <li class="never" data-hits="" data-linenumber="119"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="120"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="121"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="122"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="1d8c0ceda3860fb26fc34a1a770660c35db5b435"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/lint.rb</h3> + <h4><span class="red">61.54 %</span> covered</h4> + <div> + <b>13</b> relevant lines. + <span class="green"><b>8</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/yaml'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class Lint < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> def lint</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="8"> + + + <code class="ruby"> request.body.rewind</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> content = params[:content] || request.body.read</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> parsed = Travis::Yaml.parse(content)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> warnings = parsed.nested_warnings.map { |k, m| { key: k, message: m } }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> { lint: { warnings: warnings } }.to_json</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> post('/', scope: :public) { lint }</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby"> put('/', scope: :public) { lint }</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="5d621a9a5eb87e9eb39a114965b4bc43594c05ee"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/logs.rb</h3> + <h4><span class="yellow">83.33 %</span> covered</h4> + <div> + <b>6</b> relevant lines. + <span class="green"><b>5</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # Logs are generated by builds.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class Logs < Endpoint</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> # Fetches a log by its *id*.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> get '/:id' do |id|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> respond_with service(:find_log, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="41717bfcba400b9bc1a7add2cb84d3195cfc3565"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/repos.rb</h3> + <h4><span class="red">39.71 %</span> covered</h4> + <div> + <b>68</b> relevant lines. + <span class="green"><b>27</b> lines covered</span> and + <span class="red"><b>41</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Repos < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> set :pattern, capture: { id: /\d+/ }</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> # Endpoint for getting all repositories.</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> # You can filter the repositories by adding parameters to the request. For example, you can get all repositories</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> # owned by johndoe by adding `owner_name=johndoe`, or all repositories that johndoe has access to by adding</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> # `member=johndoe`. The parameter names correspond to the keys of the response hash.</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> # ### Response</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> # json(:repositories)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> get '/' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> prefer_follower do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> respond_with service(:find_repos, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> # Gets the repository with the given id.</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> # ### Response</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> # json(:repository)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="28"> + <span class="hits">1</span> + + <code class="ruby"> get '/:id' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="29"> + + + <code class="ruby"> prefer_follower do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="30"> + + + <code class="ruby"> respond_with service(:find_repo, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> # Retrieves repositories for a given owner.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="35"> + <span class="hits">1</span> + + <code class="ruby"> get '/:owner_name' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> prefer_follower do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="37"> + + + <code class="ruby"> respond_with service(:find_repos, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="41"> + <span class="hits">1</span> + + <code class="ruby"> get '/:id/cc' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> respond_with service(:find_repo, params.merge(schema: 'cc'))</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> # Get settings for a given repository</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> #</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="47"> + <span class="hits">1</span> + + <code class="ruby"> get '/:id/settings', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="48"> + + + <code class="ruby"> settings = service(:find_repo_settings, params).run</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> if settings</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> respond_with({ settings: settings.simple_attributes }, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="52"> + + + <code class="ruby"> status 404</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="56"> + <span class="hits">1</span> + + <code class="ruby"> patch '/:id/settings', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="57"> + + + <code class="ruby"> payload = JSON.parse request.body.read</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="59"> + + + <code class="ruby"> if payload['settings'].blank? || !payload['settings'].is_a?(Hash)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="60"> + + + <code class="ruby"> halt 422, { "error" => "Settings must be passed with a request" }</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="63"> + + + <code class="ruby"> settings = service(:find_repo_settings, params).run</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="64"> + + + <code class="ruby"> if settings</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="65"> + + + <code class="ruby"> settings.merge(payload['settings'])</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> # TODO: I would like to have better API here, but leaving this</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> # for testing to not waste too much time before I can play with it</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="68"> + + + <code class="ruby"> if settings.save</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="69"> + + + <code class="ruby"> respond_with({ settings: settings.simple_attributes }, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="70"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="71"> + + + <code class="ruby"> status 422</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="72"> + + + <code class="ruby"> respond_with(settings, type: :validation_error, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="73"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="74"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="75"> + + + <code class="ruby"> status 404</code> + </li> + + <li class="never" data-hits="" data-linenumber="76"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="77"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="78"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="79"> + + + <code class="ruby"> # Get the public key for the repository with the given id.</code> + </li> + + <li class="never" data-hits="" data-linenumber="80"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="81"> + + + <code class="ruby"> # This can be used to encrypt secure variables in the build configuration. See</code> + </li> + + <li class="never" data-hits="" data-linenumber="82"> + + + <code class="ruby"> # [the encryption keys](http://docs.travis-ci.com/user/encryption-keys/) documentation page for more</code> + </li> + + <li class="never" data-hits="" data-linenumber="83"> + + + <code class="ruby"> # information.</code> + </li> + + <li class="never" data-hits="" data-linenumber="84"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="85"> + + + <code class="ruby"> # ### Response</code> + </li> + + <li class="never" data-hits="" data-linenumber="86"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="87"> + + + <code class="ruby"> # json(:repository_key)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="88"> + <span class="hits">1</span> + + <code class="ruby"> get '/:id/key' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="89"> + + + <code class="ruby"> respond_with service(:find_repo_key, params), version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="90"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="91"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="92"> + <span class="hits">1</span> + + <code class="ruby"> post '/:id/key' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="93"> + + + <code class="ruby"> respond_with service(:regenerate_repo_key, params), version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="94"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="95"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="96"> + + + <code class="ruby"> # Gets list of branches</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="97"> + <span class="hits">1</span> + + <code class="ruby"> get '/:repository_id/branches' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="98"> + + + <code class="ruby"> respond_with service(:find_branches, params), type: :branches, version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="99"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="100"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="101"> + + + <code class="ruby"> # Gets lastest build on a branch branches</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="102"> + <span class="hits">1</span> + + <code class="ruby"> get '/:repository_id/branches/:branch' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="103"> + + + <code class="ruby"> respond_with service(:find_branch, params), type: :branch, version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="104"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="105"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="106"> + + + <code class="ruby"> # List caches for a given repo. Can be filtered with `branch` and `match` query parameter.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="107"> + <span class="hits">1</span> + + <code class="ruby"> get '/:repository_id/caches', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="108"> + + + <code class="ruby"> respond_with service(:find_caches, params), type: :caches, version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="109"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="110"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="111"> + + + <code class="ruby"> # Delete caches for a given repo. Can be filtered with `branch` and `match` query parameter.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="112"> + <span class="hits">1</span> + + <code class="ruby"> delete '/:repository_id/caches', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="113"> + + + <code class="ruby"> respond_with service(:delete_caches, params), type: :caches, version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="114"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="115"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="116"> + + + <code class="ruby"> # Gets the repository with the given name.</code> + </li> + + <li class="never" data-hits="" data-linenumber="117"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="118"> + + + <code class="ruby"> # ### Response</code> + </li> + + <li class="never" data-hits="" data-linenumber="119"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="120"> + + + <code class="ruby"> # json(:repository)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="121"> + <span class="hits">1</span> + + <code class="ruby"> get '/:owner_name/:name' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="122"> + + + <code class="ruby"> prefer_follower do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="123"> + + + <code class="ruby"> respond_with service(:find_repo, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="124"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="125"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="126"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="127"> + + + <code class="ruby"> # Gets the builds for the repository with the given name.</code> + </li> + + <li class="never" data-hits="" data-linenumber="128"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="129"> + + + <code class="ruby"> # ### Response</code> + </li> + + <li class="never" data-hits="" data-linenumber="130"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="131"> + + + <code class="ruby"> # json(:builds)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="132"> + <span class="hits">1</span> + + <code class="ruby"> get '/:owner_name/:name/builds' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="133"> + + + <code class="ruby"> name = params[:branches] ? :find_branches : :find_builds</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="134"> + + + <code class="ruby"> params['ids'] = params['ids'].split(',') if params['ids'].respond_to?(:split)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="135"> + + + <code class="ruby"> respond_with service(:find_builds, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="136"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="137"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="138"> + + + <code class="ruby"> # Get a build with the given id in the repository with the given name.</code> + </li> + + <li class="never" data-hits="" data-linenumber="139"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="140"> + + + <code class="ruby"> # ### Response</code> + </li> + + <li class="never" data-hits="" data-linenumber="141"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="142"> + + + <code class="ruby"> # json(:build)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="143"> + <span class="hits">1</span> + + <code class="ruby"> get '/:owner_name/:name/builds/:id' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="144"> + + + <code class="ruby"> respond_with service(:find_build, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="145"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="146"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="147"> + <span class="hits">1</span> + + <code class="ruby"> get '/:owner_name/:name/cc' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="148"> + + + <code class="ruby"> respond_with service(:find_repo, params.merge(schema: 'cc'))</code> + </li> + + <li class="never" data-hits="" data-linenumber="149"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="150"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="151"> + + + <code class="ruby"> # Get the public key for a given repository.</code> + </li> + + <li class="never" data-hits="" data-linenumber="152"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="153"> + + + <code class="ruby"> # This can be used to encrypt secure variables in the build configuration. See</code> + </li> + + <li class="never" data-hits="" data-linenumber="154"> + + + <code class="ruby"> # [the encryption keys](http://docs.travis-ci.com/user/encryption-keys/) documentation page for more</code> + </li> + + <li class="never" data-hits="" data-linenumber="155"> + + + <code class="ruby"> # information.</code> + </li> + + <li class="never" data-hits="" data-linenumber="156"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="157"> + + + <code class="ruby"> # ### Response</code> + </li> + + <li class="never" data-hits="" data-linenumber="158"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="159"> + + + <code class="ruby"> # json(:repository_key)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="160"> + <span class="hits">1</span> + + <code class="ruby"> get '/:owner_name/:name/key' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="161"> + + + <code class="ruby"> respond_with service(:find_repo_key, params), version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="162"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="163"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="164"> + <span class="hits">1</span> + + <code class="ruby"> post '/:owner_name/:name/key' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="165"> + + + <code class="ruby"> respond_with service(:regenerate_repo_key, params), version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="166"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="167"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="168"> + + + <code class="ruby"> # Gets list of branches</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="169"> + <span class="hits">1</span> + + <code class="ruby"> get '/:owner_name/:name/branches' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="170"> + + + <code class="ruby"> respond_with service(:find_branches, params), type: :branches, version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="171"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="172"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="173"> + + + <code class="ruby"> # Gets lastest build on a branch branches</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="174"> + <span class="hits">1</span> + + <code class="ruby"> get '/:owner_name/:name/branches/:branch' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="175"> + + + <code class="ruby"> respond_with service(:find_branch, params), type: :branch, version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="176"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="177"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="178"> + + + <code class="ruby"> # List caches for a given repo. Can be filtered with `branch` and `match` query parameter.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="179"> + <span class="hits">1</span> + + <code class="ruby"> get '/:owner_name/:name/caches', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="180"> + + + <code class="ruby"> respond_with service(:find_caches, params), type: :caches, version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="181"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="182"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="183"> + + + <code class="ruby"> # Delete caches for a given repo. Can be filtered with `branch` and `match` query parameter.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="184"> + <span class="hits">1</span> + + <code class="ruby"> delete '/:owner_name/:name/caches', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="185"> + + + <code class="ruby"> respond_with service(:delete_caches, params), type: :caches, version: :v2</code> + </li> + + <li class="never" data-hits="" data-linenumber="186"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="187"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="188"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="189"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="3542f33a7b8a282ed0436611428aa30ad3f980a1"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/requests.rb</h3> + <h4><span class="red">47.06 %</span> covered</h4> + <div> + <b>17</b> relevant lines. + <span class="green"><b>8</b> lines covered</span> and + <span class="red"><b>9</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app/services/schedule_request'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class Requests < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> post '/', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="8"> + + + <code class="ruby"> if params[:request] && params[:request][:repository]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> respond_with service(:schedule_request, params[:request])</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> else</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> # DEPRECATED: this will be removed by 1st of December</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> Metriks.meter("api.request.restart").mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> respond_with service(:reset_model, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> get '/' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> begin</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> respond_with(service(:find_requests, params).run)</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> rescue Travis::RepositoryNotFoundError => e</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> status 404</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> { "error" => "Repository could not be found" }</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="26"> + <span class="hits">1</span> + + <code class="ruby"> get '/:id' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="27"> + + + <code class="ruby"> respond_with service(:find_request, params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="b615d4751e9fd711ed50e22c4b49c7c51f964d93"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/setting_endpoint.rb</h3> + <h4><span class="red">52.73 %</span> covered</h4> + <div> + <b>55</b> relevant lines. + <span class="green"><b>29</b> lines covered</span> and + <span class="red"><b>26</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class SettingsEndpoint < Endpoint</code> + </li> + + <li class="covered" data-hits="66" data-linenumber="5"> + <span class="hits">66</span> + + <code class="ruby"> set(:prefix) { "/settings/" << name[/[^:]+$/].underscore }</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> class << self</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> # This method checks if class based on a given name exists or creates</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> # a new SettingsEndpoint subclass, which will be then used as an endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def subclass(name)</code> + </li> + + <li class="covered" data-hits="54" data-linenumber="11"> + <span class="hits">54</span> + + <code class="ruby"> class_name = name.to_s.camelize</code> + </li> + + <li class="covered" data-hits="54" data-linenumber="12"> + <span class="hits">54</span> + + <code class="ruby"> if Travis::Api::App::Endpoint.const_defined?(class_name)</code> + </li> + + <li class="covered" data-hits="53" data-linenumber="13"> + <span class="hits">53</span> + + <code class="ruby"> Travis::Api::App::Endpoint.const_get(class_name)</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> else</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> klass = create_settings_class(name)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby"> Travis::Api::App::Endpoint.const_set(class_name, klass)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> klass</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> def create_settings_class(name)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> klass = Class.new(self) do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> define_method(:name) { name }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="24"> + + + <code class="ruby"> define_routes!</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="28"> + <span class="hits">1</span> + + <code class="ruby"> def define_routes!</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="29"> + <span class="hits">1</span> + + <code class="ruby"> get("/", scope: :private) do index end</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="30"> + <span class="hits">1</span> + + <code class="ruby"> get("/:id", scope: :private) do show end</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="31"> + <span class="hits">1</span> + + <code class="ruby"> post("/", scope: :private) do create end</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="32"> + <span class="hits">1</span> + + <code class="ruby"> patch("/:id", scope: :private) do update end</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="33"> + <span class="hits">1</span> + + <code class="ruby"> delete("/:id", scope: :private) do destroy end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> # Rails style methods for easy overriding</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="38"> + <span class="hits">1</span> + + <code class="ruby"> def index</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="39"> + + + <code class="ruby"> respond_with(collection, type: name, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="42"> + <span class="hits">1</span> + + <code class="ruby"> def show</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> respond_with(record, type: singular_name, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="46"> + <span class="hits">1</span> + + <code class="ruby"> def update</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="47"> + + + <code class="ruby"> record.update(JSON.parse(request.body.read)[singular_name])</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="48"> + + + <code class="ruby"> if record.valid?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> repo_settings.save</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> respond_with(record, type: singular_name, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="52"> + + + <code class="ruby"> status 422</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="53"> + + + <code class="ruby"> respond_with(record, type: :validation_error, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="57"> + <span class="hits">1</span> + + <code class="ruby"> def create</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="58"> + + + <code class="ruby"> record = collection.create(JSON.parse(request.body.read)[singular_name])</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="59"> + + + <code class="ruby"> if record.valid?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="60"> + + + <code class="ruby"> repo_settings.save</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="61"> + + + <code class="ruby"> respond_with(record, type: singular_name, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="63"> + + + <code class="ruby"> status 422</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="64"> + + + <code class="ruby"> respond_with(record, type: :validation_error, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="68"> + <span class="hits">1</span> + + <code class="ruby"> def destroy</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="69"> + + + <code class="ruby"> record = collection.destroy(params[:id]) || record_not_found</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="70"> + + + <code class="ruby"> repo_settings.save</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="71"> + + + <code class="ruby"> respond_with(record, type: singular_name, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="72"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="73"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="74"> + <span class="hits">1</span> + + <code class="ruby"> def singular_name</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="75"> + + + <code class="ruby"> name.to_s.singularize</code> + </li> + + <li class="never" data-hits="" data-linenumber="76"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="77"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="78"> + <span class="hits">1</span> + + <code class="ruby"> def collection</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="79"> + + + <code class="ruby"> @collection ||= repo_settings.send(name)</code> + </li> + + <li class="never" data-hits="" data-linenumber="80"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="81"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="82"> + + + <code class="ruby"> # This method can't be called "settings" because it clashes with</code> + </li> + + <li class="never" data-hits="" data-linenumber="83"> + + + <code class="ruby"> # Sinatra's method</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="84"> + <span class="hits">1</span> + + <code class="ruby"> def repo_settings</code> + </li> + + <li class="never" data-hits="" data-linenumber="85"> + + + <code class="ruby"> @settings ||= begin</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="86"> + + + <code class="ruby"> service(:find_repo_settings, id: params['repository_id'].to_i).run</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="87"> + + + <code class="ruby"> end || halt(404, error: "Couldn't find repository")</code> + </li> + + <li class="never" data-hits="" data-linenumber="88"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="89"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="90"> + <span class="hits">1</span> + + <code class="ruby"> def record</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="91"> + + + <code class="ruby"> collection.find(params[:id]) || record_not_found</code> + </li> + + <li class="never" data-hits="" data-linenumber="92"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="93"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="94"> + <span class="hits">1</span> + + <code class="ruby"> def record_not_found</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="95"> + + + <code class="ruby"> halt(404, { error: "Could not find a requested setting" })</code> + </li> + + <li class="never" data-hits="" data-linenumber="96"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="97"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="98"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="c146923d5484592bc716b1adae4f3329fd9ebb1b"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/singleton_settings_endpoint.rb</h3> + <h4><span class="red">57.14 %</span> covered</h4> + <div> + <b>28</b> relevant lines. + <span class="green"><b>16</b> lines covered</span> and + <span class="red"><b>12</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app/endpoint/setting_endpoint'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class SingletonSettingsEndpoint < SettingsEndpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class << self</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> def create_settings_class(name)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> klass = Class.new(self) do</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> define_method(:name) { name }</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> get("/:repository_id", scope: :private) do show end</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> patch("/:repository_id", scope: :private) do update end</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> delete("/:repository_id", scope: :private) do destroy end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> def update</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> record = parent.update(name, JSON.parse(request.body.read)[singular_name])</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> if record.valid?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> repo_settings.save</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> respond_with(record, type: singular_name, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> status 422</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="24"> + + + <code class="ruby"> respond_with(record, type: :validation_error, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="28"> + <span class="hits">1</span> + + <code class="ruby"> def destroy</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="29"> + + + <code class="ruby"> record = parent.delete(name)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="30"> + + + <code class="ruby"> repo_settings.save</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="31"> + + + <code class="ruby"> respond_with(record, type: singular_name, version: :v2)</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="34"> + <span class="hits">1</span> + + <code class="ruby"> def record</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="35"> + + + <code class="ruby"> parent.get(name) || record_not_found</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="38"> + <span class="hits">1</span> + + <code class="ruby"> def parent</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="39"> + + + <code class="ruby"> repo_settings</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="42"> + <span class="hits">1</span> + + <code class="ruby"> def record_not_found</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> halt(404, { error: "Could not find a requested setting" })</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="3aa4c3de70a6e7203940667017613935754e19cd"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/uptime.rb</h3> + <h4><span class="red">55.56 %</span> covered</h4> + <div> + <b>9</b> relevant lines. + <span class="green"><b>5</b> lines covered</span> and + <span class="red"><b>4</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Uptime < Endpoint</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> get '/' do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> begin</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="8"> + + + <code class="ruby"> ActiveRecord::Base.connection.execute('select 1')</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> [200, "OK"]</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> rescue Exception => e</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> return [500, "Error: #{e.message}"]</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="2aeec642e9353983d22c25e11bb6aee7a68ff327"> + <div class="header"> + <h3>lib/travis/api/app/endpoint/users.rb</h3> + <h4><span class="red">50.0 %</span> covered</h4> + <div> + <b>18</b> relevant lines. + <span class="green"><b>9</b> lines covered</span> and + <span class="red"><b>9</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Endpoint</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # TODO should this be /profile?</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class Users < Endpoint</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> # Gives information about the currently logged in user.</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> # Example:</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> # {</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> # "user": {</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> # "name": "Sven Fuchs",</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> # "login": "svenfuchs",</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> # "email": "svenfuchs@artweb-design.de",</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> # "gravatar_id": "402602a60e500e85f2f5dc1ff3648ecb",</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> # "locale": "de",</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> # "is_syncing": false,</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> # "synced_at": "2012-08-14T22:11:21Z"</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> # }</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> # }</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby"> get '/', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> respond_with current_user</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="26"> + <span class="hits">1</span> + + <code class="ruby"> get '/permissions', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="27"> + + + <code class="ruby"> respond_with service(:find_user_permissions), type: :permissions</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> # TODO fix url/key generation in ember-data</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> # get '/accounts', scope: :private do</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> # respond_with service(:users, :find_accounts), type: :accounts</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> # end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> # TODO fix url/key generation in ember-data</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> # get '/broadcasts', scope: :private do</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> # respond_with service(:users, :find_broadcasts), type: :broadcasts</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> # end</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="40"> + <span class="hits">1</span> + + <code class="ruby"> get '/:id', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="41"> + + + <code class="ruby"> pass unless current_user.id.to_s == params[:id]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> respond_with current_user</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="45"> + <span class="hits">1</span> + + <code class="ruby"> put '/:id?', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="46"> + + + <code class="ruby"> respond_with service(:update_user, params[:user])</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="49"> + <span class="hits">1</span> + + <code class="ruby"> post '/sync', scope: :private do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> if current_user.syncing?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="51"> + + + <code class="ruby"> status 409</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="52"> + + + <code class="ruby"> { 'message' => "Sync already in progress. Try again later." }</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="54"> + + + <code class="ruby"> respond_with service(:sync_user)</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="98cb249669c6e20fed930c4f814f8e6266add77c"> + <div class="header"> + <h3>lib/travis/api/app/extensions.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>4</b> relevant lines. + <span class="green"><b>4</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"> # Namespace for Sinatra extensions.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module Extensions</code> + </li> + + <li class="covered" data-hits="5" data-linenumber="6"> + <span class="hits">5</span> + + <code class="ruby"> Dir.glob("#{__dir__}/extensions/*.rb").each { |f| require f[%r[(?<=lib/).+(?=\.rb$)]] }</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="00c3504cff5eca9f25748185fb2bd47ad1755d92"> + <div class="header"> + <h3>lib/travis/api/app/extensions/expose_pattern.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>7</b> relevant lines. + <span class="green"><b>7</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Extensions</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module ExposePattern</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def route(verb, path, *)</code> + </li> + + <li class="covered" data-hits="119" data-linenumber="7"> + <span class="hits">119</span> + + <code class="ruby"> condition { headers('X-Endpoint' => settings.name.to_s, 'X-Pattern' => path.to_s) }</code> + </li> + + <li class="covered" data-hits="119" data-linenumber="8"> + <span class="hits">119</span> + + <code class="ruby"> super</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="cf7268e37e643b00ddda6c99c2b8d2601a66df25"> + <div class="header"> + <h3>lib/travis/api/app/extensions/scoping.rb</h3> + <h4><span class="red">41.03 %</span> covered</h4> + <div> + <b>39</b> relevant lines. + <span class="green"><b>16</b> lines covered</span> and + <span class="red"><b>23</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Extensions</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module Scoping</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> module Helpers</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> def scope</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="8"> + + + <code class="ruby"> env['travis.scope'].to_sym</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> def public?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> scope == :public</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def required_params_match?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> return true unless token = env['travis.access_token']</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> if token.extra && (required_params = token.extra['required_params'])</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> required_params.all? { |name, value| params[name] == value }</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> true</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="26"> + <span class="hits">1</span> + + <code class="ruby"> def self.registered(app)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="27"> + <span class="hits">1</span> + + <code class="ruby"> app.set default_scope: :public, anonymous_scopes: [:public]</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="28"> + <span class="hits">1</span> + + <code class="ruby"> app.helpers(Helpers)</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="31"> + <span class="hits">1</span> + + <code class="ruby"> def scope(*names)</code> + </li> + + <li class="covered" data-hits="118" data-linenumber="32"> + <span class="hits">118</span> + + <code class="ruby"> condition do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="33"> + + + <code class="ruby"> names = [settings.default_scope] if names == [:default]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="34"> + + + <code class="ruby"> scopes = env['travis.access_token'].try(:scopes) || settings.anonymous_scopes</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> result = names.any? do |name|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="37"> + + + <code class="ruby"> if scopes.include?(name) && required_params_match?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="38"> + + + <code class="ruby"> headers['X-OAuth-Scopes'] = scopes.map(&:to_s).join(',')</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="39"> + + + <code class="ruby"> headers['X-Accepted-OAuth-Scopes'] = name.to_s</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="41"> + + + <code class="ruby"> env['travis.scope'] = name</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> headers['Vary'] = 'Accept'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> headers['Vary'] << ', Authorization' unless public?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="44"> + + + <code class="ruby"> true</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="48"> + + + <code class="ruby"> if !result</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> headers['X-OAuth-Scopes'] = scopes.map(&:to_s).join(',')</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> headers['X-Accepted-OAuth-Scopes'] = names.first.to_s</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="52"> + + + <code class="ruby"> if env['travis.access_token']</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="53"> + + + <code class="ruby"> pass { halt 403, "insufficient access" }</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="55"> + + + <code class="ruby"> pass { halt 401, "no access token supplied" }</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="59"> + + + <code class="ruby"> result</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="63"> + <span class="hits">1</span> + + <code class="ruby"> def route(verb, path, options = {}, &block)</code> + </li> + + <li class="covered" data-hits="118" data-linenumber="64"> + <span class="hits">118</span> + + <code class="ruby"> options[:scope] ||= :default</code> + </li> + + <li class="covered" data-hits="118" data-linenumber="65"> + <span class="hits">118</span> + + <code class="ruby"> super(verb, path, options, &block)</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="69"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="4afdb495e463d11449413cb7fabf94f05a66ff88"> + <div class="header"> + <h3>lib/travis/api/app/extensions/smart_constants.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>11</b> relevant lines. + <span class="green"><b>11</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Extensions</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # Allows writing</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> # helpers :some_helper</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> # Instead of</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> #</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> # helpers Travis::Api::App::Helpers::SomeHelper</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> module SmartConstants</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def helpers(*list, &block)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="14"> + <span class="hits">4</span> + + <code class="ruby"> super(*resolve_constants(list, Helpers), &block)</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> def register(*list, &block)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="18"> + <span class="hits">4</span> + + <code class="ruby"> super(*resolve_constants(list, Extensions), &block)</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> def resolve_constants(list, namespace)</code> + </li> + + <li class="covered" data-hits="20" data-linenumber="24"> + <span class="hits">20</span> + + <code class="ruby"> list.map { |e| Symbol === e ? namespace.const_get(e.to_s.camelize) : e }</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="32932af295b8d816c57702d2dd3215d03df46d91"> + <div class="header"> + <h3>lib/travis/api/app/extensions/subclass_tracker.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>13</b> relevant lines. + <span class="green"><b>13</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Extensions</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # Keeps track of subclasses. Used for endpoint and middleware detection.</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> # This will prevent garbage collection of subclasses.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> module SubclassTracker</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def direct_subclasses</code> + </li> + + <li class="covered" data-hits="707" data-linenumber="9"> + <span class="hits">707</span> + + <code class="ruby"> @direct_subclasses ||= []</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> # List of "leaf" subclasses (ie subclasses without subclasses).</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def subclasses</code> + </li> + + <li class="covered" data-hits="594" data-linenumber="14"> + <span class="hits">594</span> + + <code class="ruby"> return [self] if direct_subclasses.empty?</code> + </li> + + <li class="covered" data-hits="85" data-linenumber="15"> + <span class="hits">85</span> + + <code class="ruby"> direct_subclasses.map(&:subclasses).flatten.uniq</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> def inherited(subclass)</code> + </li> + + <li class="covered" data-hits="28" data-linenumber="19"> + <span class="hits">28</span> + + <code class="ruby"> super</code> + </li> + + <li class="covered" data-hits="28" data-linenumber="20"> + <span class="hits">28</span> + + <code class="ruby"> subclass.set app_file: caller_files.first</code> + </li> + + <li class="covered" data-hits="28" data-linenumber="21"> + <span class="hits">28</span> + + <code class="ruby"> direct_subclasses << subclass</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="3583b3399a71ebe7de3f253f8a6a166b5ff1450d"> + <div class="header"> + <h3>lib/travis/api/app/helpers.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>4</b> relevant lines. + <span class="green"><b>4</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"> # Namespace for helpers.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module Helpers</code> + </li> + + <li class="covered" data-hits="7" data-linenumber="6"> + <span class="hits">7</span> + + <code class="ruby"> Dir.glob("#{__dir__}/helpers/*.rb").each { |f| require f[%r[(?<=lib/).+(?=\.rb$)]] }</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="d434ebb9387430acf5e4c2c6adda113f213d9a27"> + <div class="header"> + <h3>lib/travis/api/app/helpers/accept.rb</h3> + <h4><span class="red">49.06 %</span> covered</h4> + <div> + <b>53</b> relevant lines. + <span class="green"><b>26</b> lines covered</span> and + <span class="red"><b>27</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Helpers</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module Accept</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> HEADER_FORMAT = /vnd\.travis-ci\.(\d+)\+(\w+)/</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> DEFAULT_VERSION = 'v1'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> DEFAULT_FORMAT = 'json'</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> class Entry</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> SEPARATORS = Regexp.escape("()<>@,;:\/[]?={}\t ")</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> TOKEN = /[^#{SEPARATORS}]+/</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :type, :subtype, :quality, :version, :params</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(accept_string)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> @type, @subtype, @quality, @version, @params = parse(accept_string)</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> def <=>(other)</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> [1 - quality, mime_type.count('*'), 1 - params.size] <=></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> [1 - other.quality, other.mime_type.count('*'), 1 - other.params.size]</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> def mime_type</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="24"> + + + <code class="ruby"> "#{type}/#{subtype}"</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="27"> + <span class="hits">1</span> + + <code class="ruby"> def version</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="28"> + + + <code class="ruby"> version = @version || params['version']</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="29"> + + + <code class="ruby"> version ? "v#{version}" : nil</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="32"> + <span class="hits">1</span> + + <code class="ruby"> def accepts?(mime_type)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="33"> + + + <code class="ruby"> return true if self.mime_type == '*/*'</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="35"> + + + <code class="ruby"> type, subtype = mime_type.scan(%r{(#{TOKEN})/(#{TOKEN})}).flatten</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> type == self.type && (self.subtype == '*' || subtype == self.subtype)</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="39"> + <span class="hits">1</span> + + <code class="ruby"> def to_s</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="40"> + + + <code class="ruby"> str = "#{mime_type}; q=#{quality}"</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="41"> + + + <code class="ruby"> str << "; #{params.map { |k,v| "#{k}=#{v}" }.join('; ')}" if params.length > 0</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> str</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="45"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="46"> + <span class="hits">1</span> + + <code class="ruby"> def parse(str)</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> # this handles only subset of what Accept header can</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> # contain, only the simplest cases, no quoted strings etc.</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> type, subtype, params = str.scan(%r{(#{TOKEN})/(#{TOKEN})(.*)}).flatten</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> quality = 1</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="52"> + + + <code class="ruby"> version = nil</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="53"> + + + <code class="ruby"> if params</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="54"> + + + <code class="ruby"> params = Hash[*params.split(';').map { |p| p.scan /(#{TOKEN})=(#{TOKEN})/ }.flatten]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="55"> + + + <code class="ruby"> quality = params.delete('q').to_f if params['q']</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="58"> + + + <code class="ruby"> if subtype =~ HEADER_FORMAT</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="59"> + + + <code class="ruby"> subtype = $2</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="60"> + + + <code class="ruby"> version = $1</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="63"> + + + <code class="ruby"> [type, subtype, quality, version, params]</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="67"> + <span class="hits">1</span> + + <code class="ruby"> def accepts?(mime_type)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="68"> + + + <code class="ruby"> accept_entries.any? { |e| e.accepts?(mime_type) }</code> + </li> + + <li class="never" data-hits="" data-linenumber="69"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="70"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="71"> + <span class="hits">1</span> + + <code class="ruby"> def accept_entries</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="72"> + + + <code class="ruby"> entries = env['HTTP_ACCEPT'].to_s.delete(' ').to_s.split(',').map { |e| Entry.new(e) }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="73"> + + + <code class="ruby"> entries.empty? ? [Entry.new('*/*')] : entries.sort</code> + </li> + + <li class="never" data-hits="" data-linenumber="74"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="75"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="76"> + <span class="hits">1</span> + + <code class="ruby"> def acceptable_formats</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="77"> + + + <code class="ruby"> if format = env['travis.format_from_path']</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="78"> + + + <code class="ruby"> [Entry.new(Rack::Mime.mime_type(".#{format}"))]</code> + </li> + + <li class="never" data-hits="" data-linenumber="79"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="80"> + + + <code class="ruby"> accept_entries</code> + </li> + + <li class="never" data-hits="" data-linenumber="81"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="82"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="83"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="84"> + <span class="hits">1</span> + + <code class="ruby"> def accept_version</code> + </li> + + <li class="covered" data-hits="43" data-linenumber="85"> + <span class="hits">43</span> + + <code class="ruby"> @accept_version ||= request.accept.join =~ HEADER_FORMAT && "v#{$1}" || DEFAULT_VERSION</code> + </li> + + <li class="never" data-hits="" data-linenumber="86"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="87"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="88"> + <span class="hits">1</span> + + <code class="ruby"> def accept_format</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="89"> + <span class="hits">10</span> + + <code class="ruby"> @accept_format ||= request.accept.join =~ HEADER_FORMAT && $2 || DEFAULT_FORMAT</code> + </li> + + <li class="never" data-hits="" data-linenumber="90"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="91"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="92"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="93"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="945fc5424b8698f6c9f47bf45d950c7993fe7f7d"> + <div class="header"> + <h3>lib/travis/api/app/helpers/current_user.rb</h3> + <h4><span class="red">70.0 %</span> covered</h4> + <div> + <b>10</b> relevant lines. + <span class="green"><b>7</b> lines covered</span> and + <span class="red"><b>3</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Helpers</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module CurrentUser</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def current_user</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> access_token.user if signed_in?</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def access_token</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> env['travis.access_token']</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def signed_in?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> !!access_token</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="d6d6177d6e0d49294315541845ceb6265759cdf1"> + <div class="header"> + <h3>lib/travis/api/app/helpers/db_follower.rb</h3> + <h4><span class="yellow">83.33 %</span> covered</h4> + <div> + <b>6</b> relevant lines. + <span class="green"><b>5</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Helpers</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module DbFollower</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def prefer_follower</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> yield</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="9b6cc591941ba41c4e94fefe940858e3353c284f"> + <div class="header"> + <h3>lib/travis/api/app/helpers/flash.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>6</b> relevant lines. + <span class="green"><b>6</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Helpers</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module Flash</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def flash</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="7"> + <span class="hits">10</span> + + <code class="ruby"> @flash ||= []</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="4bc54455bbe2ec43bb23f5b569a91e4d444598b6"> + <div class="header"> + <h3>lib/travis/api/app/helpers/mime_types.rb</h3> + <h4><span class="red">64.29 %</span> covered</h4> + <div> + <b>14</b> relevant lines. + <span class="green"><b>9</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Helpers</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module MimeTypes</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def html?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> request.accept =~ %r(text/html)</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def json?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> request.accept =~ %r(application/json)</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def xml?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> request.accept =~ %r(application/xml)</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> def png?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> request.accept =~ %r(image/png)</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby"> def atom?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> request.accept =~ %r(application/atom+xml)</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="e5ee14c5580baf7a66bac731983db9d3bdb48996"> + <div class="header"> + <h3>lib/travis/api/app/helpers/respond_with.rb</h3> + <h4><span class="red">40.54 %</span> covered</h4> + <div> + <b>37</b> relevant lines. + <span class="green"><b>15</b> lines covered</span> and + <span class="red"><b>22</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Helpers</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # Allows routes to return either hashes or anything Travis::API.data can</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> # convert (in addition to the return values supported by Sinatra, of</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> # course). These values will be encoded in JSON.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> module RespondWith</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> include Accept</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> STATUS = {</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> success: 200,</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> not_found: 404</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby"> def respond_with(resource, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> result = respond(resource, options)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> if result && response.content_type =~ /application\/json/</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> status STATUS[result[:result]] if result.is_a?(Hash) && result[:result].is_a?(Symbol)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> result = prettify_result? ? JSON.pretty_generate(result) : result.to_json</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> halt result || 404</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> def body(value = nil, options = {}, &block)</code> + </li> + + <li class="covered" data-hits="40" data-linenumber="26"> + <span class="hits">40</span> + + <code class="ruby"> value = value.to_json if value.is_a?(Hash)</code> + </li> + + <li class="covered" data-hits="40" data-linenumber="27"> + <span class="hits">40</span> + + <code class="ruby"> super(value, &block)</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="30"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="32"> + <span class="hits">1</span> + + <code class="ruby"> def respond(resource, options)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="33"> + + + <code class="ruby"> resource = apply_service_responder(resource, options)</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="35"> + + + <code class="ruby"> response = nil</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> acceptable_formats.find do |accept|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="37"> + + + <code class="ruby"> responders(resource, options).find do |const|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="38"> + + + <code class="ruby"> responder = const.new(self, resource, options.dup.merge(accept: accept))</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="39"> + + + <code class="ruby"> response = responder.apply if responder.apply?</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> if responders = options[:responders]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="44"> + + + <code class="ruby"> responders.each do |klass|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="45"> + + + <code class="ruby"> responder = klass.new(self, response, options)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="46"> + + + <code class="ruby"> response = responder.apply if responder.apply?</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> response || (resource ? error(406) : error(404))</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="53"> + <span class="hits">1</span> + + <code class="ruby"> def prettify_result?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="54"> + + + <code class="ruby"> !params[:pretty].nil? && (params[:pretty].downcase == 'true' || params[:pretty].to_i > 0)</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="57"> + <span class="hits">1</span> + + <code class="ruby"> def apply_service_responder(resource, options)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="58"> + + + <code class="ruby"> responder = Responders::Service.new(self, resource, options)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="59"> + + + <code class="ruby"> resource = responder.apply if responder.apply?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="60"> + + + <code class="ruby"> resource</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="63"> + <span class="hits">1</span> + + <code class="ruby"> def responders(resource, options)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="64"> + + + <code class="ruby"> [:Json, :Atom, :Image, :Xml, :Plain, :Badge].map do |name|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="65"> + + + <code class="ruby"> Responders.const_get(name)</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="69"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="70"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="abcb6fbe07ff5db52c5716e39eb648ef96550296"> + <div class="header"> + <h3>lib/travis/api/app/middleware.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>3</b> relevant lines. + <span class="green"><b>3</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"> # Superclass for all middleware.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Middleware < Base</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="fafd069a2bcef83fff5f536d88402c883f3cdc31"> + <div class="header"> + <h3>lib/travis/api/app/middleware/logging.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>8</b> relevant lines. + <span class="green"><b>8</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Middleware</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # Makes sure we use Travis.logger everywhere.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class Logging < Middleware</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="7"> + <span class="hits">2</span> + + <code class="ruby"> set(:setup) { ActiveRecord::Base.logger = Travis.logger }</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> before do</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="10"> + <span class="hits">23</span> + + <code class="ruby"> env['rack.logger'] = Travis.logger</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="11"> + <span class="hits">23</span> + + <code class="ruby"> env['rack.errors'] = Travis.logger.instance_variable_get(:@logdev).dev rescue nil</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="7670839fd3d16bec4a807509898851298c771968"> + <div class="header"> + <h3>lib/travis/api/app/middleware/metriks.rb</h3> + <h4><span class="red">77.42 %</span> covered</h4> + <div> + <b>31</b> relevant lines. + <span class="green"><b>24</b> lines covered</span> and + <span class="red"><b>7</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'metriks'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Middleware</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class Metriks < Middleware</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> include Helpers::Accept</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> before do</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="10"> + <span class="hits">23</span> + + <code class="ruby"> env['metriks.request.start'] ||= Time.now.utc</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> after do</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="14"> + <span class="hits">23</span> + + <code class="ruby"> if queue_start = time(env['HTTP_X_QUEUE_START']) || time(env['HTTP_X_REQUEST_START'])</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> time = env['metriks.request.start'] - queue_start</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> ::Metriks.timer('api.request_queue').update(time)</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="23" data-linenumber="19"> + <span class="hits">23</span> + + <code class="ruby"> if response.status < 400</code> + </li> + + <li class="covered" data-hits="13" data-linenumber="20"> + <span class="hits">13</span> + + <code class="ruby"> time = Time.now.utc - env['metriks.request.start']</code> + </li> + + <li class="covered" data-hits="13" data-linenumber="21"> + <span class="hits">13</span> + + <code class="ruby"> if headers['X-Pattern'].present? and headers['X-Endpoint'].present?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> name = "#{(headers['X-Endpoint'].split("::", 5).last.gsub(/::/, ".")).downcase}#{headers['X-Pattern'].gsub(/[\/]/, '.').gsub(/[:\?\*]/, "_")}"</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> metric = "api.request.endpoint.#{name}"</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="24"> + + + <code class="ruby"> ::Metriks.timer(metric).update(time)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="25"> + + + <code class="ruby"> ::Metriks.timer('api.requests').update(time)</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="covered" data-hits="13" data-linenumber="27"> + <span class="hits">13</span> + + <code class="ruby"> if content_type.present?</code> + </li> + + <li class="covered" data-hits="13" data-linenumber="28"> + <span class="hits">13</span> + + <code class="ruby"> type = content_type.split(';', 2).first.to_s.gsub(/\s/,'').gsub(/[^A-z\/]+/, '_').gsub('/', '.')</code> + </li> + + <li class="covered" data-hits="13" data-linenumber="29"> + <span class="hits">13</span> + + <code class="ruby"> ::Metriks.timer("api.request.content_type.#{type}").update(time)</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="31"> + + + <code class="ruby"> ::Metriks.timer("api.request.content_type.none").update(time)</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="covered" data-hits="13" data-linenumber="33"> + <span class="hits">13</span> + + <code class="ruby"> ::Metriks.meter("api.request.#{request.request_method.downcase}").mark</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="23" data-linenumber="36"> + <span class="hits">23</span> + + <code class="ruby"> ::Metriks.meter("api.request.status.#{response.status.to_s[0]}").mark</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="37"> + <span class="hits">23</span> + + <code class="ruby"> ::Metriks.meter("api.request.version.#{accept_version}").mark</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="40"> + <span class="hits">1</span> + + <code class="ruby"> def time(value)</code> + </li> + + <li class="covered" data-hits="46" data-linenumber="41"> + <span class="hits">46</span> + + <code class="ruby"> value = value.to_f</code> + </li> + + <li class="covered" data-hits="46" data-linenumber="42"> + <span class="hits">46</span> + + <code class="ruby"> start = env['metriks.request.start'].to_f</code> + </li> + + <li class="covered" data-hits="46" data-linenumber="43"> + <span class="hits">46</span> + + <code class="ruby"> value /= 1000 while value > start</code> + </li> + + <li class="covered" data-hits="46" data-linenumber="44"> + <span class="hits">46</span> + + <code class="ruby"> Time.at(value) if value > 946684800</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="fe2923d329420298ae0fb9e1101c22a8b601d151"> + <div class="header"> + <h3>lib/travis/api/app/middleware/rewrite.rb</h3> + <h4><span class="red">78.57 %</span> covered</h4> + <div> + <b>42</b> relevant lines. + <span class="green"><b>33</b> lines covered</span> and + <span class="red"><b>9</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Middleware</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Rewrite < Middleware</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> FORMAT = %r(\.(json|xml|png|txt|atom|svg)$)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> V1_REPO_URL = %r(^(/[^/]+/[^/]+(?:/builds(?:/[\d]+)?|/cc)?)$)</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> helpers :accept</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="2" data-linenumber="11"> + <span class="hits">2</span> + + <code class="ruby"> set(:setup) { ActiveRecord::Base.logger = Travis.logger }</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> before do</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="14"> + <span class="hits">10</span> + + <code class="ruby"> extract_format</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="15"> + <span class="hits">10</span> + + <code class="ruby"> rewrite_v1_repo_segment if v1? || xml?</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="16"> + <span class="hits">10</span> + + <code class="ruby"> rewrite_v1_named_repo_image_path if png? || svg?</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby"> after do</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="20"> + <span class="hits">10</span> + + <code class="ruby"> redirect_v1_named_repo_path if (v1? || xml?) && not_found?</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> def extract_format</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="26"> + <span class="hits">10</span> + + <code class="ruby"> env['PATH_INFO'].sub!(FORMAT, '')</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="27"> + <span class="hits">10</span> + + <code class="ruby"> env['travis.format_from_path'] = $1</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="28"> + <span class="hits">10</span> + + <code class="ruby"> env['travis.format'] = $1 || accept_format</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="31"> + <span class="hits">1</span> + + <code class="ruby"> def rewrite_v1_repo_segment</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="32"> + <span class="hits">10</span> + + <code class="ruby"> env['PATH_INFO'].sub!(%r(^/repositories), '/repos')</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="35"> + <span class="hits">1</span> + + <code class="ruby"> def rewrite_v1_named_repo_image_path</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> env['PATH_INFO'].sub!(V1_REPO_URL) { "/repos#{$1}" }</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="39"> + <span class="hits">1</span> + + <code class="ruby"> def redirect_v1_named_repo_path</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="40"> + <span class="hits">10</span> + + <code class="ruby"> if request.path =~ V1_REPO_URL</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="41"> + + + <code class="ruby"> force_redirect("/repositories#{$1}.#{env['travis.format']}")</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="45"> + <span class="hits">1</span> + + <code class="ruby"> def force_redirect(path)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="46"> + + + <code class="ruby"> path += "?#{request.query_string}" unless request.query_string.empty?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="47"> + + + <code class="ruby"> response.body = ''</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="48"> + + + <code class="ruby"> response['Content-Length'] = '0'</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> response['Content-Type'] = ''</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="50"> + + + <code class="ruby"> redirect(path)</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="53"> + <span class="hits">1</span> + + <code class="ruby"> def png?</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="54"> + <span class="hits">10</span> + + <code class="ruby"> env['travis.format'] == 'png'</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="57"> + <span class="hits">1</span> + + <code class="ruby"> def svg?</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="58"> + <span class="hits">10</span> + + <code class="ruby"> env['travis.format'] == 'svg'</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="61"> + <span class="hits">1</span> + + <code class="ruby"> def xml?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="62"> + + + <code class="ruby"> env['travis.format'] == 'xml'</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="65"> + <span class="hits">1</span> + + <code class="ruby"> def atom?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="66"> + + + <code class="ruby"> env['travis.format'] == 'atom'</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="69"> + <span class="hits">1</span> + + <code class="ruby"> def v1?</code> + </li> + + <li class="covered" data-hits="20" data-linenumber="70"> + <span class="hits">20</span> + + <code class="ruby"> accept_version == 'v1'</code> + </li> + + <li class="never" data-hits="" data-linenumber="71"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="72"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="73"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="74"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="75"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="26dd70a212f3b2cbf26d11a0b7f29ee3dec679c3"> + <div class="header"> + <h3>lib/travis/api/app/middleware/scope_check.rb</h3> + <h4><span class="green">92.59 %</span> covered</h4> + <div> + <b>27</b> relevant lines. + <span class="green"><b>25</b> lines covered</span> and + <span class="red"><b>2</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Middleware</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # Checks access tokens and sets appropriate scopes.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class ScopeCheck < Middleware</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> before do</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="8"> + <span class="hits">23</span> + + <code class="ruby"> next unless token</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="9"> + <span class="hits">4</span> + + <code class="ruby"> access_token = AccessToken.find_by_token(token)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="10"> + <span class="hits">4</span> + + <code class="ruby"> halt 403, 'access denied' unless access_token</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="11"> + <span class="hits">4</span> + + <code class="ruby"> env['travis.access_token'] = access_token</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> after do</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="15"> + <span class="hits">23</span> + + <code class="ruby"> headers['X-OAuth-Scopes'] ||= begin</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="16"> + <span class="hits">23</span> + + <code class="ruby"> scopes = Array(env['travis.access_token'].try(:scopes))</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="17"> + <span class="hits">23</span> + + <code class="ruby"> scopes.map(&:to_s).join(',')</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> def token</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="22"> + <span class="hits">27</span> + + <code class="ruby"> @token ||= header_token || query_token || travis_token</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="27"> + <span class="hits">1</span> + + <code class="ruby"> def travis_token</code> + </li> + + <li class="covered" data-hits="19" data-linenumber="28"> + <span class="hits">19</span> + + <code class="ruby"> return unless token = params[:token]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="29"> + + + <code class="ruby"> AccessToken.for_travis_token(token) || ""</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="32"> + <span class="hits">1</span> + + <code class="ruby"> def query_token</code> + </li> + + <li class="covered" data-hits="19" data-linenumber="33"> + <span class="hits">19</span> + + <code class="ruby"> params[:access_token] if params[:access_token] and not params[:access_token].empty?</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="36"> + <span class="hits">1</span> + + <code class="ruby"> def header_token</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="37"> + <span class="hits">23</span> + + <code class="ruby"> type, payload = env['HTTP_AUTHORIZATION'].to_s.split(" ", 2)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="38"> + <span class="hits">23</span> + + <code class="ruby"> return if payload.nil? or payload.empty?</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="10" data-linenumber="40"> + <span class="hits">10</span> + + <code class="ruby"> case type.downcase</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="41"> + + + <code class="ruby"> when 'basic' then payload.unpack("m").first.split(':', 2).first</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="42"> + <span class="hits">4</span> + + <code class="ruby"> when 'token' then payload.gsub(/^"(.+)"$/, '\1')</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="57848e06570d6ebc2e75aad01bea70082a1c55f4"> + <div class="header"> + <h3>lib/travis/api/app/middleware/user_agent_tracker.rb</h3> + <h4><span class="red">40.0 %</span> covered</h4> + <div> + <b>35</b> relevant lines. + <span class="green"><b>14</b> lines covered</span> and + <span class="red"><b>21</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'useragent'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Middleware</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> class UserAgentTracker < Middleware</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> WEB_BROWSERS = [</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> "Internet Explorer",</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> "Webkit", "Chrome", "Safari", "Android",</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> "Firefox", "Camino", "Iceweasel", "Seamonkey", "Android",</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> "Opera", "Mozilla"</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> ]</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> before(agent: /^$/) do</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="15"> + <span class="hits">23</span> + + <code class="ruby"> ::Metriks.meter("api.user_agent.missing").mark</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="16"> + <span class="hits">23</span> + + <code class="ruby"> halt(400, "error" => "missing User-Agent header") if Travis::Features.feature_active?(:require_user_agent)</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby"> before(agent: /^.+$/) do</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> agent = UserAgent.parse(request.user_agent)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> case agent.browser</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> when *WEB_BROWSERS then mark_browser</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> when "curl", "Wget" then mark(:console, agent.browser)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="24"> + + + <code class="ruby"> when "travis-api-wrapper" then mark(:script, :node_js, agent.browser)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="25"> + + + <code class="ruby"> when "TravisPy" then mark(:script, :python, agent.browser)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="26"> + + + <code class="ruby"> when "Ruby", "PHP", "Perl", "Python" then mark(:script, agent.browser, :vanilla)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="27"> + + + <code class="ruby"> when "Faraday" then mark(:script, :ruby, :vanilla)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="28"> + + + <code class="ruby"> when "Travis" then mark_travis(agent)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="29"> + + + <code class="ruby"> else mark_unknown</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="33"> + <span class="hits">1</span> + + <code class="ruby"> def mark_browser</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> # allows a JavaScript Client to set X-User-Agent, for instance to "travis-web" in travis-web</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="35"> + + + <code class="ruby"> x_agent = UserAgent.parse(env['HTTP_X_USER_AGENT'] || 'unknown').browser</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> mark(:browser, x_agent)</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="39"> + <span class="hits">1</span> + + <code class="ruby"> def mark_travis(agent)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="40"> + + + <code class="ruby"> command = agent.application.comment.detect { |c| c.start_with? "command " }</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> if command</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> mark(:cli, :version, agent.version)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="44"> + + + <code class="ruby"> mark(:cli, command.sub(' ', '.'))</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> else</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> # only track ruby version and library version for non-cli usage</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="47"> + + + <code class="ruby"> mark(:script, :ruby, :travis, :version, agent.version)</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="51"> + <span class="hits">1</span> + + <code class="ruby"> def mark_unknown</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="52"> + + + <code class="ruby"> logger.warn "[user-agent-tracker] Unknown User-Agent: %p" % request.user_agent</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="53"> + + + <code class="ruby"> mark(:unknown)</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="56"> + <span class="hits">1</span> + + <code class="ruby"> def mark(*keys)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="57"> + + + <code class="ruby"> key = "api.user_agent." << keys.map { |k| k.to_s.downcase.gsub(/[^a-z0-9\-\.]+/, '_') }.join('.')</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="58"> + + + <code class="ruby"> ::Metriks.meter(key).mark</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="866d316bcfc64963406986d03c50d1280b8fe34d"> + <div class="header"> + <h3>lib/travis/api/app/services/schedule_request.rb</h3> + <h4><span class="red">51.61 %</span> covered</h4> + <div> + <b>31</b> relevant lines. + <span class="green"><b>16</b> lines covered</span> and + <span class="red"><b>15</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'multi_json'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/sidekiq/build_request'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/services/base'</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::App</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> module Services</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> class ScheduleRequest < Travis::Services::Base</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> register :schedule_request</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def run</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> repo && active? ? schedule_request : not_found</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def messages</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> @messages ||= []</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby"> def schedule_request</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> Metriks.meter('api.request.create').mark</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> Travis::Sidekiq::BuildRequest.perform_async(type: 'api', payload: payload, credentials: {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> messages << { notice: 'Build request scheduled.' }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="24"> + + + <code class="ruby"> :success</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="27"> + <span class="hits">1</span> + + <code class="ruby"> def not_found</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="28"> + + + <code class="ruby"> messages << { error: "Repository #{slug} not found." }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="29"> + + + <code class="ruby"> :not_found</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="32"> + <span class="hits">1</span> + + <code class="ruby"> def active?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="33"> + + + <code class="ruby"> Travis::Features.owner_active?(:request_create, repo.owner)</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="36"> + <span class="hits">1</span> + + <code class="ruby"> def payload</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="37"> + + + <code class="ruby"> data = params.merge(user: { id: current_user.id })</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="38"> + + + <code class="ruby"> data[:repository][:id] = repo.github_id</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="39"> + + + <code class="ruby"> MultiJson.encode(data)</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="42"> + <span class="hits">1</span> + + <code class="ruby"> def repo</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> @repo ||= Repository.by_slug(slug).first</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="46"> + <span class="hits">1</span> + + <code class="ruby"> def slug</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="47"> + + + <code class="ruby"> repo = params[:repository] || {}</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="48"> + + + <code class="ruby"> repo.values_at(:owner_name, :name).join('/')</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="d04c5eced516ab14b9065b4d34d0af855835a730"> + <div class="header"> + <h3>lib/travis/api/serializer.rb</h3> + <h4><span class="red">66.67 %</span> covered</h4> + <div> + <b>12</b> relevant lines. + <span class="green"><b>8</b> lines covered</span> and + <span class="red"><b>4</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'active_model_serializers'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Serializer < ActiveModel::Serializer</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="7"> + + + <code class="ruby"> as_json</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> class ArraySerializer < ActiveModel::ArraySerializer</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> as_json</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(resource, options)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> options[:each_serializer] ||= Travis::Api::V2::Http.const_get(options[:root].to_s.singularize.camelize)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> super(resource, options)</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="babe3ce05ce1d657f847b2e01c64437b8e58b014"> + <div class="header"> + <h3>lib/travis/api/v2.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>4</b> relevant lines. + <span class="green"><b>4</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http'</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="1c817b9839dda1170aec2560bad5a09065552de6"> + <div class="header"> + <h3>lib/travis/api/v2/http.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>28</b> relevant lines. + <span class="green"><b>28</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/serializer'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/accounts'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/annotations'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/broadcasts'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/branch'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/branches'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/build'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/builds'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/caches'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/hooks'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/job'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/jobs'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/log'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/permissions'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/repositories'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/repository'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/requests'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/request'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="24"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/ssl_key'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/env_var'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="26"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/env_vars'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="27"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/user'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="28"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/validation_error'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="29"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v2/http/ssh_key'</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="c48990e0accf6ba7189617a1b67f9c86eecfc562"> + <div class="header"> + <h3>lib/travis/api/v2/http/accounts.rb</h3> + <h4><span class="red">68.75 %</span> covered</h4> + <div> + <b>16</b> relevant lines. + <span class="green"><b>11</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Accounts</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :accounts, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(accounts, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @accounts = accounts</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> {</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> :accounts => accounts.map { |account| account_data(account) }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> def account_data(account)</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> 'id' => account.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'name' => account.name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'login' => account.login,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'type' => account.type.underscore,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'repos_count' => account.repos_count</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="30"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="65342af497e7edc515415235ed81e3bbaccc6979"> + <div class="header"> + <h3>lib/travis/api/v2/http/annotations.rb</h3> + <h4><span class="red">71.43 %</span> covered</h4> + <div> + <b>14</b> relevant lines. + <span class="green"><b>10</b> lines covered</span> and + <span class="red"><b>4</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Annotations</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(annotations, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> @annotations = annotations</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> {</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="14"> + + + <code class="ruby"> "annotations" => @annotations.map { |annotation| build_annotation(annotation) },</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby"> def build_annotation(annotation)</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> "id" => annotation.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> "job_id" => annotation.job_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> "description" => annotation.description,</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> "url" => annotation.url,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> "status" => annotation.status,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> "provider_name" => annotation.annotation_provider.name,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="28"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="e48076813d88d2c6e10c03686156a6f19429e60e"> + <div class="header"> + <h3>lib/travis/api/v2/http/branch.rb</h3> + <h4><span class="red">71.43 %</span> covered</h4> + <div> + <b>14</b> relevant lines. + <span class="green"><b>10</b> lines covered</span> and + <span class="red"><b>4</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v2/http/branches'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> class Branch < Branches</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :build, :commit, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(build, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> @build = build</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="14"> + + + <code class="ruby"> @commit = build.commit</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> 'branch' => build_data(build),</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> 'commit' => commit_data(commit)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="58933f40c3a13ad2f3470bedf8880494dabc2b2d"> + <div class="header"> + <h3>lib/travis/api/v2/http/branches.rb</h3> + <h4><span class="red">54.55 %</span> covered</h4> + <div> + <b>22</b> relevant lines. + <span class="green"><b>12</b> lines covered</span> and + <span class="red"><b>10</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Branches</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :builds, :commits, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(builds, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> builds = builds.last_finished_builds_by_branches if builds.is_a?(Repository) # TODO remove, bc</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> @builds = builds</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> @commits = builds.map(&:commit)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="14"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> {</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> 'branches' => builds.map { |build| build_data(build) },</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> 'commits' => commits.map { |commit| commit_data(commit) }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="24"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="26"> + <span class="hits">1</span> + + <code class="ruby"> def build_data(build)</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'id' => build.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'repository_id' => build.repository_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'commit_id' => build.commit_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'number' => build.number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'config' => build.obfuscated_config.stringify_keys,</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'state' => build.state.to_s,</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'started_at' => format_date(build.started_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'finished_at' => format_date(build.finished_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> 'duration' => build.duration,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="37"> + + + <code class="ruby"> 'job_ids' => build.matrix.map { |job| job.id },</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> 'pull_request' => build.pull_request?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="39"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="42"> + <span class="hits">1</span> + + <code class="ruby"> def commit_data(commit)</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> 'id' => commit.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> 'sha' => commit.commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> 'branch' => commit.branch,</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> 'message' => commit.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> 'committed_at' => format_date(commit.committed_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> 'author_name' => commit.author_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> 'author_email' => commit.author_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> 'committer_name' => commit.committer_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> 'committer_email' => commit.committer_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> 'compare_url' => commit.compare_url,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="54"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="c46347e1a0d259fc446170187bf8517d99d49177"> + <div class="header"> + <h3>lib/travis/api/v2/http/broadcasts.rb</h3> + <h4><span class="red">66.67 %</span> covered</h4> + <div> + <b>15</b> relevant lines. + <span class="green"><b>10</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Broadcasts</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :broadcasts, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(broadcasts, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> @broadcasts = broadcasts</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> {</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> 'broadcasts' => broadcasts.map { |broadcast| broadcast_data(broadcast) }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> def broadcast_data(broadcast)</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> 'id' => broadcast.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> 'message' => broadcast.message</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="25"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="8c4ac5c4e74342720580a492f7c3aa9d4d384e43"> + <div class="header"> + <h3>lib/travis/api/v2/http/build.rb</h3> + <h4><span class="red">60.87 %</span> covered</h4> + <div> + <b>23</b> relevant lines. + <span class="green"><b>14</b> lines covered</span> and + <span class="red"><b>9</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Build</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :build, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(build, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> options[:include_jobs] = true unless options.key?(:include_jobs)</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> @build = build</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="14"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> 'build' => build_data(build),</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> 'commit' => commit_data(build.commit),</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="21"> + + + <code class="ruby"> 'jobs' => options[:include_jobs] ? build.matrix.map { |job| job_data(job) } : [],</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> 'annotations' => options[:include_jobs] ? Annotations.new(annotations(build), @options).data["annotations"] : [],</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="26"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="28"> + <span class="hits">1</span> + + <code class="ruby"> def build_data(build)</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'id' => build.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'repository_id' => build.repository_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'commit_id' => build.commit_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'number' => build.number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'pull_request' => build.pull_request?,</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'pull_request_title' => build.pull_request_title,</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> 'pull_request_number' => build.pull_request_number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> 'config' => build.obfuscated_config.stringify_keys,</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> 'state' => build.state.to_s,</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> 'started_at' => format_date(build.started_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> 'finished_at' => format_date(build.finished_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> 'duration' => build.duration,</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"> 'job_ids' => build.matrix_ids</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="46"> + <span class="hits">1</span> + + <code class="ruby"> def commit_data(commit)</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> 'id' => commit.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> 'sha' => commit.commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> 'branch' => commit.branch,</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> 'message' => commit.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> 'committed_at' => format_date(commit.committed_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> 'author_name' => commit.author_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> 'author_email' => commit.author_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> 'committer_name' => commit.committer_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> 'committer_email' => commit.committer_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> 'compare_url' => commit.compare_url,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="58"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="61"> + <span class="hits">1</span> + + <code class="ruby"> def job_data(job)</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> 'id' => job.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"> 'repository_id' => job.repository_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"> 'build_id' => job.source_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> 'commit_id' => job.commit_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> 'log_id' => job.log_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"> 'state' => job.state.to_s,</code> + </li> + + <li class="never" data-hits="" data-linenumber="69"> + + + <code class="ruby"> 'number' => job.number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="70"> + + + <code class="ruby"> 'config' => job.obfuscated_config.stringify_keys,</code> + </li> + + <li class="never" data-hits="" data-linenumber="71"> + + + <code class="ruby"> 'started_at' => format_date(job.started_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="72"> + + + <code class="ruby"> 'finished_at' => format_date(job.finished_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="73"> + + + <code class="ruby"> 'queue' => job.queue,</code> + </li> + + <li class="never" data-hits="" data-linenumber="74"> + + + <code class="ruby"> 'allow_failure' => job.allow_failure,</code> + </li> + + <li class="never" data-hits="" data-linenumber="75"> + + + <code class="ruby"> 'tags' => job.tags,</code> + </li> + + <li class="never" data-hits="" data-linenumber="76"> + + + <code class="ruby"> 'annotation_ids' => job.annotation_ids,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="77"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="78"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="79"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="80"> + <span class="hits">1</span> + + <code class="ruby"> def annotations(build)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="81"> + + + <code class="ruby"> build.matrix.map(&:annotations).flatten</code> + </li> + + <li class="never" data-hits="" data-linenumber="82"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="83"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="84"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="85"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="86"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="87"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="1abcacda27e1da4c1f9879072dc5eb5d0a6f1eab"> + <div class="header"> + <h3>lib/travis/api/v2/http/builds.rb</h3> + <h4><span class="red">59.09 %</span> covered</h4> + <div> + <b>22</b> relevant lines. + <span class="green"><b>13</b> lines covered</span> and + <span class="red"><b>9</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Builds</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :builds, :commits, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(builds, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @builds = builds</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> @commits = builds.map(&:commit)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> {</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> 'builds' => builds.map { |build| build_data(build) },</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> 'commits' => commits.map { |commit| commit_data(commit) }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> def build_data(build)</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'id' => build.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'repository_id' => build.repository_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'commit_id' => build.commit_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'number' => build.number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'pull_request' => build.pull_request?,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'pull_request_title' => build.pull_request_title,</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'pull_request_number' => build.pull_request_number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'config' => build.obfuscated_config.stringify_keys,</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'state' => build.state.to_s,</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> 'started_at' => format_date(build.started_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> 'finished_at' => format_date(build.finished_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> 'duration' => build.duration,</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> 'job_ids' => matrix_ids(build)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="40"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="43"> + <span class="hits">1</span> + + <code class="ruby"> def matrix_ids(build)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="44"> + + + <code class="ruby"> build.cached_matrix_ids || build.matrix_ids</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="47"> + <span class="hits">1</span> + + <code class="ruby"> def commit_data(commit)</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> 'id' => commit.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> 'sha' => commit.commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> 'branch' => commit.branch,</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> 'message' => commit.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> 'committed_at' => format_date(commit.committed_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> 'author_name' => commit.author_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> 'author_email' => commit.author_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> 'committer_name' => commit.committer_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> 'committer_email' => commit.committer_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> 'compare_url' => commit.compare_url,</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> 'pull_request_number' => commit.pull_request_number</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="60"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="b7d8a575e84049f0f7983320c9ad1737cc7619a1"> + <div class="header"> + <h3>lib/travis/api/v2/http/caches.rb</h3> + <h4><span class="red">73.33 %</span> covered</h4> + <div> + <b>15</b> relevant lines. + <span class="green"><b>11</b> lines covered</span> and + <span class="red"><b>4</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Caches</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :caches, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(caches, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> @caches = caches</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> { 'caches' => caches.map { |cache| cache_data(cache) } }</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby"> def cache_data(cache)</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> 'repository_id' => cache.repository.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> 'size' => cache.size,</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> 'slug' => cache.slug,</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> 'branch' => cache.branch,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'last_modified' => format_date(cache.last_modified)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="27"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="452e1e09b24321c66a631e743b6a84331da9bd13"> + <div class="header"> + <h3>lib/travis/api/v2/http/env_var.rb</h3> + <h4><span class="red">61.54 %</span> covered</h4> + <div> + <b>13</b> relevant lines. + <span class="green"><b>8</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class EnvVar < Travis::Api::Serializer</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> attributes :id, :name, :value, :public, :repository_id</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def value</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> if object.public?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> object.value.decrypt</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def serializable_hash</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> hash = super</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> hash.delete :value unless object.public?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> hash</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="f91e8a59d86280d6f7eb63939f3a080ab5f82e0f"> + <div class="header"> + <h3>lib/travis/api/v2/http/env_vars.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>1</b> relevant lines. + <span class="green"><b>1</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">class Travis::Api::V2::Http::EnvVars < Travis::Api::ArraySerializer</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="16f73e884ddd5d7c35925c636e1981fa77cb5467"> + <div class="header"> + <h3>lib/travis/api/v2/http/hooks.rb</h3> + <h4><span class="red">66.67 %</span> covered</h4> + <div> + <b>15</b> relevant lines. + <span class="green"><b>10</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Hooks</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :hooks, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(hooks, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> @hooks = hooks</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> {</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="15"> + + + <code class="ruby"> 'hooks' => hooks.map { |hook| hook_data(hook) },</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> def hook_data(hook)</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> 'id' => hook.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> 'name' => hook.name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> 'owner_name' => hook.owner_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'description' => hook.description,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'active' => hook.active,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'private' => hook.private,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'admin' => hook.admin?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="30"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="7bb06459f99796e92585a0613514a4dc10a3b4e6"> + <div class="header"> + <h3>lib/travis/api/v2/http/job.rb</h3> + <h4><span class="red">70.59 %</span> covered</h4> + <div> + <b>17</b> relevant lines. + <span class="green"><b>12</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Job</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :job, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(job, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @job = job</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> 'job' => job_data(job),</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> 'commit' => commit_data(job.commit),</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> 'annotations' => Annotations.new(job.annotations, @options).data["annotations"],</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> def job_data(job)</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'id' => job.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'repository_id' => job.repository_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'repository_slug' => job.repository.slug,</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'build_id' => job.source_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'commit_id' => job.commit_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'log_id' => job.log_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'number' => job.number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'config' => job.obfuscated_config.stringify_keys,</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'state' => job.state.to_s,</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> 'started_at' => format_date(job.started_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> 'finished_at' => format_date(job.finished_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> 'queue' => job.queue,</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> 'allow_failure' => job.allow_failure,</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> 'tags' => job.tags,</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> 'annotation_ids' => job.annotation_ids,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="45"> + <span class="hits">1</span> + + <code class="ruby"> def commit_data(commit)</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> 'id' => commit.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> 'sha' => commit.commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> 'branch' => commit.branch,</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> 'message' => commit.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> 'committed_at' => format_date(commit.committed_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> 'author_name' => commit.author_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> 'author_email' => commit.author_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> 'committer_name' => commit.committer_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> 'committer_email' => commit.committer_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> 'compare_url' => commit.compare_url,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="57"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="28a544a6de90280731859574fbbbcf82c3b12b13"> + <div class="header"> + <h3>lib/travis/api/v2/http/jobs.rb</h3> + <h4><span class="red">63.16 %</span> covered</h4> + <div> + <b>19</b> relevant lines. + <span class="green"><b>12</b> lines covered</span> and + <span class="red"><b>7</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Jobs</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :jobs, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(jobs, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @jobs = jobs</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> {</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> 'jobs' => jobs.map { |job| job_data(job) },</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> 'commits' => jobs.map { |job| commit_data(job.commit) }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="24"> + <span class="hits">1</span> + + <code class="ruby"> def job_data(job)</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'id' => job.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'repository_id' => job.repository_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'repository_slug' => job.repository.slug,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'build_id' => job.source_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'commit_id' => job.commit_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'log_id' => job.log_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'number' => job.number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'config' => job.obfuscated_config.stringify_keys,</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'state' => job.state.to_s,</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'started_at' => format_date(job.started_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> 'finished_at' => format_date(job.finished_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> 'queue' => job.queue,</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> 'allow_failure' => job.allow_failure,</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> 'tags' => job.tags</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="40"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="43"> + <span class="hits">1</span> + + <code class="ruby"> def commit_data(commit)</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> 'id' => commit.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> 'sha' => commit.commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> 'branch' => commit.branch,</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> 'message' => commit.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> 'committed_at' => format_date(commit.committed_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> 'author_name' => commit.author_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> 'author_email' => commit.author_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> 'committer_name' => commit.committer_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> 'committer_email' => commit.committer_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> 'compare_url' => commit.compare_url,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="55"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="305e989221ff7819ee74c2690fb3d9b4d6366b86"> + <div class="header"> + <h3>lib/travis/api/v2/http/log.rb</h3> + <h4><span class="red">50.0 %</span> covered</h4> + <div> + <b>28</b> relevant lines. + <span class="green"><b>14</b> lines covered</span> and + <span class="red"><b>14</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Log</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :log, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(log, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> @log = log</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> 'log' => options[:chunked] ? chunked_log_data : log_data,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> def log_data</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> 'id' => log.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> 'job_id' => log.job_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> 'type' => log.class.name.demodulize,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'body' => log.content</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="27"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="30"> + <span class="hits">1</span> + + <code class="ruby"> def chunked_log_data</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'id' => log.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'job_id' => log.job_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'type' => log.class.name.demodulize,</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'parts' => log_parts</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="39"> + <span class="hits">1</span> + + <code class="ruby"> def log_parts</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="40"> + + + <code class="ruby"> parts = log.parts</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="41"> + + + <code class="ruby"> parts = parts.where(number: part_numbers) if part_numbers</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> parts = parts.where(["number > ?", after]) if after</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> parts.sort_by(&:number).map do |part|</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> 'id' => part.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> 'number' => part.number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> 'content' => part.content,</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> 'final' => part.final</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="53"> + <span class="hits">1</span> + + <code class="ruby"> def after</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="54"> + + + <code class="ruby"> after = options['after'].to_i</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="55"> + + + <code class="ruby"> after == 0 ? nil : after</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="58"> + <span class="hits">1</span> + + <code class="ruby"> def part_numbers</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="59"> + + + <code class="ruby"> if numbers = options['part_numbers']</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="60"> + + + <code class="ruby"> numbers.is_a?(String) ? numbers.split(',').map(&:to_i) : numbers</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="87c289727e6a92299bc4a9407f685b69ca6eb426"> + <div class="header"> + <h3>lib/travis/api/v2/http/permissions.rb</h3> + <h4><span class="red">58.33 %</span> covered</h4> + <div> + <b>24</b> relevant lines. + <span class="green"><b>14</b> lines covered</span> and + <span class="red"><b>10</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Permissions</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :permissions, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(permissions, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> @permissions = permissions</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> 'permissions' => repo_ids,</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> 'admin' => admin_ids,</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> 'pull' => pull_ids,</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> 'push' => push_ids</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> def filtered_ids(perm = nil)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="24"> + + + <code class="ruby"> if perm</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="25"> + + + <code class="ruby"> permissions.find_all { |p| p.send("#{perm}?") }.map { |permission| permission.repository_id }</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="27"> + + + <code class="ruby"> permissions.map { |permission| permission.repository_id }</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="31"> + <span class="hits">1</span> + + <code class="ruby"> def repo_ids</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="32"> + + + <code class="ruby"> filtered_ids</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="35"> + <span class="hits">1</span> + + <code class="ruby"> def admin_ids</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> filtered_ids(:admin)</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="39"> + <span class="hits">1</span> + + <code class="ruby"> def pull_ids</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="40"> + + + <code class="ruby"> filtered_ids(:pull)</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="43"> + <span class="hits">1</span> + + <code class="ruby"> def push_ids</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="44"> + + + <code class="ruby"> filtered_ids(:push)</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="8ff46500e36176862b05aa7513e20da8d68dc208"> + <div class="header"> + <h3>lib/travis/api/v2/http/repositories.rb</h3> + <h4><span class="red">68.75 %</span> covered</h4> + <div> + <b>16</b> relevant lines. + <span class="green"><b>11</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Repositories</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :repositories, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(repositories, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @repositories = repositories</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> {</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> 'repos' => repositories.map { |repository| repository_data(repository) }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> def repository_data(repository)</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> 'id' => repository.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'slug' => repository.slug,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'description' => repository.description,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'last_build_id' => repository.last_build_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'last_build_number' => repository.last_build_number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'last_build_state' => repository.last_build_state.to_s,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'last_build_duration' => repository.last_build_duration,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'last_build_language' => nil,</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'last_build_started_at' => format_date(repository.last_build_started_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'last_build_finished_at' => format_date(repository.last_build_finished_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'active' => repository.active,</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> 'github_language' => repository.github_language</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="37"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="eff78d14dee73bdad5c2af8b49e3b528390c9207"> + <div class="header"> + <h3>lib/travis/api/v2/http/repository.rb</h3> + <h4><span class="red">78.57 %</span> covered</h4> + <div> + <b>14</b> relevant lines. + <span class="green"><b>11</b> lines covered</span> and + <span class="red"><b>3</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Repository</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :repository, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(repository, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @repository = repository</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> 'repo' => repository_data(repository)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> # TODO why does this not include the last build? (i.e. 'builds' => { last build here })</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> def repository_data(repository)</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> 'id' => repository.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'slug' => repository.slug,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'description' => repository.description,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'last_build_id' => repository.last_build_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'last_build_number' => repository.last_build_number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'last_build_state' => repository.last_build_state.to_s,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'last_build_duration' => repository.last_build_duration,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'last_build_language' => nil,</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'last_build_started_at' => format_date(repository.last_build_started_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'last_build_finished_at' => format_date(repository.last_build_finished_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'github_language' => repository.github_language</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="0438b13b58bbb8a610c81181e35ca9c4273df442"> + <div class="header"> + <h3>lib/travis/api/v2/http/request.rb</h3> + <h4><span class="red">52.17 %</span> covered</h4> + <div> + <b>23</b> relevant lines. + <span class="green"><b>12</b> lines covered</span> and + <span class="red"><b>11</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Request</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :request, :commit, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(request, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> @request = request</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @commit = request.commit</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> data = {</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> 'request' => request_data</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> if commit</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> data['commit'] = commit_data</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="22"> + + + <code class="ruby"> data</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="27"> + <span class="hits">1</span> + + <code class="ruby"> def request_data</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="28"> + + + <code class="ruby"> data = {</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'id' => request.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'repository_id' => request.repository_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'commit_id' => request.commit_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'created_at' => format_date(request.created_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'owner_id' => request.owner_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'owner_type' => request.owner_type,</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'event_type' => request.event_type,</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> 'base_commit' => request.base_commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> 'head_commit' => request.head_commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> 'result' => request.result,</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> 'message' => request.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> 'pull_request' => request.pull_request?,</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> 'pull_request_number' => request.pull_request_number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"> 'pull_request_title' => request.pull_request_title,</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"> 'branch' => request.branch_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> 'tag' => request.tag_name</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="47"> + + + <code class="ruby"> data['build_id'] = request.builds.first.id if request.builds.present?</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> data</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="52"> + <span class="hits">1</span> + + <code class="ruby"> def commit_data</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> 'id' => commit.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> 'sha' => commit.commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> 'branch' => commit.branch,</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> 'message' => commit.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> 'committed_at' => format_date(commit.committed_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> 'author_name' => commit.author_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"> 'author_email' => commit.author_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> 'committer_name' => commit.committer_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> 'committer_email' => commit.committer_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> 'compare_url' => commit.compare_url,</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"> 'pull_request_number' => commit.pull_request_number</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="65"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="69"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="70"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="71"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="3409238a742e733e8cc83123cd42c5d119a08c09"> + <div class="header"> + <h3>lib/travis/api/v2/http/requests.rb</h3> + <h4><span class="red">54.55 %</span> covered</h4> + <div> + <b>22</b> relevant lines. + <span class="green"><b>12</b> lines covered</span> and + <span class="red"><b>10</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class Requests</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :requests, :commits, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(requests, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> @requests = requests</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @commits = requests.map(&:commit)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> {</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> 'requests' => requests.map { |request| request_data(request) },</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> 'commits' => commits.compact.map { |commit| commit_data(commit) }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="24"> + <span class="hits">1</span> + + <code class="ruby"> def request_data(request)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="25"> + + + <code class="ruby"> data = {</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'id' => request.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'repository_id' => request.repository_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'commit_id' => request.commit_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'created_at' => format_date(request.created_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'owner_id' => request.owner_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'owner_type' => request.owner_type,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'event_type' => request.event_type,</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'base_commit' => request.base_commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'head_commit' => request.head_commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> 'result' => request.result,</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> 'message' => request.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> 'pull_request' => request.pull_request?,</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> 'pull_request_number' => request.pull_request_number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> 'pull_request_title' => request.pull_request_title,</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> 'branch' => request.branch_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> 'tag' => request.tag_name</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="44"> + + + <code class="ruby"> data['build_id'] = request.builds.first.id if request.builds.present?</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="46"> + + + <code class="ruby"> data</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="49"> + <span class="hits">1</span> + + <code class="ruby"> def commit_data(commit)</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> 'id' => commit.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> 'sha' => commit.commit,</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> 'branch' => commit.branch,</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> 'message' => commit.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> 'committed_at' => format_date(commit.committed_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> 'author_name' => commit.author_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> 'author_email' => commit.author_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> 'committer_name' => commit.committer_name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> 'committer_email' => commit.committer_email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"> 'compare_url' => commit.compare_url,</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> 'pull_request_number' => commit.pull_request_number</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="62"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="67"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="5b078e65cda2e46c4754334f975a5362fd4e47ac"> + <div class="header"> + <h3>lib/travis/api/v2/http/ssh_key.rb</h3> + <h4><span class="red">66.67 %</span> covered</h4> + <div> + <b>15</b> relevant lines. + <span class="green"><b>10</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'openssl'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/private_key'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> class SshKey < Travis::Api::Serializer</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> attributes :id, :description, :fingerprint</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> def id</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> object.repository_id</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def fingerprint</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> value = object.value.decrypt</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> return unless value</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> PrivateKey.new(value).fingerprint</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> rescue OpenSSL::PKey::RSAError</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> nil</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="f9da561db1b52264c76f56f7164b6394902c3a2e"> + <div class="header"> + <h3>lib/travis/api/v2/http/ssl_key.rb</h3> + <h4><span class="red">75.0 %</span> covered</h4> + <div> + <b>12</b> relevant lines. + <span class="green"><b>9</b> lines covered</span> and + <span class="red"><b>3</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class SslKey</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :key</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(key, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> @key = key</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> def fingerprint</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> PrivateKey.new(key.private_key).fingerprint</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> 'key' => key.public_key,</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> 'fingerprint' => fingerprint</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="20"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="4fe5f748a2411310c3bf861101420669e9a8812e"> + <div class="header"> + <h3>lib/travis/api/v2/http/user.rb</h3> + <h4><span class="red">73.33 %</span> covered</h4> + <div> + <b>15</b> relevant lines. + <span class="green"><b>11</b> lines covered</span> and + <span class="red"><b>4</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class User</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> include Formats</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :user, :options</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(user, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> @user = user</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="12"> + + + <code class="ruby"> @options = options</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> 'user' => user_data,</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> def user_data</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> 'id' => user.id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> 'name' => user.name,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> 'login' => user.login,</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> 'email' => user.email,</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> 'gravatar_id' => user.email ? Digest::MD5.hexdigest(user.email) : "",</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> 'locale' => user.locale,</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> 'is_syncing' => user.syncing?,</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> 'synced_at' => format_date(user.synced_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> 'correct_scopes' => user.correct_scopes?,</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> 'created_at' => format_date(user.created_at),</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="35"> + + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="dd52431f41a7d9215be3e7f466926538b62b434a"> + <div class="header"> + <h3>lib/travis/api/v2/http/validation_error.rb</h3> + <h4><span class="red">47.37 %</span> covered</h4> + <div> + <b>19</b> relevant lines. + <span class="green"><b>9</b> lines covered</span> and + <span class="red"><b>10</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Api</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V2</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Http</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> class ValidationError</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :resource</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(resource, options = {})</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> @resource = resource</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> def data</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="13"> + + + <code class="ruby"> response = {</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> message: 'Validation failed'</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> }</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="16"> + + + <code class="ruby"> resource.errors.to_hash.each do |name, errors|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> response['errors'] ||= []</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> errors.each do |error_code|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> response['errors'] << { field: name, code: code(error_code) }</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> response</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="26"> + <span class="hits">1</span> + + <code class="ruby"> def code(error_code)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="27"> + + + <code class="ruby"> case error_code</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> when :blank</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="29"> + + + <code class="ruby"> 'missing_field'</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="31"> + + + <code class="ruby"> error_code.to_s</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby">end</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"></code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="ec916e10f6af10305ba62ae14eb26968f828b52d"> + <div class="header"> + <h3>lib/travis/api/v3.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>18</b> relevant lines. + <span class="green"><b>18</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module API</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> module V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> V3 = self</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def load_dir(dir, recursive: true)</code> + </li> + + <li class="covered" data-hits="49" data-linenumber="7"> + <span class="hits">49</span> + + <code class="ruby"> Dir.glob("#{dir}/*.rb").each { |f| require f[%r[(?<=lib/).+(?=\.rb$)]] }</code> + </li> + + <li class="covered" data-hits="53" data-linenumber="8"> + <span class="hits">53</span> + + <code class="ruby"> Dir.glob("#{dir}/*").each { |dir| load_dir(dir) } if recursive</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> def response(payload, headers = {}, content_type: 'application/json'.freeze, status: 200)</code> + </li> + + <li class="covered" data-hits="22" data-linenumber="12"> + <span class="hits">22</span> + + <code class="ruby"> payload = JSON.pretty_generate(payload) unless payload.is_a? String</code> + </li> + + <li class="covered" data-hits="22" data-linenumber="13"> + <span class="hits">22</span> + + <code class="ruby"> headers = { 'Content-Type'.freeze => content_type, 'Content-Length'.freeze => payload.bytesize.to_s }.merge!(headers)</code> + </li> + + <li class="covered" data-hits="22" data-linenumber="14"> + <span class="hits">22</span> + + <code class="ruby"> [status, headers, [payload] ]</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> extend self</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> load_dir("#{__dir__}/v3")</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby"> ClientError = Error .create(status: 400)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> NotFound = ClientError .create(:resource, status: 404, template: '%s not found (or insufficient access)')</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby"> EnitityMissing = NotFound .create(type: 'not_found')</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> WrongCredentials = ClientError .create('access denied', status: 403)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="24"> + <span class="hits">1</span> + + <code class="ruby"> WrongParams = ClientError .create('wrong parameters')</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="130cf32796ab3cf4d5781313e44244a58973bbf8"> + <div class="header"> + <h3>lib/travis/api/v3/access_control.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>11</b> relevant lines. + <span class="green"><b>11</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module AccessControl</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> REGISTER = {}</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> def self.new(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="6"> + <span class="hits">23</span> + + <code class="ruby"> type, payload = env['HTTP_AUTHORIZATION'.freeze].to_s.split(" ", 2)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="7"> + <span class="hits">23</span> + + <code class="ruby"> payload &&= payload.unpack(?m.freeze).first if type == 'basic'.freeze</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="8"> + <span class="hits">23</span> + + <code class="ruby"> payload &&= type == 'token'.freeze ? payload.gsub(/^"(.+)"$/, '\1'.freeze) : payload.split(?:.freeze)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="9"> + <span class="hits">23</span> + + <code class="ruby"> modes = REGISTER.fetch(type, [])</code> + </li> + + <li class="covered" data-hits="46" data-linenumber="10"> + <span class="hits">46</span> + + <code class="ruby"> access_control = modes.inject(nil) { |current, mode| current || mode.for_request(type, payload, env) }</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="11"> + <span class="hits">23</span> + + <code class="ruby"> raise WrongCredentials unless access_control</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="12"> + <span class="hits">23</span> + + <code class="ruby"> access_control</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="0c37cbeb8112d8c673c2de5e8d4a0bc4a54debad"> + <div class="header"> + <h3>lib/travis/api/v3/access_control/anonymous.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>6</b> relevant lines. + <span class="green"><b>6</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v3/access_control/generic'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class AccessControl::Anonymous < AccessControl::Generic</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # use when Authorization header is not set</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> auth_type(nil)</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> def self.for_request(*)</code> + </li> + + <li class="covered" data-hits="13" data-linenumber="9"> + <span class="hits">13</span> + + <code class="ruby"> new</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="0a4dcd743492bb72a7b2e02c986303e9b6a5f680"> + <div class="header"> + <h3>lib/travis/api/v3/access_control/application.rb</h3> + <h4><span class="green">93.33 %</span> covered</h4> + <div> + <b>15</b> relevant lines. + <span class="green"><b>14</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v3/access_control/generic'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class AccessControl::Application < AccessControl::Generic</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :application_name, :config, :user</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(application_name, user: nil)</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="8"> + <span class="hits">6</span> + + <code class="ruby"> @application_name = application_name</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="9"> + <span class="hits">6</span> + + <code class="ruby"> @config = Travis.config.applications[application_name]</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="10"> + <span class="hits">6</span> + + <code class="ruby"> @user = user</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="11"> + <span class="hits">6</span> + + <code class="ruby"> raise ArgumentError, 'unknown application %p' % application_name unless config</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="12"> + <span class="hits">6</span> + + <code class="ruby"> raise ArgumentError, 'cannot use %p without a user' % application_name if config.requires_user and not user</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> protected</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> def logged_in?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> !!user</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> def full_access?</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="22"> + <span class="hits">4</span> + + <code class="ruby"> config.full_access</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="3e4c532be49003dde82e2f143a6ec6abac0c0fa4"> + <div class="header"> + <h3>lib/travis/api/v3/access_control/generic.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>25</b> relevant lines. + <span class="green"><b>25</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> class AccessControl::Generic</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> def self.for_request(type, payload, env)</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def self.auth_type(*list)</code> + </li> + + <li class="covered" data-hits="7" data-linenumber="7"> + <span class="hits">7</span> + + <code class="ruby"> list.each { |e| (AccessControl::REGISTER[e] ||= []) << self }</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def visible?(object)</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="11"> + <span class="hits">18</span> + + <code class="ruby"> full_access? or dispatch(object)</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> protected</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby"> def repository_visible?(repository)</code> + </li> + + <li class="covered" data-hits="14" data-linenumber="17"> + <span class="hits">14</span> + + <code class="ruby"> return true if unrestricted_api? and not repository.private?</code> + </li> + + <li class="covered" data-hits="12" data-linenumber="18"> + <span class="hits">12</span> + + <code class="ruby"> private_repository_visible?(repository)</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> def private_repository_visible?(repository)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="22"> + <span class="hits">4</span> + + <code class="ruby"> false</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> def full_access?</code> + </li> + + <li class="covered" data-hits="28" data-linenumber="26"> + <span class="hits">28</span> + + <code class="ruby"> false</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="29"> + <span class="hits">1</span> + + <code class="ruby"> def logged_in?</code> + </li> + + <li class="covered" data-hits="14" data-linenumber="30"> + <span class="hits">14</span> + + <code class="ruby"> false</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="33"> + <span class="hits">1</span> + + <code class="ruby"> def public_api?</code> + </li> + + <li class="covered" data-hits="14" data-linenumber="34"> + <span class="hits">14</span> + + <code class="ruby"> !Travis.config.private_api</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="37"> + <span class="hits">1</span> + + <code class="ruby"> def unrestricted_api?</code> + </li> + + <li class="covered" data-hits="14" data-linenumber="38"> + <span class="hits">14</span> + + <code class="ruby"> full_access? or logged_in? or public_api?</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="41"> + <span class="hits">1</span> + + <code class="ruby"> private</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="43"> + <span class="hits">1</span> + + <code class="ruby"> def dispatch(object, method = caller_locations.first.base_label)</code> + </li> + + <li class="covered" data-hits="14" data-linenumber="44"> + <span class="hits">14</span> + + <code class="ruby"> method = object.class.name.underscore + ?_.freeze + method</code> + </li> + + <li class="covered" data-hits="14" data-linenumber="45"> + <span class="hits">14</span> + + <code class="ruby"> send(method, object) if respond_to?(method, true)</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="cc06bcaeb6af4b5039cc7be04f2dcf7d8cbc1656"> + <div class="header"> + <h3>lib/travis/api/v3/access_control/legacy_token.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>15</b> relevant lines. + <span class="green"><b>15</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app/access_token'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v3/access_control/user'</code> + </li> + + <li class="never" data-hits="" data-linenumber="3"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> # Using v2 API tokens to access v3 API.</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> # Allows us to later introduce a new way of storing tokens with more capabilities without API users having to know.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> class AccessControl::LegacyToken < AccessControl::User</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> auth_type('token', 'basic')</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def self.for_request(type, payload, env)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="11"> + <span class="hits">4</span> + + <code class="ruby"> payload = paylad.first if payload.is_a? Array</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="12"> + <span class="hits">4</span> + + <code class="ruby"> token = Travis::Api::App::AccessToken.find_by_token(payload)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="13"> + <span class="hits">4</span> + + <code class="ruby"> new(token) if token</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="16"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(token)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="17"> + <span class="hits">4</span> + + <code class="ruby"> @token = token</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="18"> + <span class="hits">4</span> + + <code class="ruby"> super(token.user)</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> protected</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> def permission?(action, id)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="24"> + <span class="hits">4</span> + + <code class="ruby"> super if @token.scopes.include? :private</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="53595a642e443774649a7e171c5987c76711acd2"> + <div class="header"> + <h3>lib/travis/api/v3/access_control/scoped.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>11</b> relevant lines. + <span class="green"><b>11</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v3/access_control/generic'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class AccessControl::Scoped < AccessControl::Generic</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> attr_accessor :unscoped, :owner_name, :name</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(scope, unscoped)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="8"> + <span class="hits">4</span> + + <code class="ruby"> @owner_name, @name = scope.split(?/.freeze, 2)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="9"> + <span class="hits">4</span> + + <code class="ruby"> @unscoped = unscoped</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> protected</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def private_repository_visible?(repository)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="15"> + <span class="hits">4</span> + + <code class="ruby"> return false if name and repository.name != name</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="16"> + <span class="hits">4</span> + + <code class="ruby"> unscoped.visible?(repository) if repository.owner_name == owner_name</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="79c75a7a3afdda48d239b26bfbce537aac5c7e87"> + <div class="header"> + <h3>lib/travis/api/v3/access_control/signature.rb</h3> + <h4><span class="yellow">81.25 %</span> covered</h4> + <div> + <b>32</b> relevant lines. + <span class="green"><b>26</b> lines covered</span> and + <span class="red"><b>6</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v3/access_control/generic'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/app/access_token'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">require 'digest/sha1'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby">require 'openssl'</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> # Support signed requests to not expose the secret to an untrusted environment.</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> class AccessControl::Signature < AccessControl::Generic</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> auth_type('signature')</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> def self.for_request(type, payload, env)</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="12"> + <span class="hits">6</span> + + <code class="ruby"> *args, signature = payload</code> + </li> + + <li class="covered" data-hits="16" data-linenumber="13"> + <span class="hits">16</span> + + <code class="ruby"> options = Hash[args.map { |a| a.split(?=.freeze, 2) }]</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="14"> + <span class="hits">6</span> + + <code class="ruby"> challenge = ""</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="6" data-linenumber="16"> + <span class="hits">6</span> + + <code class="ruby"> if github_id = options[?u.freeze]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> return unless user = ::User.find_by_github_id(github_id)</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="6" data-linenumber="20"> + <span class="hits">6</span> + + <code class="ruby"> if application = options[?a.freeze]</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="21"> + <span class="hits">6</span> + + <code class="ruby"> return unless Travis.config.applications and app_config = Travis.config.applications[application]</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="6" data-linenumber="24"> + <span class="hits">6</span> + + <code class="ruby"> if c = options[?c.freeze]</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="25"> + + + <code class="ruby"> challenge << env['REQUEST_METHOD'.freeze] << "\n".freeze if c.include?(?m.freeze)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="26"> + + + <code class="ruby"> challenge << env['SCRIPT_NAME'.freeze] << env['PATH_INFO'.freeze] << "\n" if c.include?(?p.freeze)</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="6" data-linenumber="29"> + <span class="hits">6</span> + + <code class="ruby"> challenge << app_config[:secret] if app_config and user</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="30"> + <span class="hits">6</span> + + <code class="ruby"> challenge << args.join(?:.freeze)</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="6" data-linenumber="32"> + <span class="hits">6</span> + + <code class="ruby"> if app_config</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="33"> + <span class="hits">6</span> + + <code class="ruby"> control = AccessControl::Application.new(application, user: user)</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="34"> + <span class="hits">6</span> + + <code class="ruby"> secrets = user ? secrets_for(user) : [app_config[:secret]]</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> else</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> control = AccessControl::User.new(user)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="37"> + + + <code class="ruby"> secrets = secrets_for(user)</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="6" data-linenumber="40"> + <span class="hits">6</span> + + <code class="ruby"> if scope = options[?s.freeze]</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="41"> + <span class="hits">4</span> + + <code class="ruby"> control &&= AccessControl::Scoped.new(scope, control) </code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="12" data-linenumber="44"> + <span class="hits">12</span> + + <code class="ruby"> control if secrets.any? { |secret| signed(challenge, secret) == signature }</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="47"> + <span class="hits">1</span> + + <code class="ruby"> def self.secrets_for(user)</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> [</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="49"> + + + <code class="ruby"> Travis::Api::App::AccessToken.new(user: user, app_id: 1), # generated from github token</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> Travis::Api::App::AccessToken.new(user: user, app_id: 0) # used by web</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> ]</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="54"> + <span class="hits">1</span> + + <code class="ruby"> def self.signed(challenge, secret)</code> + </li> + + <li class="covered" data-hits="6" data-linenumber="55"> + <span class="hits">6</span> + + <code class="ruby"> OpenSSL::HMAC.hexdigest('sha256'.freeze, secret, challenge)</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="57"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="8ed530d2fb0e1b23faa65b796edd40391a551aff"> + <div class="header"> + <h3>lib/travis/api/v3/access_control/user.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>14</b> relevant lines. + <span class="green"><b>14</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v3/access_control/generic'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class AccessControl::User < AccessControl::Generic</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :user, :permissions</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(user)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="8"> + <span class="hits">4</span> + + <code class="ruby"> @user = user</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="9"> + <span class="hits">4</span> + + <code class="ruby"> @permissions = user.permissions.where(user_id: user.id)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="10"> + <span class="hits">4</span> + + <code class="ruby"> super()</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> protected</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def private_repository_visible?(repository)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="16"> + <span class="hits">4</span> + + <code class="ruby"> permission?(:pull, repository)</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby"> def permission?(type, id)</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="20"> + <span class="hits">4</span> + + <code class="ruby"> id = id.id if id.is_a? ::Repository</code> + </li> + + <li class="covered" data-hits="4" data-linenumber="21"> + <span class="hits">4</span> + + <code class="ruby"> permissions.where(type => true, :repository_id => id).any?</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="e7d3951ce9217b83d561dc22cebb4194095eba79"> + <div class="header"> + <h3>lib/travis/api/v3/error.rb</h3> + <h4><span class="yellow">85.71 %</span> covered</h4> + <div> + <b>21</b> relevant lines. + <span class="green"><b>18</b> lines covered</span> and + <span class="red"><b>3</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'rack/utils'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Error < StandardError</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> def self.create(default_message = nil, **options)</code> + </li> + + <li class="covered" data-hits="5" data-linenumber="6"> + <span class="hits">5</span> + + <code class="ruby"> options[:default_message] = default_message if default_message</code> + </li> + + <li class="covered" data-hits="38" data-linenumber="7"> + <span class="hits">38</span> + + <code class="ruby"> Class.new(self) { options.each { |key, value| define_singleton_method(key) { value } } }</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def self.status</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="11"> + + + <code class="ruby"> 500</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def self.type</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="15"> + <span class="hits">10</span> + + <code class="ruby"> @type ||= name[/[^:]+$/].underscore</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> def self.template</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> '%s'.freeze</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby"> def self.default_message</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="23"> + + + <code class="ruby"> @default_message ||= Rack::Utils::HTTP_STATUS_CODES.fetch(status, 'unknown error'.freeze).downcase</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="26"> + <span class="hits">1</span> + + <code class="ruby"> attr_accessor :status, :type, :payload</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="28"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(message = self.class.default_message, status: self.class.status, type: self.class.type, **payload)</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="29"> + <span class="hits">10</span> + + <code class="ruby"> if message.is_a? Symbol</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="30"> + <span class="hits">10</span> + + <code class="ruby"> payload[:resource_type] ||= message</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="31"> + <span class="hits">10</span> + + <code class="ruby"> message = self.class.template % message</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="10" data-linenumber="34"> + <span class="hits">10</span> + + <code class="ruby"> self.status, self.type, self.payload = status, type, payload</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="35"> + <span class="hits">10</span> + + <code class="ruby"> super(message)</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="31a1a8c991fef1e18b15080ccfcb0e9ba1d8c1a4"> + <div class="header"> + <h3>lib/travis/api/v3/opt_in.rb</h3> + <h4><span class="green">97.22 %</span> covered</h4> + <div> + <b>36</b> relevant lines. + <span class="green"><b>35</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> class OptIn</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :legacy_stack, :prefix, :router, :accept, :version_header</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(legacy_stack, prefix: '/v3', router: Router.new, accept: 'application/vnd.travis-ci.3+', version_header: 'Travis-API-Version')</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="6"> + <span class="hits">27</span> + + <code class="ruby"> @legacy_stack = legacy_stack</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="7"> + <span class="hits">27</span> + + <code class="ruby"> @prefix = prefix</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="8"> + <span class="hits">27</span> + + <code class="ruby"> @router = router</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="9"> + <span class="hits">27</span> + + <code class="ruby"> @accept = accept</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="10"> + <span class="hits">27</span> + + <code class="ruby"> @version_header = "HTTP_#{version_header.upcase.gsub(/\W/, '_')}"</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def call(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="14"> + <span class="hits">23</span> + + <code class="ruby"> return redirect(env) if redirect?(env)</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="23" data-linenumber="16"> + <span class="hits">23</span> + + <code class="ruby"> if matched = matching_env(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="17"> + <span class="hits">23</span> + + <code class="ruby"> result = @router.call(matched)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="18"> + <span class="hits">23</span> + + <code class="ruby"> result, missing = nil, result if cascade?(*result)</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="23" data-linenumber="21"> + <span class="hits">23</span> + + <code class="ruby"> result = result || legacy_stack.call(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="22"> + <span class="hits">23</span> + + <code class="ruby"> pick(result, missing)</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> def pick(result, missing)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="26"> + <span class="hits">23</span> + + <code class="ruby"> return result if missing.nil?</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="27"> + <span class="hits">10</span> + + <code class="ruby"> return result if result[0] != 404</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="28"> + <span class="hits">10</span> + + <code class="ruby"> missing</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="31"> + <span class="hits">1</span> + + <code class="ruby"> def redirect?(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="32"> + <span class="hits">23</span> + + <code class="ruby"> env['PATH_INFO'.freeze] == prefix</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="35"> + <span class="hits">1</span> + + <code class="ruby"> def redirect(env)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="36"> + + + <code class="ruby"> [307, {'Location'.freeze => env['SCRIPT_NAME'.freeze] + prefix + ?/.freeze, 'Conent-Type'.freeze => 'text/plain'.freeze}, []]</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="38"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="39"> + <span class="hits">1</span> + + <code class="ruby"> def cascade?(status, headers, body)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="40"> + <span class="hits">23</span> + + <code class="ruby"> status % 100 == 4 and headers['X-Cascade'.freeze] == 'pass'.freeze</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="42"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="43"> + <span class="hits">1</span> + + <code class="ruby"> def matching_env(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="44"> + <span class="hits">23</span> + + <code class="ruby"> for_v3 = from_prefix(env) || from_accept(env) || from_version_header(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="45"> + <span class="hits">23</span> + + <code class="ruby"> for_v3 == true ? env : for_v3</code> + </li> + + <li class="never" data-hits="" data-linenumber="46"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="48"> + <span class="hits">1</span> + + <code class="ruby"> def from_prefix(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="49"> + <span class="hits">23</span> + + <code class="ruby"> return unless prefix and env['PATH_INFO'.freeze].start_with?(prefix + ?/.freeze)</code> + </li> + + <li class="covered" data-hits="20" data-linenumber="50"> + <span class="hits">20</span> + + <code class="ruby"> env.merge({</code> + </li> + + <li class="never" data-hits="" data-linenumber="51"> + + + <code class="ruby"> 'SCRIPT_NAME'.freeze => env['SCRIPT_NAME'.freeze] + prefix,</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> 'PATH_INFO'.freeze => env['PATH_INFO'.freeze][prefix.size..-1]</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> })</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="56"> + <span class="hits">1</span> + + <code class="ruby"> def from_accept(env)</code> + </li> + + <li class="covered" data-hits="3" data-linenumber="57"> + <span class="hits">3</span> + + <code class="ruby"> env['HTTP_ACCEPT'.freeze].include?(accept) if accept and env.include?('HTTP_ACCEPT'.freeze)</code> + </li> + + <li class="never" data-hits="" data-linenumber="58"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="60"> + <span class="hits">1</span> + + <code class="ruby"> def from_version_header(env)</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="61"> + <span class="hits">2</span> + + <code class="ruby"> env[version_header] == '3'.freeze if version_header and env.include?(version_header)</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="64"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="8705c480fd77b20d19558856194eeee048030a20"> + <div class="header"> + <h3>lib/travis/api/v3/renderer.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>8</b> relevant lines. + <span class="green"><b>8</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Renderer</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> extend self</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> def [](key)</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="6"> + <span class="hits">18</span> + + <code class="ruby"> return key if key.respond_to? :render</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="7"> + <span class="hits">18</span> + + <code class="ruby"> const_get(key.to_s.camelize)</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def format_date(date)</code> + </li> + + <li class="covered" data-hits="16" data-linenumber="11"> + <span class="hits">16</span> + + <code class="ruby"> date && date.strftime('%Y-%m-%dT%H:%M:%SZ')</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="1b1a35fbaa7ca2749c8e0b8b9c270d2424fa0183"> + <div class="header"> + <h3>lib/travis/api/v3/renderer/error.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>5</b> relevant lines. + <span class="green"><b>5</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Renderer::Error</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> extend self</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> def render(error)</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> :@type => 'error'.freeze,</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> :error_type => error.type,</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> :error_message => error.message,</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> **error.payload</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="11"> + <span class="hits">10</span> + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="cca5ed5e9f0a0d7cd46bb5427220ee36042a9e9c"> + <div class="header"> + <h3>lib/travis/api/v3/renderer/repository.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>10</b> relevant lines. + <span class="green"><b>10</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Renderer::Repository</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> DIRECT_ATTRIBUTES = %i[id name slug description github_language private]</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> extend self</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def render(repository)</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="7"> + <span class="hits">8</span> + + <code class="ruby"> { :@type => 'repository'.freeze, **direct_attributes(repository), **nested_resources(repository) }</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def direct_attributes(repository)</code> + </li> + + <li class="covered" data-hits="56" data-linenumber="11"> + <span class="hits">56</span> + + <code class="ruby"> DIRECT_ATTRIBUTES.map { |a| [a, repository.public_send(a)] }.to_h</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def nested_resources(repository)</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> {</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> owner: {</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"> :@type => repository.owner_type.downcase,</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"> :id => repository.owner_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> :login => repository.owner_name</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> },</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> last_build: {</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> :@type => 'build'.freeze,</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> :id => repository.last_build_id,</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"> :number => repository.last_build_number,</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> :state => repository.last_build_state.to_s,</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> :duration => repository.last_build_duration,</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> :started_at => Renderer.format_date(repository.last_build_started_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> :finished_at => Renderer.format_date(repository.last_build_finished_at),</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> }</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="30"> + <span class="hits">8</span> + + <code class="ruby"> }</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="74ddbe2707d65e192759c48049f9527b65ce82db"> + <div class="header"> + <h3>lib/travis/api/v3/result.rb</h3> + <h4><span class="green">93.75 %</span> covered</h4> + <div> + <b>16</b> relevant lines. + <span class="green"><b>15</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> class Result</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> attr_accessor :type, :resource</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(type, resource = [])</code> + </li> + + <li class="covered" data-hits="22" data-linenumber="6"> + <span class="hits">22</span> + + <code class="ruby"> @type, @resource = type, resource</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> def respond_to_missing?(method, *)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> super or method.to_sym == type.to_sym</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def <<(value)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> resource << value</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> self</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> def render</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="19"> + <span class="hits">18</span> + + <code class="ruby"> Renderer[type].render(resource)</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="22"> + <span class="hits">1</span> + + <code class="ruby"> def method_missing(method, *args)</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="23"> + <span class="hits">2</span> + + <code class="ruby"> return super unless method.to_sym == type.to_sym</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="24"> + <span class="hits">2</span> + + <code class="ruby"> raise ArgumentError, 'wrong number of arguments (1 for 0)'.freeze if args.any?</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="25"> + <span class="hits">2</span> + + <code class="ruby"> resource</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="31c7c96fc03fbcc205b874d99b9af9102c3400d7"> + <div class="header"> + <h3>lib/travis/api/v3/router.rb</h3> + <h4><span class="green">90.32 %</span> covered</h4> + <div> + <b>31</b> relevant lines. + <span class="green"><b>28</b> lines covered</span> and + <span class="red"><b>3</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> class Router</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> include Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> attr_accessor :routes</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(routes = Routes)</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="7"> + <span class="hits">27</span> + + <code class="ruby"> @routes = routes</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="8"> + <span class="hits">27</span> + + <code class="ruby"> routes.draw_routes</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="11"> + <span class="hits">1</span> + + <code class="ruby"> def call(env)</code> + </li> + + <li class="covered" data-hits="23" data-linenumber="12"> + <span class="hits">23</span> + + <code class="ruby"> return service_index(env) if env['PATH_INFO'.freeze] == ?/.freeze</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="13"> + <span class="hits">18</span> + + <code class="ruby"> access_control = AccessControl.new(env)</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="14"> + <span class="hits">18</span> + + <code class="ruby"> factory, params = routes.factory_for(env['REQUEST_METHOD'.freeze], env['PATH_INFO'.freeze])</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="15"> + <span class="hits">18</span> + + <code class="ruby"> env_params = params(env)</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="18" data-linenumber="17"> + <span class="hits">18</span> + + <code class="ruby"> raise NotFound unless factory</code> + </li> + + <li class="never" data-hits="" data-linenumber="18"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="18" data-linenumber="19"> + <span class="hits">18</span> + + <code class="ruby"> service = factory.new(access_control, env_params.merge(params))</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="20"> + <span class="hits">18</span> + + <code class="ruby"> result = service.run</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="21"> + <span class="hits">8</span> + + <code class="ruby"> render(result, env_params)</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"> rescue Error => error</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="23"> + <span class="hits">10</span> + + <code class="ruby"> result = Result.new(:error, error)</code> + </li> + + <li class="covered" data-hits="10" data-linenumber="24"> + <span class="hits">10</span> + + <code class="ruby"> V3.response(result.render, 'X-Cascade'.freeze => 'pass'.freeze, status: error.status)</code> + </li> + + <li class="never" data-hits="" data-linenumber="25"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="27"> + <span class="hits">1</span> + + <code class="ruby"> def render(result, env_params)</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="28"> + <span class="hits">8</span> + + <code class="ruby"> V3.response(result.render)</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="30"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="31"> + <span class="hits">1</span> + + <code class="ruby"> def service_index(env)</code> + </li> + + <li class="covered" data-hits="5" data-linenumber="32"> + <span class="hits">5</span> + + <code class="ruby"> ServiceIndex.for(env, routes).render(env)</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="34"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="35"> + <span class="hits">1</span> + + <code class="ruby"> def params(env)</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="36"> + <span class="hits">18</span> + + <code class="ruby"> request = Rack::Request.new(env)</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="37"> + <span class="hits">18</span> + + <code class="ruby"> params = request.params</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="38"> + <span class="hits">18</span> + + <code class="ruby"> media_type = request.media_type</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="18" data-linenumber="40"> + <span class="hits">18</span> + + <code class="ruby"> if media_type == 'application/json'.freeze or media_type == 'text/json'.freeze</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="41"> + + + <code class="ruby"> request.body.rewind</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="42"> + + + <code class="ruby"> json_params = env['travis.input.json'.freeze] ||= JSON.load(request.body)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="43"> + + + <code class="ruby"> params.merge! json_params if json_params.is_a? Hash</code> + </li> + + <li class="never" data-hits="" data-linenumber="44"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="45"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="18" data-linenumber="46"> + <span class="hits">18</span> + + <code class="ruby"> params</code> + </li> + + <li class="never" data-hits="" data-linenumber="47"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="48"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="0e450b71a9d314b9765473a9783eafbc6ad24b88"> + <div class="header"> + <h3>lib/travis/api/v3/routes.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>7</b> relevant lines. + <span class="green"><b>7</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Routes</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> require 'travis/api/v3/routes/dsl'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> extend DSL</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> resource :repository do</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> route '/repo/:id'</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> get :find_repository</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="2e298b60191a32090a5982c87b6a53c75d24cb8c"> + <div class="header"> + <h3>lib/travis/api/v3/routes/dsl.rb</h3> + <h4><span class="green">97.22 %</span> covered</h4> + <div> + <b>36</b> relevant lines. + <span class="green"><b>35</b> lines covered</span> and + <span class="red"><b>1</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'travis/api/v3/routes/resource'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> module Routes::DSL</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> def routes</code> + </li> + + <li class="covered" data-hits="126" data-linenumber="6"> + <span class="hits">126</span> + + <code class="ruby"> @routes ||= {}</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> def resources</code> + </li> + + <li class="covered" data-hits="32" data-linenumber="10"> + <span class="hits">32</span> + + <code class="ruby"> @resources ||= []</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def current_resource</code> + </li> + + <li class="covered" data-hits="3" data-linenumber="14"> + <span class="hits">3</span> + + <code class="ruby"> @current_resource ||= nil</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> def resource(type, &block)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> resource = Routes::Resource.new(type)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="19"> + <span class="hits">1</span> + + <code class="ruby"> with_resource(resource, &block)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby"> resources << resource</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="23"> + <span class="hits">1</span> + + <code class="ruby"> def with_resource(resource)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="24"> + <span class="hits">1</span> + + <code class="ruby"> resource_was, @current_resource = current_resource, resource</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> yield</code> + </li> + + <li class="never" data-hits="" data-linenumber="26"> + + + <code class="ruby"> ensure</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="27"> + <span class="hits">1</span> + + <code class="ruby"> @current_resource = resource_was</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="29"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="30"> + <span class="hits">1</span> + + <code class="ruby"> def route(value)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="31"> + <span class="hits">1</span> + + <code class="ruby"> current_resource.route = value</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="34"> + <span class="hits">1</span> + + <code class="ruby"> def get(*args)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="35"> + <span class="hits">1</span> + + <code class="ruby"> current_resource.add_service('GET'.freeze, *args)</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="38"> + <span class="hits">1</span> + + <code class="ruby"> def post(*args)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="39"> + + + <code class="ruby"> current_resource.add_service('POST'.freeze, *args)</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="41"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="42"> + <span class="hits">1</span> + + <code class="ruby"> def draw_routes</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="43"> + <span class="hits">27</span> + + <code class="ruby"> resources.each do |resource|</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="44"> + <span class="hits">27</span> + + <code class="ruby"> prefix = resource.route</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="45"> + <span class="hits">27</span> + + <code class="ruby"> resource.services.each do |(request_method, sub_route), service|</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="46"> + <span class="hits">27</span> + + <code class="ruby"> route = sub_route ? prefix + sub_route : prefix</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="47"> + <span class="hits">27</span> + + <code class="ruby"> routes[route] ||= {}</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="48"> + <span class="hits">27</span> + + <code class="ruby"> routes[route][request_method] = Services[service]</code> + </li> + + <li class="never" data-hits="" data-linenumber="49"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="50"> + + + <code class="ruby"> end</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="51"> + <span class="hits">27</span> + + <code class="ruby"> self.routes.replace(routes)</code> + </li> + + <li class="never" data-hits="" data-linenumber="52"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="54"> + <span class="hits">1</span> + + <code class="ruby"> def factory_for(request_method, path)</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="55"> + <span class="hits">18</span> + + <code class="ruby"> routes.each do |route, method_map|</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="56"> + <span class="hits">18</span> + + <code class="ruby"> next unless params = route.params(path)</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="57"> + <span class="hits">18</span> + + <code class="ruby"> raise MethodNotAllowed unless factory = method_map[request_method]</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="58"> + <span class="hits">18</span> + + <code class="ruby"> return [factory, params]</code> + </li> + + <li class="never" data-hits="" data-linenumber="59"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="60"> + + + <code class="ruby"> nil # nothing matched</code> + </li> + + <li class="never" data-hits="" data-linenumber="61"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="62"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="63"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="f17bf0ade034477bfdb62ad253c6d587b77e5214"> + <div class="header"> + <h3>lib/travis/api/v3/routes/resource.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>12</b> relevant lines. + <span class="green"><b>12</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">require 'mustermann'</code> + </li> + + <li class="never" data-hits="" data-linenumber="2"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> class Routes::Resource</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> attr_accessor :identifier, :route, :services</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(identifier)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> @identifier = identifier</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> @services = {}</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> def add_service(request_method, service, sub_route = nil)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> sub_route &&= Mustermann.new(sub_route)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> services[[request_method, sub_route]] = service</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="17"> + <span class="hits">1</span> + + <code class="ruby"> def route=(value)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> @route = value ? Mustermann.new(value) : value</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="847a0c89fe4c592228989215bbeb1143051d97b6"> + <div class="header"> + <h3>lib/travis/api/v3/service.rb</h3> + <h4><span class="yellow">85.0 %</span> covered</h4> + <div> + <b>20</b> relevant lines. + <span class="green"><b>17</b> lines covered</span> and + <span class="red"><b>3</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> class Service</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> def self.required_params</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="4"> + + + <code class="ruby"> @required_params ||= []</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> def self.params(*list, optional: false)</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="8"> + <span class="hits">1</span> + + <code class="ruby"> @params ||= []</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="9"> + <span class="hits">1</span> + + <code class="ruby"> list.each do |param|</code> + </li> + + <li class="covered" data-hits="3" data-linenumber="10"> + <span class="hits">3</span> + + <code class="ruby"> param = param.to_s</code> + </li> + + <li class="covered" data-hits="39" data-linenumber="11"> + <span class="hits">39</span> + + <code class="ruby"> define_method(param) { params[param] }</code> + </li> + + <li class="covered" data-hits="3" data-linenumber="12"> + <span class="hits">3</span> + + <code class="ruby"> required_params << param unless optional</code> + </li> + + <li class="covered" data-hits="3" data-linenumber="13"> + <span class="hits">3</span> + + <code class="ruby"> @params << param</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"> end</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> @params</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="17"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="18"> + <span class="hits">1</span> + + <code class="ruby"> attr_accessor :access_control, :params</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="20"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(access_control, params)</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="21"> + <span class="hits">18</span> + + <code class="ruby"> @access_control = access_control</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="22"> + <span class="hits">18</span> + + <code class="ruby"> @params = params</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> def required_params?</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="26"> + + + <code class="ruby"> required_params.all? { |param| params.include? param }</code> + </li> + + <li class="never" data-hits="" data-linenumber="27"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="28"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="29"> + <span class="hits">1</span> + + <code class="ruby"> def required_params</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="30"> + + + <code class="ruby"> self.class.required_params</code> + </li> + + <li class="never" data-hits="" data-linenumber="31"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="32"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="33"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="63648861eabe7693b10dd0f87b899dfb0a4ff38f"> + <div class="header"> + <h3>lib/travis/api/v3/service_index.rb</h3> + <h4><span class="green">91.53 %</span> covered</h4> + <div> + <b>59</b> relevant lines. + <span class="green"><b>54</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> class ServiceIndex</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> ALLOW_POST = ['application/json', 'application/x-www-form-urlencoded', 'multipart/form-data']</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="4"> + <span class="hits">1</span> + + <code class="ruby"> @index_cache = {}</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="6"> + <span class="hits">1</span> + + <code class="ruby"> def self.for(env, routes)</code> + </li> + + <li class="covered" data-hits="5" data-linenumber="7"> + <span class="hits">5</span> + + <code class="ruby"> access_factory = AccessControl.new(env).class</code> + </li> + + <li class="covered" data-hits="5" data-linenumber="8"> + <span class="hits">5</span> + + <code class="ruby"> prefix = env['SCRIPT_NAME'.freeze]</code> + </li> + + <li class="covered" data-hits="5" data-linenumber="9"> + <span class="hits">5</span> + + <code class="ruby"> @index_cache[[access_factory, routes, prefix]] ||= new(access_factory, routes, prefix)</code> + </li> + + <li class="never" data-hits="" data-linenumber="10"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="12"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :access_factory, :routes, :json_home_response, :json_response, :prefix</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="14"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(access_factory, routes, prefix)</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="15"> + <span class="hits">2</span> + + <code class="ruby"> @prefix = prefix || ''</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="16"> + <span class="hits">2</span> + + <code class="ruby"> @access_factory, @routes = access_factory, routes</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="17"> + <span class="hits">2</span> + + <code class="ruby"> @json_response = V3.response(render_json, content_type: 'application/json'.freeze)</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="18"> + <span class="hits">2</span> + + <code class="ruby"> @json_home_response = V3.response(render_json_home, content_type: 'application/json-home'.freeze)</code> + </li> + + <li class="never" data-hits="" data-linenumber="19"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="21"> + <span class="hits">1</span> + + <code class="ruby"> def render(env)</code> + </li> + + <li class="covered" data-hits="5" data-linenumber="22"> + <span class="hits">5</span> + + <code class="ruby"> json_home?(env) ? json_home_response : json_response</code> + </li> + + <li class="never" data-hits="" data-linenumber="23"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="24"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="25"> + <span class="hits">1</span> + + <code class="ruby"> def render_json</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="26"> + <span class="hits">2</span> + + <code class="ruby"> resources = { }</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="27"> + <span class="hits">2</span> + + <code class="ruby"> routes.resources.each do |resource|</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="28"> + <span class="hits">2</span> + + <code class="ruby"> resources[resource.identifier] ||= {}</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="29"> + <span class="hits">2</span> + + <code class="ruby"> resource.services.each do |(request_method, sub_route), service|</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="30"> + <span class="hits">2</span> + + <code class="ruby"> service &&= service.to_s.sub(/_#{resource.identifier}$/, ''.freeze)</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="31"> + <span class="hits">2</span> + + <code class="ruby"> list = resources[resource.identifier][service] ||= []</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="32"> + <span class="hits">2</span> + + <code class="ruby"> pattern = sub_route ? resource.route + sub_route : resource.route</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="33"> + <span class="hits">2</span> + + <code class="ruby"> pattern.to_templates.each do |template|</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="34"> + <span class="hits">2</span> + + <code class="ruby"> list << { 'request-method'.freeze => request_method, 'uri-template'.freeze => prefix + template }</code> + </li> + + <li class="never" data-hits="" data-linenumber="35"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="36"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="37"> + + + <code class="ruby"> end</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="38"> + <span class="hits">2</span> + + <code class="ruby"> { resources: resources }</code> + </li> + + <li class="never" data-hits="" data-linenumber="39"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="40"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="41"> + <span class="hits">1</span> + + <code class="ruby"> def render_json_home</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="42"> + <span class="hits">2</span> + + <code class="ruby"> relations = {}</code> + </li> + + <li class="never" data-hits="" data-linenumber="43"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="2" data-linenumber="44"> + <span class="hits">2</span> + + <code class="ruby"> routes.resources.each do |resource|</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="45"> + <span class="hits">2</span> + + <code class="ruby"> resource.services.each do |(request_method, sub_route), service|</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="46"> + <span class="hits">2</span> + + <code class="ruby"> service &&= service.to_s.sub(/_#{resource.identifier}$/, ''.freeze)</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="47"> + <span class="hits">2</span> + + <code class="ruby"> pattern = sub_route ? resource.route + sub_route : resource.route</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="48"> + <span class="hits">2</span> + + <code class="ruby"> relation = "http://schema.travis-ci.com/rel/#{resource.identifier}/#{service}"</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="49"> + <span class="hits">2</span> + + <code class="ruby"> pattern.to_templates.each do |template|</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="50"> + <span class="hits">2</span> + + <code class="ruby"> relations[relation] ||= {}</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="51"> + <span class="hits">2</span> + + <code class="ruby"> relations[relation][template] ||= { allow: [], vars: template.scan(/{\+?([^}]+)}/).flatten }</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="52"> + <span class="hits">2</span> + + <code class="ruby"> relations[relation][template][:allow] << request_method</code> + </li> + + <li class="never" data-hits="" data-linenumber="53"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="54"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="55"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="56"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="2" data-linenumber="57"> + <span class="hits">2</span> + + <code class="ruby"> nested_relations = {}</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="58"> + <span class="hits">2</span> + + <code class="ruby"> relations.delete_if do |relation, request_map|</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="59"> + <span class="hits">2</span> + + <code class="ruby"> next if request_map.size < 2</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="60"> + + + <code class="ruby"> common_vars = request_map.values.map { |e| e[:vars] }.inject(:&)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="61"> + + + <code class="ruby"> request_map.each do |template, payload|</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="62"> + + + <code class="ruby"> special_vars = payload[:vars] - common_vars</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="63"> + + + <code class="ruby"> schema = special_vars.any? ? "#{relation}/by_#{special_vars.join(?_)}" : relation</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="64"> + + + <code class="ruby"> nested_relations[schema] = { template => payload }</code> + </li> + + <li class="never" data-hits="" data-linenumber="65"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="66"> + + + <code class="ruby"> end</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="67"> + <span class="hits">2</span> + + <code class="ruby"> relations.merge! nested_relations</code> + </li> + + <li class="never" data-hits="" data-linenumber="68"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="2" data-linenumber="69"> + <span class="hits">2</span> + + <code class="ruby"> resources = relations.map do |relation, payload|</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="70"> + <span class="hits">2</span> + + <code class="ruby"> template, payload = payload.first</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="71"> + <span class="hits">2</span> + + <code class="ruby"> hints = { 'allow' => payload[:allow] }</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="72"> + <span class="hits">2</span> + + <code class="ruby"> hints['accept-post'] = ALLOW_POST if payload[:allow].include? 'POST'</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="73"> + <span class="hits">2</span> + + <code class="ruby"> hints['accept-patch'] = ALLOW_POST if payload[:allow].include? 'PATCH'</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="74"> + <span class="hits">2</span> + + <code class="ruby"> hints['accept-put'] = ALLOW_POST if payload[:allow].include? 'PUT'</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="75"> + <span class="hits">2</span> + + <code class="ruby"> hints['representations'] = ['application/json', 'application/vnd.travis-ci.3+json']</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="76"> + <span class="hits">2</span> + + <code class="ruby"> [relation, {</code> + </li> + + <li class="never" data-hits="" data-linenumber="77"> + + + <code class="ruby"> 'href-template' => prefix + template,</code> + </li> + + <li class="covered" data-hits="2" data-linenumber="78"> + <span class="hits">2</span> + + <code class="ruby"> 'href-vars' => Hash[payload[:vars].map { |var| [var, "http://schema.travis-ci.com/param/#{var}"] }],</code> + </li> + + <li class="never" data-hits="" data-linenumber="79"> + + + <code class="ruby"> 'hints' => hints</code> + </li> + + <li class="never" data-hits="" data-linenumber="80"> + + + <code class="ruby"> }]</code> + </li> + + <li class="never" data-hits="" data-linenumber="81"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="82"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="2" data-linenumber="83"> + <span class="hits">2</span> + + <code class="ruby"> { resources: Hash[resources] }</code> + </li> + + <li class="never" data-hits="" data-linenumber="84"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="85"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="86"> + <span class="hits">1</span> + + <code class="ruby"> def json_home?(env)</code> + </li> + + <li class="covered" data-hits="5" data-linenumber="87"> + <span class="hits">5</span> + + <code class="ruby"> env['HTTP_ACCEPT'.freeze] == 'application/json-home'.freeze</code> + </li> + + <li class="never" data-hits="" data-linenumber="88"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="89"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="90"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="4fa3e7e42191523754efec186ec8bfce3291040f"> + <div class="header"> + <h3>lib/travis/api/v3/services.rb</h3> + <h4><span class="green">100.0 %</span> covered</h4> + <div> + <b>5</b> relevant lines. + <span class="green"><b>5</b> lines covered</span> and + <span class="red"><b>0</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> module Services</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> def self.[](key)</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="4"> + <span class="hits">27</span> + + <code class="ruby"> return key if key.respond_to? :new</code> + </li> + + <li class="covered" data-hits="27" data-linenumber="5"> + <span class="hits">27</span> + + <code class="ruby"> const_get(key.to_s.camelize)</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="7"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="a6bb60f0c77473ac7b1a29920833a93a5c2cd7f7"> + <div class="header"> + <h3>lib/travis/api/v3/services/find_repository.rb</h3> + <h4><span class="red">78.57 %</span> covered</h4> + <div> + <b>14</b> relevant lines. + <span class="green"><b>11</b> lines covered</span> and + <span class="red"><b>3</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">module Travis::API::V3</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> class Services::FindRepository < Service</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> params :id, :github_id, :slug, optional: true</code> + </li> + + <li class="never" data-hits="" data-linenumber="4"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="5"> + <span class="hits">1</span> + + <code class="ruby"> def run</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="6"> + <span class="hits">18</span> + + <code class="ruby"> raise NotFound, :repository unless repository and access_control.visible? repository</code> + </li> + + <li class="covered" data-hits="8" data-linenumber="7"> + <span class="hits">8</span> + + <code class="ruby"> Result.new(:repository, repository)</code> + </li> + + <li class="never" data-hits="" data-linenumber="8"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="9"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="10"> + <span class="hits">1</span> + + <code class="ruby"> def repository</code> + </li> + + <li class="covered" data-hits="42" data-linenumber="11"> + <span class="hits">42</span> + + <code class="ruby"> raise EntityMissing, :repository if defined?(@repository) and @repository.nil?</code> + </li> + + <li class="covered" data-hits="42" data-linenumber="12"> + <span class="hits">42</span> + + <code class="ruby"> @repository ||= find_repository</code> + </li> + + <li class="never" data-hits="" data-linenumber="13"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="14"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="15"> + <span class="hits">1</span> + + <code class="ruby"> def find_repository</code> + </li> + + <li class="covered" data-hits="18" data-linenumber="16"> + <span class="hits">18</span> + + <code class="ruby"> return ::Repository.find_by_id(id) if id</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="17"> + + + <code class="ruby"> return ::Repository.find_by_github_id(github_id) if github_id</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="18"> + + + <code class="ruby"> return ::Repository.by_slug(slug).first if slug</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="19"> + + + <code class="ruby"> raise WrongParams</code> + </li> + + <li class="never" data-hits="" data-linenumber="20"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="21"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="22"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + <div class="source_table" id="dc5349ac13a7e081565d2ad293a276d468fd8b0b"> + <div class="header"> + <h3>lib/travis/private_key.rb</h3> + <h4><span class="red">50.0 %</span> covered</h4> + <div> + <b>10</b> relevant lines. + <span class="green"><b>5</b> lines covered</span> and + <span class="red"><b>5</b> lines missed.</span> + </div> + </div> + + <pre> + <ol> + + <li class="covered" data-hits="1" data-linenumber="1"> + <span class="hits">1</span> + + <code class="ruby">class PrivateKey</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="2"> + <span class="hits">1</span> + + <code class="ruby"> attr_reader :key</code> + </li> + + <li class="covered" data-hits="1" data-linenumber="3"> + <span class="hits">1</span> + + <code class="ruby"> def initialize(key)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="4"> + + + <code class="ruby"> @key = key</code> + </li> + + <li class="never" data-hits="" data-linenumber="5"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="6"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="7"> + <span class="hits">1</span> + + <code class="ruby"> def fingerprint</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="8"> + + + <code class="ruby"> rsa_key = OpenSSL::PKey::RSA.new(key)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="9"> + + + <code class="ruby"> public_ssh_rsa = "\x00\x00\x00\x07ssh-rsa" + rsa_key.e.to_s(0) + rsa_key.n.to_s(0)</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="10"> + + + <code class="ruby"> OpenSSL::Digest::MD5.new(public_ssh_rsa).hexdigest.scan(/../).join(':')</code> + </li> + + <li class="never" data-hits="" data-linenumber="11"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="12"> + + + <code class="ruby"></code> + </li> + + <li class="covered" data-hits="1" data-linenumber="13"> + <span class="hits">1</span> + + <code class="ruby"> def inspect</code> + </li> + + <li class="missed" data-hits="0" data-linenumber="14"> + + + <code class="ruby"> "<PrivateKey #{fingerprint}>"</code> + </li> + + <li class="never" data-hits="" data-linenumber="15"> + + + <code class="ruby"> end</code> + </li> + + <li class="never" data-hits="" data-linenumber="16"> + + + <code class="ruby">end</code> + </li> + + </ol> + </pre> +</div> + + </div> + </div> + </body> +</html> diff --git a/Gemfile b/Gemfile index 26dabac1..647a0e86 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,7 @@ gem 'pry' gem 'metriks', '0.9.9.6' gem 'metriks-librato_metrics', github: 'eric/metriks-librato_metrics' gem 'micro_migrations' +gem 'simplecov' group :test do gem 'rspec', '~> 2.13' diff --git a/Gemfile.lock b/Gemfile.lock index 6d9c30fc..96594a19 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -43,7 +43,7 @@ GIT GIT remote: git://github.com/travis-ci/travis-core.git - revision: cbfb6da8a1c6f4cc80c40b260d4d2708e3acec03 + revision: a0aa1e2f79d45a4c59c1046a5435fe598eda2d2a specs: travis-core (0.0.1) actionmailer (~> 3.2.19) @@ -89,7 +89,6 @@ PATH remote: . specs: travis-api (0.0.1) - backports (~> 2.5) memcachier mustermann (~> 0.4) pg (~> 0.13.2) @@ -140,7 +139,7 @@ GEM descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) - backports (2.8.2) + backports (3.6.4) builder (3.0.4) bunny (0.8.0) celluloid (0.12.0) @@ -172,19 +171,20 @@ GEM descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) diff-lcs (1.2.5) + docile (1.1.5) dotenv (0.7.0) equalizer (0.0.9) erubis (2.7.0) - eventmachine (1.0.3) + eventmachine (1.0.4) factory_girl (2.4.2) activesupport - faraday (0.9.0) + faraday (0.9.1) multipart-post (>= 1.2, < 3) ffi (1.9.6) foreman (0.64.0) dotenv (~> 0.7.0) thor (>= 0.13.6) - gh (0.13.2) + gh (0.13.3) addressable backports faraday (~> 0.8) @@ -291,6 +291,11 @@ GEM simple_states (1.0.1) activesupport hashr (~> 0.0.10) + simplecov (0.9.1) + docile (~> 1.1.0) + multi_json (~> 1.0) + simplecov-html (~> 0.8.0) + simplecov-html (0.8.0) sinatra (1.4.5) rack (~> 1.4) rack-protection (~> 1.4) @@ -365,6 +370,7 @@ DEPENDENCIES rerun rspec (~> 2.13) sentry-raven! + simplecov sinatra sinatra-contrib travis-api! diff --git a/lib/travis/api/app.rb b/lib/travis/api/app.rb index dc2d6105..d9c3c4ac 100644 --- a/lib/travis/api/app.rb +++ b/lib/travis/api/app.rb @@ -2,7 +2,6 @@ require 'travis' require 'travis/model' require 'travis/support/amqp' require 'travis/states_cache' -require 'backports' require 'rack' require 'rack/protection' require 'rack/contrib' @@ -197,8 +196,8 @@ module Travis::Api end def self.load_endpoints - Backports.require_relative_dir 'app/middleware' - Backports.require_relative_dir 'app/endpoint' + Dir.glob("#{__dir__}/app/middleware/*.rb").each { |f| require f[%r[(?<=lib/).+(?=\.rb$)]] } + Dir.glob("#{__dir__}/app/endpoint/*.rb").each { |f| require f[%r[(?<=lib/).+(?=\.rb$)]] } end def self.setup_endpoints diff --git a/lib/travis/api/app/extensions.rb b/lib/travis/api/app/extensions.rb index dd189114..d7faa8fe 100644 --- a/lib/travis/api/app/extensions.rb +++ b/lib/travis/api/app/extensions.rb @@ -3,6 +3,6 @@ require 'travis/api/app' class Travis::Api::App # Namespace for Sinatra extensions. module Extensions - Backports.require_relative_dir 'extensions' + Dir.glob("#{__dir__}/extensions/*.rb").each { |f| require f[%r[(?<=lib/).+(?=\.rb$)]] } end end diff --git a/lib/travis/api/app/helpers.rb b/lib/travis/api/app/helpers.rb index a009b025..e09bbd8f 100644 --- a/lib/travis/api/app/helpers.rb +++ b/lib/travis/api/app/helpers.rb @@ -3,6 +3,6 @@ require 'travis/api/app' class Travis::Api::App # Namespace for helpers. module Helpers - Backports.require_relative_dir 'helpers' + Dir.glob("#{__dir__}/helpers/*.rb").each { |f| require f[%r[(?<=lib/).+(?=\.rb$)]] } end end diff --git a/lib/travis/api/v3.rb b/lib/travis/api/v3.rb index 3d640a5e..bd63d030 100644 --- a/lib/travis/api/v3.rb +++ b/lib/travis/api/v3.rb @@ -11,11 +11,17 @@ module Travis def response(payload, headers = {}, content_type: 'application/json'.freeze, status: 200) payload = JSON.pretty_generate(payload) unless payload.is_a? String headers = { 'Content-Type'.freeze => content_type, 'Content-Length'.freeze => payload.bytesize.to_s }.merge!(headers) - [200, headers, [payload] ] + [status, headers, [payload] ] end extend self load_dir("#{__dir__}/v3") + + ClientError = Error .create(status: 400) + NotFound = ClientError .create(:resource, status: 404, template: '%s not found (or insufficient access)') + EnitityMissing = NotFound .create(type: 'not_found') + WrongCredentials = ClientError .create('access denied', status: 403) + WrongParams = ClientError .create('wrong parameters') end end end diff --git a/lib/travis/api/v3/access_control/legacy_token.rb b/lib/travis/api/v3/access_control/legacy_token.rb index 6e17408e..f07d936c 100644 --- a/lib/travis/api/v3/access_control/legacy_token.rb +++ b/lib/travis/api/v3/access_control/legacy_token.rb @@ -21,7 +21,7 @@ module Travis::API::V3 protected def permission?(action, id) - super if token.scopes.include? :private + super if @token.scopes.include? :private end end end diff --git a/lib/travis/api/v3/access_control/scoped.rb b/lib/travis/api/v3/access_control/scoped.rb index 33160381..5bf1df90 100644 --- a/lib/travis/api/v3/access_control/scoped.rb +++ b/lib/travis/api/v3/access_control/scoped.rb @@ -13,7 +13,7 @@ module Travis::API::V3 def private_repository_visible?(repository) return false if name and repository.name != name - unscoped.private_repository_visible?(repository) if repository.owner_name == owner_name + unscoped.visible?(repository) if repository.owner_name == owner_name end end end diff --git a/lib/travis/api/v3/access_control/signature.rb b/lib/travis/api/v3/access_control/signature.rb index 5ec284cf..b07baa05 100644 --- a/lib/travis/api/v3/access_control/signature.rb +++ b/lib/travis/api/v3/access_control/signature.rb @@ -18,11 +18,14 @@ module Travis::API::V3 end if application = options[?a.freeze] - return unless Travis.config.application and app_config = Travis.config.applications[application] + return unless Travis.config.applications and app_config = Travis.config.applications[application] + end + + if c = options[?c.freeze] + challenge << env['REQUEST_METHOD'.freeze] << "\n".freeze if c.include?(?m.freeze) + challenge << env['SCRIPT_NAME'.freeze] << env['PATH_INFO'.freeze] << "\n" if c.include?(?p.freeze) end - challenge << env['REQUEST_METHOD'.freeze] << "\n".freeze if options[?c.freeeze].include?(?m.freeze) - challenge << env['SCRIPT_NAME'.freeze] << env['PATH_INFO'.freeze] << "\n" if options[?c.freeeze].include?(?p.freeze) challenge << app_config[:secret] if app_config and user challenge << args.join(?:.freeze) @@ -35,7 +38,7 @@ module Travis::API::V3 end if scope = options[?s.freeze] - control &&= Scoped.new(scope, control) + control &&= AccessControl::Scoped.new(scope, control) end control if secrets.any? { |secret| signed(challenge, secret) == signature } @@ -48,7 +51,7 @@ module Travis::API::V3 ] end - def signed(challenge, secret) + def self.signed(challenge, secret) OpenSSL::HMAC.hexdigest('sha256'.freeze, secret, challenge) end end diff --git a/lib/travis/api/v3/access_control/user.rb b/lib/travis/api/v3/access_control/user.rb index a735b81f..d6881a1f 100644 --- a/lib/travis/api/v3/access_control/user.rb +++ b/lib/travis/api/v3/access_control/user.rb @@ -13,12 +13,12 @@ module Travis::API::V3 protected def private_repository_visible?(repository) - permissions?(:pull, repository) + permission?(:pull, repository) end def permission?(type, id) id = id.id if id.is_a? ::Repository - permissions.where(type => trye, :repository_id => id).any? + permissions.where(type => true, :repository_id => id).any? end end end diff --git a/lib/travis/api/v3/error.rb b/lib/travis/api/v3/error.rb new file mode 100644 index 00000000..fe098a9b --- /dev/null +++ b/lib/travis/api/v3/error.rb @@ -0,0 +1,38 @@ +require 'rack/utils' + +module Travis::API::V3 + class Error < StandardError + def self.create(default_message = nil, **options) + options[:default_message] = default_message if default_message + Class.new(self) { options.each { |key, value| define_singleton_method(key) { value } } } + end + + def self.status + 500 + end + + def self.type + @type ||= name[/[^:]+$/].underscore + end + + def self.template + '%s'.freeze + end + + def self.default_message + @default_message ||= Rack::Utils::HTTP_STATUS_CODES.fetch(status, 'unknown error'.freeze).downcase + end + + attr_accessor :status, :type, :payload + + def initialize(message = self.class.default_message, status: self.class.status, type: self.class.type, **payload) + if message.is_a? Symbol + payload[:resource_type] ||= message + message = self.class.template % message + end + + self.status, self.type, self.payload = status, type, payload + super(message) + end + end +end diff --git a/lib/travis/api/v3/renderer/error.rb b/lib/travis/api/v3/renderer/error.rb new file mode 100644 index 00000000..d913e139 --- /dev/null +++ b/lib/travis/api/v3/renderer/error.rb @@ -0,0 +1,14 @@ +module Travis::API::V3 + module Renderer::Error + extend self + + def render(error) + { + :@type => 'error'.freeze, + :error_type => error.type, + :error_message => error.message, + **error.payload + } + end + end +end diff --git a/lib/travis/api/v3/router.rb b/lib/travis/api/v3/router.rb index d522410e..a0fb3678 100644 --- a/lib/travis/api/v3/router.rb +++ b/lib/travis/api/v3/router.rb @@ -1,16 +1,10 @@ module Travis::API::V3 class Router include Travis::API::V3 + attr_accessor :routes - not_found = '{"error":{"message":"not found"}}'.freeze - headers = { 'Content-Type'.freeze => 'application/json'.freeze, 'X-Cascade'.freeze => 'pass'.freeze, 'Content-Length'.freeze => not_found.bytesize.to_s } - NOT_FOUND = [ 404, headers, [not_found] ] - - attr_accessor :routes, :not_found - - def initialize(routes = Routes, not_found: NOT_FOUND) - @routes = routes - @not_found = not_found + def initialize(routes = Routes) + @routes = routes routes.draw_routes end @@ -19,13 +13,15 @@ module Travis::API::V3 access_control = AccessControl.new(env) factory, params = routes.factory_for(env['REQUEST_METHOD'.freeze], env['PATH_INFO'.freeze]) env_params = params(env) - if factory - service = factory.new(access_control, env_params.merge(params)) - result = service.run - render(result, env_params) - else - NOT_FOUND - end + + raise NotFound unless factory + + service = factory.new(access_control, env_params.merge(params)) + result = service.run + render(result, env_params) + rescue Error => error + result = Result.new(:error, error) + V3.response(result.render, 'X-Cascade'.freeze => 'pass'.freeze, status: error.status) end def render(result, env_params) diff --git a/lib/travis/api/v3/services/find_repository.rb b/lib/travis/api/v3/services/find_repository.rb index 73d3a68a..5db62e60 100644 --- a/lib/travis/api/v3/services/find_repository.rb +++ b/lib/travis/api/v3/services/find_repository.rb @@ -3,12 +3,12 @@ module Travis::API::V3 params :id, :github_id, :slug, optional: true def run - raise NotFound unless repository and access_control.visible? repository + raise NotFound, :repository unless repository and access_control.visible? repository Result.new(:repository, repository) end def repository - raise EntityMissing if defined?(@repository) and @repository.nil? + raise EntityMissing, :repository if defined?(@repository) and @repository.nil? @repository ||= find_repository end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e41dbdf2..ced5e7af 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,7 @@ ENV['RACK_ENV'] = ENV['RAILS_ENV'] = ENV['ENV'] = 'test' +require 'support/coverage' + require 'rspec' require 'database_cleaner' require 'sinatra/test_helpers' diff --git a/spec/support/coverage.rb b/spec/support/coverage.rb new file mode 100644 index 00000000..f5b93400 --- /dev/null +++ b/spec/support/coverage.rb @@ -0,0 +1,7 @@ +require 'simplecov' + +SimpleCov.start do + coverage_dir '.coverage' + add_filter "/spec/" + add_group "v3", "lib/travis/api/v3" +end diff --git a/spec/v3/result_spec.rb b/spec/v3/result_spec.rb new file mode 100644 index 00000000..b66945b3 --- /dev/null +++ b/spec/v3/result_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe Travis::API::V3::Result do + subject(:result) { described_class.new(:example) } + + example { expect(result.type) .to be == :example } + example { expect(result.resource) .to be == [] } + example { expect(result.example) .to be == [] } + + example do + result << 42 + expect(result.example).to include(42) + end +end diff --git a/spec/v3/service_index_spec.rb b/spec/v3/service_index_spec.rb new file mode 100644 index 00000000..8faa4b24 --- /dev/null +++ b/spec/v3/service_index_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe Travis::API::V3::ServiceIndex do + let(:headers) {{ }} + let(:path) { '/' } + let(:json) { JSON.load(response.body) } + let(:response) { get(path, {}, headers) } + + describe "custom json entry point" do + let(:expected_resources) {{ + "repository" => { + "find" => [{"request-method"=>"GET", "uri-template"=>"#{path}repo/{id}"}] + } + }} + + describe 'with /v3 prefix' do + let(:path) { '/v3/' } + specify(:resources) { expect(json['resources']).to be == expected_resources } + end + + describe 'with Accept header' do + let(:headers) { { 'HTTP_ACCEPT' => 'application/vnd.travis-ci.3+json' } } + specify(:resources) { expect(json['resources']).to be == expected_resources } + end + + describe 'with Travis-API-Version header' do + let(:headers) { { 'HTTP_TRAVIS_API_VERSION' => '3' } } + specify(:resources) { expect(json['resources']).to be == expected_resources } + end + end + + describe "json-home document" do + describe 'with /v3 prefix' do + let(:headers) { { 'HTTP_ACCEPT' => 'application/json-home' } } + let(:path) { '/v3/' } + specify(:resources) { expect(json['resources']).to include("http://schema.travis-ci.com/rel/repository/find") } + end + + describe 'with Travis-API-Version header' do + let(:headers) { { 'HTTP_ACCEPT' => 'application/json-home', 'HTTP_TRAVIS_API_VERSION' => '3' } } + specify(:resources) { expect(json['resources']).to include("http://schema.travis-ci.com/rel/repository/find") } + end + end +end diff --git a/spec/v3/services/find_repository_spec.rb b/spec/v3/services/find_repository_spec.rb new file mode 100644 index 00000000..af0ce98a --- /dev/null +++ b/spec/v3/services/find_repository_spec.rb @@ -0,0 +1,211 @@ +require 'spec_helper' + +describe Travis::API::V3::Services::FindRepository do + let(:repo) { Repository.by_slug('svenfuchs/minimal').first } + + describe "public repository" do + before { get("/v3/repo/#{repo.id}") } + example { expect(last_response).to be_ok } + example { expect(JSON.load(body)).to be == { + "@type" => "repository", + "id" => repo.id, + "name" => "minimal", + "slug" => "svenfuchs/minimal", + "description" => nil, + "github_language" => nil, + "private" => false, + "owner" => { + "@type" => "user", + "id" => repo.owner_id, + "login" => "svenfuchs" }, + "last_build" => { + "@type" => "build", + "id" => repo.last_build_id, + "number" => "2", + "state" => "passed", + "duration" => nil, + "started_at" => "2010-11-12T12:30:00Z", + "finished_at" => "2010-11-12T12:30:20Z"} + }} + end + + describe "missing repository" do + before { get("/v3/repo/999999999999999") } + example { expect(last_response).to be_not_found } + example { expect(JSON.load(body)).to be == { + "@type" => "error", + "error_type" => "not_found", + "error_message" => "repository not found (or insufficient access)", + "resource_type" => "repository" + }} + end + + describe "public repository, private API" do + before { Travis.config.private_api = true } + before { get("/v3/repo/#{repo.id}") } + after { Travis.config.private_api = true } + example { expect(last_response).to be_not_found } + example { expect(JSON.load(body)).to be == { + "@type" => "error", + "error_type" => "not_found", + "error_message" => "repository not found (or insufficient access)", + "resource_type" => "repository" + }} + end + + describe "private repository, not authenticated" do + before { repo.update_attribute(:private, true) } + before { get("/v3/repo/#{repo.id}") } + before { repo.update_attribute(:private, false) } + example { expect(last_response).to be_not_found } + example { expect(JSON.load(body)).to be == { + "@type" => "error", + "error_type" => "not_found", + "error_message" => "repository not found (or insufficient access)", + "resource_type" => "repository" + }} + end + + describe "private repository, private API, authenticated as user with access" do + let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + before { Permission.create(repository: repo, user: repo.owner, pull: true) } + before { repo.update_attribute(:private, true) } + before { get("/v3/repo/#{repo.id}", {}, headers) } + before { repo.update_attribute(:private, false) } + example { expect(last_response).to be_ok } + example { expect(JSON.load(body)).to be == { + "@type" => "repository", + "id" => repo.id, + "name" => "minimal", + "slug" => "svenfuchs/minimal", + "description" => nil, + "github_language" => nil, + "private" => true, + "owner" => { + "@type" => "user", + "id" => repo.owner_id, + "login" => "svenfuchs" }, + "last_build" => { + "@type" => "build", + "id" => repo.last_build_id, + "number" => "2", + "state" => "passed", + "duration" => nil, + "started_at" => "2010-11-12T12:30:00Z", + "finished_at" => "2010-11-12T12:30:20Z"} + }} + end + + describe "private repository, private API, authenticated as user without access" do + let(:token) { Travis::Api::App::AccessToken.create(user: User.find(2), app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + before { repo.update_attribute(:private, true) } + before { get("/v3/repo/#{repo.id}", {}, headers) } + before { repo.update_attribute(:private, false) } + example { expect(last_response).to be_not_found } + example { expect(JSON.load(body)).to be == { + "@type" => "error", + "error_type" => "not_found", + "error_message" => "repository not found (or insufficient access)", + "resource_type" => "repository" + }} + end + + describe "private repository, authenticated as internal application with full access" do + let(:app_name) { 'travis-example' } + let(:app_secret) { '12345678' } + let(:sign_opts) { "a=#{app_name}" } + let(:signature) { OpenSSL::HMAC.hexdigest('sha256', app_secret, sign_opts) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "signature #{sign_opts}:#{signature}" }} + before { Travis.config.applications = { app_name => { full_access: true, secret: app_secret }}} + + + before { repo.update_attribute(:private, true) } + before { get("/v3/repo/#{repo.id}", {}, headers) } + before { repo.update_attribute(:private, false) } + + + example { expect(last_response).to be_ok } + example { expect(JSON.load(body)).to be == { + "@type" => "repository", + "id" => repo.id, + "name" => "minimal", + "slug" => "svenfuchs/minimal", + "description" => nil, + "github_language" => nil, + "private" => true, + "owner" => { + "@type" => "user", + "id" => repo.owner_id, + "login" => "svenfuchs" }, + "last_build" => { + "@type" => "build", + "id" => repo.last_build_id, + "number" => "2", + "state" => "passed", + "duration" => nil, + "started_at" => "2010-11-12T12:30:00Z", + "finished_at" => "2010-11-12T12:30:20Z"} + }} + end + + describe "private repository, authenticated as internal application with full access, but scoped to a different org" do + let(:app_name) { 'travis-example' } + let(:app_secret) { '12345678' } + let(:sign_opts) { "a=#{app_name}:s=travis-pro" } + let(:signature) { OpenSSL::HMAC.hexdigest('sha256', app_secret, sign_opts) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "signature #{sign_opts}:#{signature}" }} + before { Travis.config.applications = { app_name => { full_access: true, secret: app_secret }}} + + before { repo.update_attribute(:private, true) } + before { get("/v3/repo/#{repo.id}", {}, headers) } + before { repo.update_attribute(:private, false) } + + example { expect(last_response).to be_not_found } + example { expect(JSON.load(body)).to be == { + "@type" => "error", + "error_type" => "not_found", + "error_message" => "repository not found (or insufficient access)", + "resource_type" => "repository" + }} + end + + describe "private repository, authenticated as internal application with full access, scoped to the right org" do + let(:app_name) { 'travis-example' } + let(:app_secret) { '12345678' } + let(:sign_opts) { "a=#{app_name}:s=#{repo.owner_name}" } + let(:signature) { OpenSSL::HMAC.hexdigest('sha256', app_secret, sign_opts) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "signature #{sign_opts}:#{signature}" }} + before { Travis.config.applications = { app_name => { full_access: true, secret: app_secret }}} + + + before { repo.update_attribute(:private, true) } + before { get("/v3/repo/#{repo.id}", {}, headers) } + before { repo.update_attribute(:private, false) } + + + example { expect(last_response).to be_ok } + example { expect(JSON.load(body)).to be == { + "@type" => "repository", + "id" => repo.id, + "name" => "minimal", + "slug" => "svenfuchs/minimal", + "description" => nil, + "github_language" => nil, + "private" => true, + "owner" => { + "@type" => "user", + "id" => repo.owner_id, + "login" => "svenfuchs" }, + "last_build" => { + "@type" => "build", + "id" => repo.last_build_id, + "number" => "2", + "state" => "passed", + "duration" => nil, + "started_at" => "2010-11-12T12:30:00Z", + "finished_at" => "2010-11-12T12:30:20Z"} + }} + end +end \ No newline at end of file diff --git a/travis-api.gemspec b/travis-api.gemspec index f4ffa7d3..f84e0bf3 100644 --- a/travis-api.gemspec +++ b/travis-api.gemspec @@ -165,11 +165,15 @@ Gem::Specification.new do |s| "lib/travis/api/v3/access_control/signature.rb", "lib/travis/api/v3/access_control/user.rb", "lib/travis/api/v3/opt_in.rb", + "lib/travis/api/v3/renderer.rb", + "lib/travis/api/v3/renderer/repository.rb", "lib/travis/api/v3/result.rb", "lib/travis/api/v3/router.rb", "lib/travis/api/v3/routes.rb", "lib/travis/api/v3/routes/dsl.rb", + "lib/travis/api/v3/routes/resource.rb", "lib/travis/api/v3/service.rb", + "lib/travis/api/v3/service_index.rb", "lib/travis/api/v3/services.rb", "lib/travis/api/v3/services/find_repository.rb", "lib/travis/private_key.rb", @@ -272,7 +276,6 @@ Gem::Specification.new do |s| s.add_dependency 'travis-support' s.add_dependency 'travis-core' - s.add_dependency 'backports', '~> 2.5' s.add_dependency 'pg', '~> 0.13.2' s.add_dependency 'thin', '~> 1.4' s.add_dependency 'sinatra', '~> 1.3'