text:
require 'spec_helper'

describe API::Runners do
  let(:admin) { create(:user, :admin) }
  let(:user) { create(:user) }
  let(:user2) { create(:user) }

  let(:project) { create(:project, creator_id: user.id) }
  let(:project2) { create(:project, creator_id: user.id) }

  let(:group) { create(:group).tap { |group| group.add_owner(user) } }
  let(:group2) { create(:group).tap { |group| group.add_owner(user) } }

  let!(:shared_runner) { create(:ci_runner, :instance, description: 'Shared runner') }
  let!(:project_runner) { create(:ci_runner, :project, description: 'Project runner', projects: [project]) }
  let!(:two_projects_runner) { create(:ci_runner, :project, description: 'Two projects runner', projects: [project, project2]) }
  let!(:group_runner) { create(:ci_runner, :group, description: 'Group runner', groups: [group]) }

  before do
    # Set project access for users
    create(:project_member, :maintainer, user: user, project: project)
    create(:project_member, :maintainer, user: user, project: project2)
    create(:project_member, :reporter, user: user2, project: project)
  end

  describe 'GET /runners' do
    context 'authorized user' do
      it 'returns response status and headers' do
        get api('/runners', user)

        expect(response).to have_gitlab_http_status(200)
        expect(response).to include_pagination_headers
      end

      it 'returns user available runners' do
        get api('/runners', user)

        expect(json_response).to match_array [
          a_hash_including('description' => 'Project runner'),
          a_hash_including('description' => 'Two projects runner'),
          a_hash_including('description' => 'Group runner')
        ]
      end

      it 'filters runners by scope' do
        create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])

        get api('/runners?scope=paused', user)

        expect(response).to have_gitlab_http_status(200)
        expect(response).to include_pagination_headers

        expect(json_response).to match_array [
          a_hash_including('description' => 'Inactive project runner')
        ]
      end

      it 'avoids filtering if scope is invalid' do
        get api('/runners?scope=unknown', user)
        expect(response).to have_gitlab_http_status(400)
      end

      it 'filters runners by type' do
        get api('/runners?type=project_type', user)

        expect(json_response).to match_array [
          a_hash_including('description' => 'Project runner'),
          a_hash_including('description' => 'Two projects runner')
        ]
      end

      it 'does not filter by invalid type' do
        get api('/runners?type=bogus', user)

        expect(response).to have_gitlab_http_status(400)
      end

      it 'filters runners by status' do
        create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])

        get api('/runners?status=paused', user)

        expect(json_response).to match_array [
          a_hash_including('description' => 'Inactive project runner')
        ]
      end

      it 'does not filter by invalid status' do
        get api('/runners?status=bogus', user)

        expect(response).to have_gitlab_http_status(400)
      end
    end

    context 'unauthorized user' do
      it 'does not return runners' do
        get api('/runners')

        expect(response).to have_gitlab_http_status(401)
      end
    end
  end

  describe 'GET /runners/all' do
    context 'authorized user' do
      context 'with admin privileges' do
        it 'returns response status and headers' do
          get api('/runners/all', admin)

          expect(response).to have_gitlab_http_status(200)
          expect(response).to include_pagination_headers
        end

        it 'returns all runners' do
          get api('/runners/all', admin)

          expect(json_response).to match_array [
            a_hash_including('description' => 'Project runner'),
            a_hash_including('description' => 'Two projects runner'),
            a_hash_including('description' => 'Group runner'),
            a_hash_including('description' => 'Shared runner')
          ]
        end

        it 'filters runners by scope' do
          get api('/runners/all?scope=shared', admin)

          shared = json_response.all? { |r| r['is_shared'] }
          expect(response).to have_gitlab_http_status(200)
          expect(response).to include_pagination_headers
          expect(json_response).to be_an Array
          expect(json_response[0]).to have_key('ip_address')
          expect(shared).to be_truthy
        end

        it 'filters runners by scope' do
          get api('/runners/all?scope=specific', admin)

          expect(response).to have_gitlab_http_status(200)
          expect(response).to include_pagination_headers

          expect(json_response).to match_array [
            a_hash_including('description' => 'Project runner'),
            a_hash_including('description' => 'Two projects runner'),
            a_hash_including('description' => 'Group runner')
          ]
        end

        it 'avoids filtering if scope is invalid' do
          get api('/runners/all?scope=unknown', admin)
          expect(response).to have_gitlab_http_status(400)
        end

        it 'filters runners by type' do
          get api('/runners/all?type=project_type', admin)

          expect(json_response).to match_array [
            a_hash_including('description' => 'Project runner'),
            a_hash_including('description' => 'Two projects runner')
          ]
        end

        it 'does not filter by invalid type' do
          get api('/runners/all?type=bogus', admin)

          expect(response).to have_gitlab_http_status(400)
        end

        it 'filters runners by status' do
          create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])

          get api('/runners/all?status=paused', admin)

          expect(json_response).to match_array [
            a_hash_including('description' => 'Inactive project runner')
          ]
        end

        it 'does not filter by invalid status' do
          get api('/runners/all?status=bogus', admin)

          expect(response).to have_gitlab_http_status(400)
        end
      end

      context 'without admin privileges' do
        it 'does not return runners list' do
          get api('/runners/all', user)

          expect(response).to have_gitlab_http_status(403)
        end
      end
    end

    context 'unauthorized user' do
      it 'does not return runners' do
        get api('/runners')

        expect(response).to have_gitlab_http_status(401)
      end
    end
  end

  describe 'GET /runners/:id' do
    context 'admin user' do
      context 'when runner is shared' do
        it "returns runner's details" do
          get api("/runners/#{shared_runner.id}", admin)

          expect(response).to have_gitlab_http_status(200)
          expect(json_response['description']).to eq(shared_runner.description)
          expect(json_response['maximum_timeout']).to be_nil
        end
      end

      context 'when runner is not shared' do
        context 'when unused runner is present' do
          let!(:unused_project_runner) { create(:ci_runner, :project, :without_projects) }

          it 'deletes unused runner' do
            expect do
              delete api("/runners/#{unused_project_runner.id}", admin)

              expect(response).to have_gitlab_http_status(204)
            end.to change { Ci::Runner.project_type.count }.by(-1)
          end
        end

        it "returns runner's details" do
          get api("/runners/#{project_runner.id}", admin)

          expect(response).to have_gitlab_http_status(200)
          expect(json_response['description']).to eq(project_runner.description)
        end

        it "returns the project's details for a project runner" do
          get api("/runners/#{project_runner.id}", admin)

          expect(json_response['projects'].first['id']).to eq(project.id)
        end
      end

      it 'returns 404 if runner does not exists' do
        get api('/runners/9999', admin)

        expect(response).to have_gitlab_http_status(404)
      end
    end

    context "runner project's administrative user" do
      context 'when runner is not shared' do
        it "returns runner's details" do
          get api("/runners/#{project_runner.id}", user)

          expect(response).to have_gitlab_http_status(200)
          expect(json_response['description']).to eq(project_runner.description)
        end
      end

      context 'when runner is shared' do
        it "returns runner's details" do
          get api("/runners/#{shared_runner.id}", user)

          expect(response).to have_gitlab_http_status(200)
          expect(json_response['description']).to eq(shared_runner.description)
        end
      end
    end

    context 'other authorized user' do
      it "does not return project runner's details" do
        get api("/runners/#{project_runner.id}", user2)

        expect(response).to have_http_status(403)
      end
    end

    context 'unauthorized user' do
      it "does not return project runner's details" do
        get api("/runners/#{project_runner.id}")

        expect(response).to have_http_status(401)
      end
    end
  end

  describe 'PUT /runners/:id' do
    context 'admin user' do
      # see https://gitlab.com/gitlab-org/gitlab-ce/issues/48625
      context 'single parameter update' do
        it 'runner description' do
          description = shared_runner.description
          update_runner(shared_runner.id, admin, description: "#{description}_updated")

          expect(response).to have_gitlab_http_status(200)
          expect(shared_runner.reload.description).to eq("#{description}_updated")
        end

        it 'runner active state' do
          active = shared_runner.active
          update_runner(shared_runner.id, admin, active: !active)

          expect(response).to have_gitlab_http_status(200)
          expect(shared_runner.reload.active).to eq(!active)
        end

        it 'runner tag list' do
          update_runner(shared_runner.id, admin, tag_list: ['ruby2.1', 'pgsql', 'mysql'])

          expect(response).to have_gitlab_http_status(200)
          expect(shared_runner.reload.tag_list).to include('ruby2.1', 'pgsql', 'mysql')
        end

        it 'runner untagged flag' do
          # Ensure tag list is non-empty before setting untagged to false.
          update_runner(shared_runner.id, admin, tag_list: ['ruby2.1', 'pgsql', 'mysql'])
          update_runner(shared_runner.id, admin, run_untagged: 'false')

          expect(response).to have_gitlab_http_status(200)
          expect(shared_runner.reload.run_untagged?).to be(false)
        end

        it 'runner unlocked flag' do
          update_runner(shared_runner.id, admin, locked: 'true')

          expect(response).to have_gitlab_http_status(200)
          expect(shared_runner.reload.locked?).to be(true)
        end

        it 'runner access level' do
          update_runner(shared_runner.id, admin, access_level: 'ref_protected')

          expect(response).to have_gitlab_http_status(200)
          expect(shared_runner.reload.ref_protected?).to be_truthy
        end

        it 'runner maximum timeout' do
          update_runner(shared_runner.id, admin, maximum_timeout: 1234)

          expect(response).to have_gitlab_http_status(200)
          expect(shared_runner.reload.maximum_timeout).to eq(1234)
        end

        it 'fails with no parameters' do
          put api("/runners/#{shared_runner.id}", admin)

          shared_runner.reload
          expect(response).to have_gitlab_http_status(400)
        end
      end

      context 'when runner is shared' do
        it 'updates runner' do
          description = shared_runner.description
          active = shared_runner.active
          runner_queue_value = shared_runner.ensure_runner_queue_value

          update_runner(shared_runner.id, admin, description: "#{description}_updated",
                                                 active: !active,
                                                 tag_list: ['ruby2.1', 'pgsql', 'mysql'],
                                                 run_untagged: 'false',
                                                 locked: 'true',
                                                 access_level: 'ref_protected',
                                                 maximum_timeout: 1234)
          shared_runner.reload

          expect(response).to have_gitlab_http_status(200)
          expect(shared_runner.description).to eq("#{description}_updated")
          expect(shared_runner.active).to eq(!active)
          expect(shared_runner.tag_list).to include('ruby2.1', 'pgsql', 'mysql')
          expect(shared_runner.run_untagged?).to be(false)
          expect(shared_runner.locked?).to be(true)
          expect(shared_runner.ref_protected?).to be_truthy
          expect(shared_runner.ensure_runner_queue_value)
            .not_to eq(runner_queue_value)
          expect(shared_runner.maximum_timeout).to eq(1234)
        end
      end

      context 'when runner is not shared' do
        it 'updates runner' do
          description = project_runner.description
          runner_queue_value = project_runner.ensure_runner_queue_value

          update_runner(project_runner.id, admin, description: 'test')
          project_runner.reload

          expect(response).to have_gitlab_http_status(200)
          expect(project_runner.description).to eq('test')
          expect(project_runner.description).not_to eq(description)
          expect(project_runner.ensure_runner_queue_value)
            .not_to eq(runner_queue_value)
        end
      end

      it 'returns 404 if runner does not exists' do
        update_runner(9999, admin, description: 'test')

        expect(response).to have_gitlab_http_status(404)
      end

      def update_runner(id, user, args)
        put api("/runners/#{id}", user), params: args
      end
    end

    context 'authorized user' do
      context 'when runner is shared' do
        it 'does not update runner' do
          put api("/runners/#{shared_runner.id}", user), params: { description: 'test' }

          expect(response).to have_gitlab_http_status(403)
        end
      end

      context 'when runner is not shared' do
        it 'does not update project runner without access to it' do
          put api("/runners/#{project_runner.id}", user2), params: { description: 'test' }

          expect(response).to have_http_status(403)
        end

        it 'updates project runner with access to it' do
          description = project_runner.description
          put api("/runners/#{project_runner.id}", admin), params: { description: 'test' }
          project_runner.reload

          expect(response).to have_gitlab_http_status(200)
          expect(project_runner.description).to eq('test')
          expect(project_runner.description).not_to eq(description)
        end
      end
    end

    context 'unauthorized user' do
      it 'does not delete project runner' do
        put api("/runners/#{project_runner.id}")

        expect(response).to have_http_status(401)
      end
    end
  end

  describe 'DELETE /runners/:id' do
    context 'admin user' do
      context 'when runner is shared' do
        it 'deletes runner' do
          expect do
            delete api("/runners/#{shared_runner.id}", admin)

            expect(response).to have_gitlab_http_status(204)
          end.to change { Ci::Runner.instance_type.count }.by(-1)
        end

        it_behaves_like '412 response' do
          let(:request) { api("/runners/#{shared_runner.id}", admin) }
        end
      end

      context 'when runner is not shared' do
        it 'deletes used project runner' do
          expect do
            delete api("/runners/#{project_runner.id}", admin)

            expect(response).to have_http_status(204)
          end.to change { Ci::Runner.project_type.count }.by(-1)
        end
      end

      it 'returns 404 if runner does not exists' do
        delete api('/runners/9999', admin)

        expect(response).to have_gitlab_http_status(404)
      end
    end

    context 'authorized user' do
      context 'when runner is shared' do
        it 'does not delete runner' do
          delete api("/runners/#{shared_runner.id}", user)
          expect(response).to have_gitlab_http_status(403)
        end
      end

      context 'when runner is not shared' do
        it 'does not delete runner without access to it' do
          delete api("/runners/#{project_runner.id}", user2)
          expect(response).to have_gitlab_http_status(403)
        end

        it 'does not delete project runner with more than one associated project' do
          delete api("/runners/#{two_projects_runner.id}", user)
          expect(response).to have_gitlab_http_status(403)
        end

        it 'deletes project runner for one owned project' do
          expect do
            delete api("/runners/#{project_runner.id}", user)

            expect(response).to have_http_status(204)
          end.to change { Ci::Runner.project_type.count }.by(-1)
        end

        it_behaves_like '412 response' do
          let(:request) { api("/runners/#{project_runner.id}", user) }
        end
      end
    end

    context 'unauthorized user' do
      it 'does not delete project runner' do
        delete api("/runners/#{project_runner.id}")

        expect(response).to have_http_status(401)
      end
    end
  end

  describe 'GET /runners/:id/jobs' do
    set(:job_1) { create(:ci_build) }
    let!(:job_2) { create(:ci_build, :running, runner: shared_runner, project: project) }
    let!(:job_3) { create(:ci_build, :failed, runner: shared_runner, project: project) }
    let!(:job_4) { create(:ci_build, :running, runner: project_runner, project: project) }
    let!(:job_5) { create(:ci_build, :failed, runner: project_runner, project: project) }

    context 'admin user' do
      context 'when runner exists' do
        context 'when runner is shared' do
          it 'return jobs' do
            get api("/runners/#{shared_runner.id}/jobs", admin)

            expect(response).to have_gitlab_http_status(200)
            expect(response).to include_pagination_headers

            expect(json_response).to be_an(Array)
            expect(json_response.length).to eq(2)
          end
        end

        context 'when runner is specific' do
          it 'return jobs' do
            get api("/runners/#{project_runner.id}/jobs", admin)

            expect(response).to have_gitlab_http_status(200)
            expect(response).to include_pagination_headers

            expect(json_response).to be_an(Array)
            expect(json_response.length).to eq(2)
          end
        end

        context 'when valid status is provided' do
          it 'return filtered jobs' do
            get api("/runners/#{project_runner.id}/jobs?status=failed", admin)

            expect(response).to have_gitlab_http_status(200)
            expect(response).to include_pagination_headers

            expect(json_response).to be_an(Array)
            expect(json_response.length).to eq(1)
            expect(json_response.first).to include('id' => job_5.id)
          end
        end

        context 'when invalid status is provided' do
          it 'return 400' do
            get api("/runners/#{project_runner.id}/jobs?status=non-existing", admin)

            expect(response).to have_gitlab_http_status(400)
          end
        end
      end

      context "when runner doesn't exist" do
        it 'returns 404' do
          get api('/runners/9999/jobs', admin)

          expect(response).to have_gitlab_http_status(404)
        end
      end
    end

    context "runner project's administrative user" do
      context 'when runner exists' do
        context 'when runner is shared' do
          it 'returns 403' do
            get api("/runners/#{shared_runner.id}/jobs", user)

            expect(response).to have_gitlab_http_status(403)
          end
        end

        context 'when runner is specific' do
          it 'return jobs' do
            get api("/runners/#{project_runner.id}/jobs", user)

            expect(response).to have_gitlab_http_status(200)
            expect(response).to include_pagination_headers

            expect(json_response).to be_an(Array)
            expect(json_response.length).to eq(2)
          end
        end

        context 'when valid status is provided' do
          it 'return filtered jobs' do
            get api("/runners/#{project_runner.id}/jobs?status=failed", user)

            expect(response).to have_gitlab_http_status(200)
            expect(response).to include_pagination_headers

            expect(json_response).to be_an(Array)
            expect(json_response.length).to eq(1)
            expect(json_response.first).to include('id' => job_5.id)
          end
        end

        context 'when invalid status is provided' do
          it 'return 400' do
            get api("/runners/#{project_runner.id}/jobs?status=non-existing", user)

            expect(response).to have_gitlab_http_status(400)
          end
        end
      end

      context "when runner doesn't exist" do
        it 'returns 404' do
          get api('/runners/9999/jobs', user)

          expect(response).to have_gitlab_http_status(404)
        end
      end
    end

    context 'other authorized user' do
      it 'does not return jobs' do
        get api("/runners/#{project_runner.id}/jobs", user2)

        expect(response).to have_gitlab_http_status(403)
      end
    end

    context 'unauthorized user' do
      it 'does not return jobs' do
        get api("/runners/#{project_runner.id}/jobs")

        expect(response).to have_gitlab_http_status(401)
      end
    end
  end

  describe 'GET /projects/:id/runners' do
    context 'authorized user with maintainer privileges' do
      it 'returns response status and headers' do
        get api('/runners/all', admin)

        expect(response).to have_gitlab_http_status(200)
        expect(response).to include_pagination_headers
      end

      it 'returns all runners' do
        get api("/projects/#{project.id}/runners", user)

        expect(json_response).to match_array [
          a_hash_including('description' => 'Project runner'),
          a_hash_including('description' => 'Two projects runner'),
          a_hash_including('description' => 'Shared runner')
        ]
      end

      it 'filters runners by scope' do
        get api("/projects/#{project.id}/runners?scope=specific", user)

        expect(response).to have_gitlab_http_status(200)
        expect(response).to include_pagination_headers

        expect(json_response).to match_array [
          a_hash_including('description' => 'Project runner'),
          a_hash_including('description' => 'Two projects runner')
        ]
      end

      it 'avoids filtering if scope is invalid' do
        get api("/projects/#{project.id}/runners?scope=unknown", user)
        expect(response).to have_gitlab_http_status(400)
      end

      it 'filters runners by type' do
        get api("/projects/#{project.id}/runners?type=project_type", user)

        expect(json_response).to match_array [
          a_hash_including('description' => 'Project runner'),
          a_hash_including('description' => 'Two projects runner')
        ]
      end

      it 'does not filter by invalid type' do
        get api("/projects/#{project.id}/runners?type=bogus", user)

        expect(response).to have_gitlab_http_status(400)
      end

      it 'filters runners by status' do
        create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])

        get api("/projects/#{project.id}/runners?status=paused", user)

        expect(json_response).to match_array [
          a_hash_including('description' => 'Inactive project runner')
        ]
      end

      it 'does not filter by invalid status' do
        get api("/projects/#{project.id}/runners?status=bogus", user)

        expect(response).to have_gitlab_http_status(400)
      end
    end

    context 'authorized user without maintainer privileges' do
      it "does not return project's runners" do
        get api("/projects/#{project.id}/runners", user2)

        expect(response).to have_gitlab_http_status(403)
      end
    end

    context 'unauthorized user' do
      it "does not return project's runners" do
        get api("/projects/#{project.id}/runners")

        expect(response).to have_gitlab_http_status(401)
      end
    end
  end

  describe 'POST /projects/:id/runners' do
    context 'authorized user' do
      let(:project_runner2) { create(:ci_runner, :project, projects: [project2]) }

      it 'enables specific runner' do
        expect do
          post api("/projects/#{project.id}/runners", user), params: { runner_id: project_runner2.id }
        end.to change { project.runners.count }.by(+1)
        expect(response).to have_gitlab_http_status(201)
      end

      it 'avoids changes when enabling already enabled runner' do
        expect do
          post api("/projects/#{project.id}/runners", user), params: { runner_id: project_runner.id }
        end.to change { project.runners.count }.by(0)
        expect(response).to have_gitlab_http_status(400)
      end

      it 'does not enable locked runner' do
        project_runner2.update(locked: true)

        expect do
          post api("/projects/#{project.id}/runners", user), params: { runner_id: project_runner2.id }
        end.to change { project.runners.count }.by(0)

        expect(response).to have_gitlab_http_status(403)
      end

      it 'does not enable shared runner' do
        post api("/projects/#{project.id}/runners", user), params: { runner_id: shared_runner.id }

        expect(response).to have_gitlab_http_status(403)
      end

      it 'does not enable group runner' do
        post api("/projects/#{project.id}/runners", user), params: { runner_id: group_runner.id }

        expect(response).to have_http_status(403)
      end

      context 'user is admin' do
        context 'when project runner is used' do
          let!(:new_project_runner) { create(:ci_runner, :project) }

          it 'enables any specific runner' do
            expect do
              post api("/projects/#{project.id}/runners", admin), params: { runner_id: new_project_runner.id }
            end.to change { project.runners.count }.by(+1)
            expect(response).to have_gitlab_http_status(201)
          end
        end

        it 'enables a instance type runner' do
          expect do
            post api("/projects/#{project.id}/runners", admin), params: { runner_id: shared_runner.id }
          end.to change { project.runners.count }.by(1)

          expect(shared_runner.reload).not_to be_instance_type
          expect(response).to have_gitlab_http_status(201)
        end
      end

      it 'raises an error when no runner_id param is provided' do
        post api("/projects/#{project.id}/runners", admin)

        expect(response).to have_gitlab_http_status(400)
      end
    end

    context 'user is not admin' do
      let!(:new_project_runner) { create(:ci_runner, :project) }

      it 'does not enable runner without access to' do
        post api("/projects/#{project.id}/runners", user), params: { runner_id: new_project_runner.id }

        expect(response).to have_gitlab_http_status(403)
      end
    end

    context 'authorized user without permissions' do
      it 'does not enable runner' do
        post api("/projects/#{project.id}/runners", user2)

        expect(response).to have_gitlab_http_status(403)
      end
    end

    context 'unauthorized user' do
      it 'does not enable runner' do
        post api("/projects/#{project.id}/runners")

        expect(response).to have_gitlab_http_status(401)
      end
    end
  end

  describe 'DELETE /projects/:id/runners/:runner_id' do
    context 'authorized user' do
      context 'when runner have more than one associated projects' do
        it "disables project's runner" do
          expect do
            delete api("/projects/#{project.id}/runners/#{two_projects_runner.id}", user)

            expect(response).to have_gitlab_http_status(204)
          end.to change { project.runners.count }.by(-1)
        end

        it_behaves_like '412 response' do
          let(:request) { api("/projects/#{project.id}/runners/#{two_projects_runner.id}", user) }
        end
      end

      context 'when runner have one associated projects' do
        it "does not disable project's runner" do
          expect do
            delete api("/projects/#{project.id}/runners/#{project_runner.id}", user)
          end.to change { project.runners.count }.by(0)
          expect(response).to have_gitlab_http_status(403)
        end
      end

      it 'returns 404 is runner is not found' do
        delete api("/projects/#{project.id}/runners/9999", user)

        expect(response).to have_gitlab_http_status(404)
      end
    end

    context 'authorized user without permissions' do
      it "does not disable project's runner" do
        delete api("/projects/#{project.id}/runners/#{project_runner.id}", user2)

        expect(response).to have_gitlab_http_status(403)
      end
    end

    context 'unauthorized user' do
      it "does not disable project's runner" do
        delete api("/projects/#{project.id}/runners/#{project_runner.id}")

        expect(response).to have_gitlab_http_status(401)
      end
    end
  end
end

redpajama_set_name: RedPajamaGithub


text:
package com.otterca.repository.webservice.server.rest;

/**
 * @author Bear Giles <bgiles@coyotesong.com>
 */
public abstract class AbstractResource {

    public String scrubCount(final long count) {
        return String.format("{ \"count\": %d }", count);
    }

    public String scrubPolicy(final String dirty) {
        final String clean = dirty;
        //clean.setUuid(dirty.getUuid());
        //clean.setName(dirty.getName());
        //clean.setVersion(dirty.getVersion());
        //clean.setCreationDate(dirty.getCreationDate());
        // clean.setSelf("resource/" + dirty.getUuid());
        return clean;
    }
}


text:
assignees:
- soltysh
- sttts

---

* TOC
{:toc}

## Audit in Kubernetes

Kubernetes Audit provides a security-relevant chronological set of records documenting
the sequence of activities that have affected system by individual users, administrators
or other components of the system. It allows cluster administrator to
answer the following questions:
    - what happened?
    - when did it happen?
    - who initiated it?
    - on what did it happen?
    - where was it observed?
    - from where was it initiated?
    - to where was it going?

NOTE: Currently, Kubernetes provides only basic audit capabilities, there is still a lot
of work going on to provide fully featured auditing capabilities (see https://github.com/kubernetes/features/issues/22).

Kubernetes audit is part of [kube-apiserver](/docs/admin/kube-apiserver) logging all requests
coming to the server. Each audit log contains two entries:

1. The request line containing:
    - unique id allowing to match the response line (see 2)
    - source ip of the request
    - HTTP method being invoked
    - original user invoking the operation
    - impersonated user for the operation
    - namespace of the request or <none>
    - URI as requested
2. The response line containing:
    - the unique id from 1
    - response code

Example output for user `admin` asking for a list of pods:

```
2016-09-07T13:03:57.400333046Z AUDIT: id="5c3b8227-4af9-4322-8a71-542231c3887b" ip="127.0.0.1" method="GET" user="admin" as="<self>" namespace="default" uri="/api/v1/namespaces/default/pods"
2016-09-07T13:03:57.400710987Z AUDIT: id="5c3b8227-4af9-4322-8a71-542231c3887b" response="200"
```

NOTE: The audit capabilities are available *only* for the secured endpoint of the API server.

## Configuration

[Kube-apiserver](/docs/admin/kube-apiserver) provides following options which are responsible
for configuring where and how audit logs are handled:

- `audit-log-path` - enables the audit log pointing to a file where the requests are being logged to.
- `audit-log-maxage` - specifies maximum number of days to retain old audit log files based on the timestamp encoded in their filename.
- `audit-log-maxbackup` - specifies maximum number of old audit log files to retain.
- `audit-log-maxsize` - specifies maximum size in megabytes of the audit log file before it gets rotated. Defaults to 100MB

If an audit log file already exists, Kubernetes appends new audit logs to that file.
Otherwise, Kubernetes creates an audit log file at the location you specified in
`audit-log-path`. If the audit log file exceeds the size you specify in `audit-log-maxsize`,
Kubernetes will rename the current log file by appending the current timestamp on
the file name (before the file extension) and create a new audit log file.
Kubernetes may delete old log files when creating a new log file; you can configure
how many files are retained and how old they can be by specifying the `audit-log-maxbackup`
and `audit-log-maxage` options.


text:
import { MetadataGroup, validators } from '@ionic/cli-framework';
import { createPromptChoiceSeparator } from '@ionic/cli-framework-prompts';
import { prettyPath } from '@ionic/utils-terminal';
import * as Debug from 'debug';

import { PROJECT_FILE } from '../constants';
import { App, CommandInstanceInfo, CommandLineInputs, CommandLineOptions, CommandMetadata, CommandPreRun, GithubBranch, GithubRepo } from '../definitions';
import { isSuperAgentError } from '../guards';
import { ancillary, input, strong, weak } from '../lib/color';
import { Command } from '../lib/command';
import { FatalException } from '../lib/errors';
import { runCommand } from '../lib/executor';
import { openUrl } from '../lib/open';

const debug = Debug('ionic:commands:link');

const CHOICE_CREATE_NEW_APP = 'createNewApp';
const CHOICE_NEVERMIND = 'nevermind';

const CHOICE_RELINK = 'relink';
const CHOICE_LINK_EXISTING_APP = 'linkExistingApp';

const CHOICE_IONIC = 'ionic';
const CHOICE_GITHUB = 'github';
const CHOICE_SKIP = 'skip'

const CHOICE_MASTER_ONLY = 'master';
const CHOICE_SPECIFIC_BRANCHES = 'specific';

export class LinkCommand extends Command implements CommandPreRun {
  async getMetadata(): Promise<CommandMetadata> {
    const projectFile = this.project ? prettyPath(this.project.filePath) : PROJECT_FILE;

    return {
      name: 'link',
      type: 'project',
      groups: [MetadataGroup.PAID],
      summary: 'Connect local apps to Ionic',
      description: `
Link apps on Appflow to local Ionic projects with this command.

If the ${input('id')} argument is excluded, this command will prompt you to select an app from Appflow.

Appflow uses a git-based workflow to manage app updates. During the linking process, select ${strong('GitHub')} (recommended) or ${strong('Appflow')} as a git host. See our documentation[^appflow-git-basics] for more information.

Ultimately, this command sets the ${strong('id')} property in ${strong(prettyPath(projectFile))}, which marks this app as linked.

If you are having issues linking, please get in touch with our Support[^support-request].
      `,
      footnotes: [
        {
          id: 'appflow-git-basics',
          url: 'https://ionicframework.com/docs/appflow/basics/git',
          shortUrl: 'https://ion.link/appflow-git-basics',
        },
        {
          id: 'support-request',
          url: 'https://ion.link/support-request',
        },
      ],
      exampleCommands: ['', 'a1b2c3d4'],
      inputs: [
        {
          name: 'id',
          summary: `The Appflow ID of the app to link (e.g. ${input('a1b2c3d4')})`,
        },
      ],
      options: [
        {
          name: 'name',
          summary: 'The app name to use during the linking of a new app',
          groups: [MetadataGroup.HIDDEN],
        },
        {
          name: 'create',
          summary: 'Create a new app on Ionic Appflow and link it with this local Ionic project',
          type: Boolean,
          groups: [MetadataGroup.HIDDEN],
        },
        {
          name: 'pro-id',
          summary: 'Specify an app ID from the Ionic Appflow to link',
          groups: [MetadataGroup.DEPRECATED, MetadataGroup.HIDDEN],
          spec: { value: 'id' },
        },
      ],
    };
  }

  async preRun(inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {
    const { create } = options;

    if (inputs[0] && create) {
      throw new FatalException(`Sorry--cannot use both ${input('id')} and ${input('--create')}. You must either link an existing app or create a new one.`);
    }

    const id = options['pro-id'] ? String(options['pro-id']) : undefined;

    if (id) {
      inputs[0] = id;
    }
  }

  async run(inputs: CommandLineInputs, options: CommandLineOptions, runinfo: CommandInstanceInfo): Promise<void> {
    const { promptToLogin } = await import('../lib/session');

    if (!this.project) {
      throw new FatalException(`Cannot run ${input('ionic link')} outside a project directory.`);
    }

    let id: string | undefined = inputs[0];
    let { create } = options;

    const idFromConfig = this.project.config.get('id');

    if (idFromConfig) {
      if (id && idFromConfig === id) {
        this.env.log.msg(`Already linked with app ${input(id)}.`);
        return;
      }

      const msg = id ?
        `Are you sure you want to link it to ${input(id)} instead?` :
        `Would you like to run link again?`;

      const confirm = await this.env.prompt({
        type: 'confirm',
        name: 'confirm',
        message: `App ID ${input(idFromConfig)} is already set up with this app. ${msg}`,
      });

      if (!confirm) {
        this.env.log.msg('Not linking.');
        return;
      }
    }

    if (!this.env.session.isLoggedIn()) {
      await promptToLogin(this.env);
    }

    if (!id && !create) {
      const choices = [
        {
          name: `Link ${idFromConfig ? 'a different' : 'an existing'} app on Ionic Appflow`,
          value: CHOICE_LINK_EXISTING_APP,
        },
        {
          name: 'Create a new app on Ionic Appflow',
          value: CHOICE_CREATE_NEW_APP,
        },
      ];

      if (idFromConfig) {
        choices.unshift({
          name: `Relink ${input(idFromConfig)}`,
          value: CHOICE_RELINK,
        });
      }

      const result = await this.env.prompt({
        type: 'list',
        name: 'whatToDo',
        message: 'What would you like to do?',
        choices,
      });

      if (result === CHOICE_CREATE_NEW_APP) {
        create = true;
        id = undefined;
      } else if (result === CHOICE_LINK_EXISTING_APP) {
        const tasks = this.createTaskChain();
        tasks.next(`Looking up your apps`);
        const apps: App[] = [];

        const appClient = await this.getAppClient();
        const paginator = appClient.paginate();

        for (const r of paginator) {
          const res = await r;
          apps.push(...res.data);
        }

        tasks.end();

        if (apps.length === 0) {
          const confirm = await this.env.prompt({
            type: 'confirm',
            name: 'confirm',
            message: `No apps found. Would you like to create a new app on Ionic Appflow?`,
          });

          if (!confirm) {
            throw new FatalException(`Cannot link without an app selected.`);
          }

          create = true;
          id = undefined;
        } else {
          const choice = await this.chooseApp(apps);

          if (choice === CHOICE_NEVERMIND) {
            this.env.log.info('Not linking app.');
            id = undefined;
          } else {
            id = choice;
          }
        }
      } else if (result === CHOICE_RELINK) {
        id = idFromConfig;
      }
    }

    if (create) {
      let name = options['name'] ? String(options['name']) : undefined;

      if (!name) {
        name = await this.env.prompt({
          type: 'input',
          name: 'name',
          message: 'Please enter a name for your new app:',
          validate: v => validators.required(v),
        });
      }

      id = await this.createApp({ name }, runinfo);
    } else if (id) {
      const app = await this.lookUpApp(id);
      await this.linkApp(app, runinfo);
    }
  }

  private async getAppClient() {
    const { AppClient } = await import('../lib/app');
    const token = await this.env.session.getUserToken();
    return new AppClient(token, this.env);
  }

  private async getUserClient() {
    const { UserClient } = await import('../lib/user');
    const token = await this.env.session.getUserToken();
    return new UserClient(token, this.env);
  }

  async lookUpApp(id: string): Promise<App> {
    const tasks = this.createTaskChain();
    tasks.next(`Looking up app ${input(id)}`);

    const appClient = await this.getAppClient();
    const app = await appClient.load(id); // Make sure the user has access to the app

    tasks.end();

    return app;
  }

  async createApp({ name }: { name: string; }, runinfo: CommandInstanceInfo): Promise<string> {
    const appClient = await this.getAppClient();
    const org_id = this.env.config.get('org.id');
    const app = await appClient.create({ name, org_id });

    await this.linkApp(app, runinfo);

    return app.id;
  }

  async linkApp(app: App, runinfo: CommandInstanceInfo) {
    // TODO: load connections

    // TODO: check for git availability before this

    this.env.log.nl();

    this.env.log.info(
      `Ionic Appflow uses a git-based workflow to manage app updates.\n` +
      `You will be prompted to set up the git host and repository for this new app. See the docs${ancillary('[1]')} for more information.\n\n` +
      `${ancillary('[1]')}: ${strong('https://ion.link/appflow-git-basics')}`
    );

    this.env.log.nl();

    const service = await this.env.prompt({
      type: 'list',
      name: 'gitService',
      message: 'Which git host would you like to use?',
      choices: [
        {
          name: 'GitHub',
          value: CHOICE_GITHUB,
        },
        {
          name: 'Ionic Appflow',
          value: CHOICE_IONIC,
        },
        {
          name: 'Don\'t use a git host',
          value: CHOICE_SKIP,
        },
      ],
    });

    let githubUrl: string | undefined;
    if (service === CHOICE_IONIC) {
      if (!this.env.config.get('git.setup')) {
        await runCommand(runinfo, ['ssh', 'setup']);
      }

      await runCommand(runinfo, ['config', 'set', 'id', `"${app.id}"`, '--json']);
      await runCommand(runinfo, ['git', 'remote']);
    } else {
      if (service === CHOICE_GITHUB) {
        githubUrl = await this.linkGithub(app);
      }

      await runCommand(runinfo, ['config', 'set', 'id', `"${app.id}"`, '--json']);
    }

    this.env.log.ok(`Project linked with app ${input(app.id)}!`);
    if (service === CHOICE_GITHUB) {
      this.env.log.info(
        `Here are some additional links that can help you with you first push to GitHub:\n` +
        `${strong('Adding GitHub as a remote')}:\n\t${strong('https://help.github.com/articles/adding-a-remote/')}\n\n` +
        `${strong('Pushing to a remote')}:\n\t${strong('https://help.github.com/articles/pushing-to-a-remote/')}\n\n` +
        `${strong('Working with branches')}:\n\t${strong('https://guides.github.com/introduction/flow/')}\n\n` +
        `${strong('More comfortable with a GUI? Try GitHub Desktop!')}\n\t${strong('https://desktop.github.com/')}`
      );

      if (githubUrl) {
        this.env.log.info(
          `You can now push to one of your branches on GitHub to trigger a build in Ionic Appflow!\n` +
          `If you haven't added GitHub as your origin you can do so by running:\n\n` +
          `${input('git remote add origin ' + githubUrl)}\n\n` +
          `You can find additional links above to help if you're having issues.`
        );
      }
    }
  }

  async linkGithub(app: App): Promise<string | undefined> {
    const { id } = this.env.session.getUser();

    const userClient = await this.getUserClient();
    const user = await userClient.load(id, { fields: ['oauth_identities'] });

    if (!user.oauth_identities || !user.oauth_identities.github) {
      await this.oAuthProcess(id);
    }

    if (await this.needsAssociation(app, user.id)) {
      await this.confirmGithubRepoExists();
      const repoId = await this.selectGithubRepo();
      const branches = await this.selectGithubBranches(repoId);
      return this.connectGithub(app, repoId, branches);
    }
  }

  async confirmGithubRepoExists() {
    let confirm = false;

    this.env.log.nl();
    this.env.log.info(strong(`In order to link to a GitHub repository the repository must already exist on GitHub.`));
    this.env.log.info(
      `${strong('If the repository does not exist please create one now before continuing.')}\n` +
      `If you're not familiar with Git you can learn how to set it up with GitHub here:\n\n` +
      strong(`https://help.github.com/articles/set-up-git/ \n\n`) +
      `You can find documentation on how to create a repository on GitHub and push to it here:\n\n` +
      strong(`https://help.github.com/articles/create-a-repo/`)
    );

    confirm = await this.env.prompt({
      type: 'confirm',
      name: 'confirm',
      message: 'Does the repository exist on GitHub?',
    });

    if (!confirm) {
      throw new FatalException(`Repo must exist on GitHub in order to link. Please create the repo and run ${input('ionic link')} again.`);
    }
  }

  async oAuthProcess(userId: number) {
    const userClient = await this.getUserClient();

    let confirm = false;

    this.env.log.nl();
    this.env.log.info(
      `GitHub OAuth setup required.\n` +
      `To continue, we need you to authorize Ionic Appflow with your GitHub account. ` +
      `A browser will open and prompt you to complete the authorization request. ` +
      `When finished, please return to the CLI to continue linking your app.`
    );

    confirm = await this.env.prompt({
      type: 'confirm',
      name: 'ready',
      message: 'Open browser:',
    });

    if (!confirm) {
      throw new FatalException(`GitHub OAuth setup is required to link to GitHub repository. Please run ${input('ionic link')} again when ready.`);
    }

    const url = await userClient.oAuthGithubLogin(userId);
    await openUrl(url);

    confirm = await this.env.prompt({
      type: 'confirm',
      name: 'ready',
      message: 'Authorized and ready to continue:',
    });

    if (!confirm) {
      throw new FatalException(`GitHub OAuth setup is required to link to GitHub repository. Please run ${input('ionic link')} again when ready.`);
    }
  }

  async needsAssociation(app: App, userId: number): Promise<boolean> {
    const appClient = await this.getAppClient();

    if (app.association && app.association.repository.html_url) {
      this.env.log.msg(`App ${input(app.id)} already connected to ${strong(app.association.repository.html_url)}`);

      const confirm = await this.env.prompt({
        type: 'confirm',
        name: 'confirm',
        message: 'Would you like to connect a different repo?',
      });

      if (!confirm) {
        return false;
      }

      try {
        // TODO: maybe we can use a PUT instead of DELETE now + POST later?
        await appClient.deleteAssociation(app.id);
      } catch (e) {
        if (isSuperAgentError(e)) {
          if (e.response.status === 401) {
            await this.oAuthProcess(userId);
            await appClient.deleteAssociation(app.id);
            return true;
          } else if (e.response.status === 404) {
            debug(`DELETE ${app.id} GitHub association not found`);
            return true;
          }
        }

        throw e;
      }
    }

    return true;
  }

  async connectGithub(app: App, repoId: number, branches: string[]): Promise<string | undefined> {
    const appClient = await this.getAppClient();

    try {
      const association = await appClient.createAssociation(app.id, { repoId, type: 'github', branches });
      this.env.log.ok(`App ${input(app.id)} connected to ${strong(association.repository.html_url)}`);
      return association.repository.html_url;
    } catch (e) {
      if (isSuperAgentError(e) && e.response.status === 403) {
        throw new FatalException(e.response.body.error.message);
      }
    }
  }

  formatRepoName(fullName: string) {
    const [ org, name ] = fullName.split('/');

    return `${weak(`${org} /`)} ${name}`;
  }

  async chooseApp(apps: App[]): Promise<string> {
    const { formatName } = await import('../lib/app');

    const neverMindChoice = {
      name: strong('Nevermind'),
      id: CHOICE_NEVERMIND,
      value: CHOICE_NEVERMIND,
      org: null,
    };

    const linkedApp = await this.env.prompt({
      type: 'list',
      name: 'linkedApp',
      message: 'Which app would you like to link',
      choices: [
        ...apps.map(app => ({
          name: `${formatName(app)} ${weak(`(${app.id})`)}`,
          value: app.id,
        })),
        createPromptChoiceSeparator(),
        neverMindChoice,
        createPromptChoiceSeparator(),
      ],
    });

    return linkedApp;
  }

  async selectGithubRepo(): Promise<number> {
    const user = this.env.session.getUser();
    const userClient = await this.getUserClient();

    const tasks = this.createTaskChain();
    const task = tasks.next('Looking up your GitHub repositories');

    const paginator = userClient.paginateGithubRepositories(user.id);
    const repos: GithubRepo[] = [];

    try {
      for (const r of paginator) {
        const res = await r;
        repos.push(...res.data);

        task.msg = `Looking up your GitHub repositories: ${strong(String(repos.length))} found`;
      }
    } catch (e) {
      tasks.fail();

      if (isSuperAgentError(e) && e.response.status === 401) {
        await this.oAuthProcess(user.id);
        return this.selectGithubRepo();
      }

      throw e;
    }

    tasks.end();

    const repoId = await this.env.prompt({
      type: 'list',
      name: 'githubRepo',
      message: 'Which GitHub repository would you like to link?',
      choices: repos.map(repo => ({
        name: this.formatRepoName(repo.full_name),
        value: String(repo.id),
      })),
    });

    return Number(repoId);
  }

  async selectGithubBranches(repoId: number): Promise<string[]> {
    this.env.log.nl();
    this.env.log.info(strong(`By default Ionic Appflow links only to the ${input('master')} branch.`));
    this.env.log.info(
      `${strong('If you\'d like to link to another branch or multiple branches you\'ll need to select each branch to connect to.')}\n` +
      `If you're not familiar with on working with branches in GitHub you can read about them here:\n\n` +
      strong(`https://guides.github.com/introduction/flow/ \n\n`)
    );

    const choice = await this.env.prompt({
      type: 'list',
      name: 'githubMultipleBranches',
      message: 'Which would you like to do?',
      choices: [
        {
          name: `Link to master branch only`,
          value: CHOICE_MASTER_ONLY,
        },
        {
          name: `Link to specific branches`,
          value: CHOICE_SPECIFIC_BRANCHES,
        },
      ],
    });

    switch (choice) {
      case CHOICE_MASTER_ONLY:
        return ['master'];
      case CHOICE_SPECIFIC_BRANCHES:
        // fall through and begin prompting to choose branches
        break;
      default:
        throw new FatalException('Aborting. No branch choice specified.');
    }

    const user = this.env.session.getUser();
    const userClient = await this.getUserClient();
    const paginator = userClient.paginateGithubBranches(user.id, repoId);
    const tasks = this.createTaskChain();
    const task = tasks.next('Looking for available branches');
    const availableBranches: GithubBranch[] = [];
    try {
      for (const r of paginator) {
        const res = await r;
        availableBranches.push(...res.data);

        task.msg = `Looking up the available branches on your GitHub repository: ${strong(String(availableBranches.length))} found`;
      }
    } catch (e) {
      tasks.fail();
      throw e;
    }
    tasks.end();

    const choices = availableBranches.map(branch => ({
      name: branch.name,
      value: branch.name,
      checked: branch.name === 'master',
    }));

    if (choices.length === 0) {
      this.env.log.warn(`No branches found for the repository. Linking to ${input('master')} branch.`);
      return ['master'];
    }

    const selectedBranches = await this.env.prompt({
      type: 'checkbox',
      name: 'githubBranches',
      message: 'Which branch would you like to link?',
      choices,
      default: ['master'],
    });

    return selectedBranches;
  }
}


text:
package org.zstack.test.utils;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 */
public class TestSubList {
    @Test
    public void test() {
        List<Integer> lst = new ArrayList<Integer>();
        lst.add(1);
        lst.add(2);
        lst.add(3);
        lst.add(4);
        lst.add(5);
        lst.add(6);

        List<Integer> sub = lst.subList(0, 3);
        List n = new ArrayList();
        n.addAll(sub);
        sub.clear();
        System.out.println(lst.toString());
        System.out.println(n.toString());
    }
}


text:
package com.speedment.runtime.core.internal.stream.parallel;

import java.util.stream.IntStream;

/**
 *
 * @author pemi
 */
public final class ComputeIntensityUtil {

    static IntStream repeatOnHalfAvailableProcessors(int item) {
        return repeat(item, availableProcessors() / 2);
    }

    static int toThePowerOfTwo(int x) {
        return 1 << x;
    }

    static int times256(int x) {
        return x * 256;
    }

    static int availableProcessors() {
        return Runtime.getRuntime().availableProcessors();
    }

    static IntStream repeat(int item, int times) {
        return IntStream.generate(() -> item).limit(times);
    }

    private ComputeIntensityUtil() {
    }

}


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
Mém. Soc. Émul. Montbéliard, Sér. 2 5: 140 (1872)

#### Original name
Psalliota campestris f. campestris

### Remarks
null


text:
module GoogleApi

  class ApiError < StandardError

    attr_reader :result

    def initialize(result)
      @result = result
    end

  end

end


text:
config.load_autoconfig(True)

# Enable plugins
c.content.plugins = True
c.qt.args = ['ppapi-widevine-path=/usr/lib/qt/plugins/ppapi/libwidevinecdmadapter.so']

# Adblock
c.content.blocking.enabled = True
c.content.blocking.method = 'auto'
c.content.blocking.adblock.lists = ['https://easylist.to/easylist/easylist.txt',
                                    'https://easylist.to/easylist/easyprivacy.txt']

# Adjust font and font size
c.fonts.default_family = "Terminus"
c.fonts.default_size = "16pt"
c.fonts.web.family.standard = "Terminus"
c.fonts.web.size.default = 16

# Tabs
c.tabs.padding = {"top": 5, "bottom": 5, "left": 5, "right": 5}

# Play videos with mpv
config.bind('e', 'spawn --detach mpv {url}')
config.bind('E', 'hint links spawn --detach mpv {hint-url}')

# base16-qutebrowser (https://github.com/theova/base16-qutebrowser)
# Base16 qutebrowser template by theova and Daniel Mulford
# Solarized Dark scheme by Ethan Schoonover (modified by aramisgithub)

base00 = "#002b36"
base01 = "#073642"
base02 = "#586e75"
base03 = "#657b83"
base04 = "#839496"
base05 = "#93a1a1"
base06 = "#eee8d5"
base07 = "#fdf6e3"
base08 = "#dc322f"
base09 = "#cb4b16"
base0A = "#b58900"
base0B = "#859900"
base0C = "#2aa198"
base0D = "#268bd2"
base0E = "#6c71c4"
base0F = "#d33682"

# set qutebrowser colors

# Text color of the completion widget. May be a single color to use for
# all columns or a list of three colors, one for each column.
c.colors.completion.fg = base05

# Background color of the completion widget for odd rows.
c.colors.completion.odd.bg = base00

# Background color of the completion widget for even rows.
c.colors.completion.even.bg = base00

# Foreground color of completion widget category headers.
c.colors.completion.category.fg = base0D

# Background color of the completion widget category headers.
c.colors.completion.category.bg = base00

# Top border color of the completion widget category headers.
c.colors.completion.category.border.top = base00

# Bottom border color of the completion widget category headers.
c.colors.completion.category.border.bottom = base00

# Foreground color of the selected completion item.
c.colors.completion.item.selected.fg = base00

# Background color of the selected completion item.
c.colors.completion.item.selected.bg = base0D

# Top border color of the selected completion item
c.colors.completion.item.selected.border.top = base0D

# Bottom border color of the selected completion item.
c.colors.completion.item.selected.border.bottom = base0D

# Foreground color of the matched text in the selected completion item.
c.colors.completion.item.selected.match.fg = base00

# Foreground color of the matched text in the completion.
c.colors.completion.match.fg = base09

# Color of the scrollbar handle in the completion view.
c.colors.completion.scrollbar.fg = base05

# Color of the scrollbar in the completion view.
c.colors.completion.scrollbar.bg = base00

# Background color of disabled items in the context menu.
c.colors.contextmenu.disabled.bg = base01

# Foreground color of disabled items in the context menu.
c.colors.contextmenu.disabled.fg = base04

# Background color of the context menu. If set to null, the Qt default is used.
c.colors.contextmenu.menu.bg = base00

# Foreground color of the context menu. If set to null, the Qt default is used.
c.colors.contextmenu.menu.fg =  base05

# Background color of the context menu's selected item. If set to null, the Qt default is used.
c.colors.contextmenu.selected.bg = base0D

#Foreground color of the context menu's selected item. If set to null, the Qt default is used.
c.colors.contextmenu.selected.fg = base00

# Background color for the download bar.
c.colors.downloads.bar.bg = base00

# Color gradient start for download text.
c.colors.downloads.start.fg = base00

# Color gradient start for download backgrounds.
c.colors.downloads.start.bg = base0D

# Color gradient end for download text.
c.colors.downloads.stop.fg = base00

# Color gradient stop for download backgrounds.
c.colors.downloads.stop.bg = base0C

# Foreground color for downloads with errors.
c.colors.downloads.error.fg = base08

# Font color for hints.
c.colors.hints.fg = base00

# Background color for hints. Note that you can use a `rgba(...)` value
# for transparency.
c.colors.hints.bg = base0A

# Font color for the matched part of hints.
c.colors.hints.match.fg = base05

# Text color for the keyhint widget.
c.colors.keyhint.fg = base05

# Highlight color for keys to complete the current keychain.
c.colors.keyhint.suffix.fg = base05

# Background color of the keyhint widget.
c.colors.keyhint.bg = base00

# Foreground color of an error message.
c.colors.messages.error.fg = base00

# Background color of an error message.
c.colors.messages.error.bg = base08

# Border color of an error message.
c.colors.messages.error.border = base08

# Foreground color of a warning message.
c.colors.messages.warning.fg = base00

# Background color of a warning message.
c.colors.messages.warning.bg = base0E

# Border color of a warning message.
c.colors.messages.warning.border = base0E

# Foreground color of an info message.
c.colors.messages.info.fg = base05

# Background color of an info message.
c.colors.messages.info.bg = base00

# Border color of an info message.
c.colors.messages.info.border = base00

# Foreground color for prompts.
c.colors.prompts.fg = base05

# Border used around UI elements in prompts.
c.colors.prompts.border = base00

# Background color for prompts.
c.colors.prompts.bg = base00

# Background color for the selected item in filename prompts.
c.colors.prompts.selected.bg = base0A

# Foreground color of the statusbar.
c.colors.statusbar.normal.fg = base05

# Background color of the statusbar.
c.colors.statusbar.normal.bg = base00

# Foreground color of the statusbar in insert mode.
c.colors.statusbar.insert.fg = base0C

# Background color of the statusbar in insert mode.
c.colors.statusbar.insert.bg = base00

# Foreground color of the statusbar in passthrough mode.
c.colors.statusbar.passthrough.fg = base0A

# Background color of the statusbar in passthrough mode.
c.colors.statusbar.passthrough.bg = base00

# Foreground color of the statusbar in private browsing mode.
c.colors.statusbar.private.fg = base0E

# Background color of the statusbar in private browsing mode.
c.colors.statusbar.private.bg = base00

# Foreground color of the statusbar in command mode.
c.colors.statusbar.command.fg = base04

# Background color of the statusbar in command mode.
c.colors.statusbar.command.bg = base01

# Foreground color of the statusbar in private browsing + command mode.
c.colors.statusbar.command.private.fg = base0E

# Background color of the statusbar in private browsing + command mode.
c.colors.statusbar.command.private.bg = base01

# Foreground color of the statusbar in caret mode.
c.colors.statusbar.caret.fg = base0D

# Background color of the statusbar in caret mode.
c.colors.statusbar.caret.bg = base00

# Foreground color of the statusbar in caret mode with a selection.
c.colors.statusbar.caret.selection.fg = base0D

# Background color of the statusbar in caret mode with a selection.
c.colors.statusbar.caret.selection.bg = base00

# Background color of the progress bar.
c.colors.statusbar.progress.bg = base0D

# Default foreground color of the URL in the statusbar.
c.colors.statusbar.url.fg = base05

# Foreground color of the URL in the statusbar on error.
c.colors.statusbar.url.error.fg = base08

# Foreground color of the URL in the statusbar for hovered links.
c.colors.statusbar.url.hover.fg = base09

# Foreground color of the URL in the statusbar on successful load
# (http).
c.colors.statusbar.url.success.http.fg = base0B

# Foreground color of the URL in the statusbar on successful load
# (https).
c.colors.statusbar.url.success.https.fg = base0B

# Foreground color of the URL in the statusbar when there's a warning.
c.colors.statusbar.url.warn.fg = base0E

# Background color of the tab bar.
c.colors.tabs.bar.bg = base00

# Color gradient start for the tab indicator.
c.colors.tabs.indicator.start = base0D

# Color gradient end for the tab indicator.
c.colors.tabs.indicator.stop = base0C

# Color for the tab indicator on errors.
c.colors.tabs.indicator.error = base08

# Foreground color of unselected odd tabs.
c.colors.tabs.odd.fg = base05

# Background color of unselected odd tabs.
c.colors.tabs.odd.bg = base00

# Foreground color of unselected even tabs.
c.colors.tabs.even.fg = base05

# Background color of unselected even tabs.
c.colors.tabs.even.bg = base00

# Background color of pinned unselected even tabs.
c.colors.tabs.pinned.even.bg = base0B

# Foreground color of pinned unselected even tabs.
c.colors.tabs.pinned.even.fg = base00

# Background color of pinned unselected odd tabs.
c.colors.tabs.pinned.odd.bg = base0B

# Foreground color of pinned unselected odd tabs.
c.colors.tabs.pinned.odd.fg = base00

# Background color of pinned selected even tabs.
c.colors.tabs.pinned.selected.even.bg = base0D

# Foreground color of pinned selected even tabs.
c.colors.tabs.pinned.selected.even.fg = base00

# Background color of pinned selected odd tabs.
c.colors.tabs.pinned.selected.odd.bg = base0D

# Foreground color of pinned selected odd tabs.
c.colors.tabs.pinned.selected.odd.fg = base00

# Foreground color of selected odd tabs.
c.colors.tabs.selected.odd.fg = base00

# Background color of selected odd tabs.
c.colors.tabs.selected.odd.bg = base0D

# Foreground color of selected even tabs.
c.colors.tabs.selected.even.fg = base00

# Background color of selected even tabs.
c.colors.tabs.selected.even.bg = base0D

# Background color for webpages if unset (or empty to use the theme's
# color).
# c.colors.webpage.bg = base00


text:
#pragma once

#include <pebble.h>

struct WeatherAppMainWindowViewModel;

typedef void (*WeatherAppMainWindowViewModelFunc)(struct WeatherAppMainWindowViewModel* model);

typedef struct {
  WeatherAppMainWindowViewModelFunc announce_changed;
  struct {
    GColor top;
    GColor bottom;
    int32_t to_bottom_normalized;
  } bg_color;
  char *city;
  struct {
    int16_t value;
    char text[8];
  } temperature;
  struct {
    GDrawCommandImage *draw_command;
    int32_t to_square_normalized;
  } icon;
  struct {
    int16_t idx;
    int16_t num;
    char text[8];
  } pagination;
  struct {
    int16_t high;
    int16_t low;
    char text[20];
  } highlow;
  char *description;
} WeatherAppMainWindowViewModel;

//! calls model's .announce_changed or does nothing if NULL
void weather_app_main_window_view_model_announce_changed(WeatherAppMainWindowViewModel *model);

typedef struct {
  char *city;
  char *description;
  int icon;
  int16_t current;
  int16_t high;
  int16_t low;
} WeatherAppDataPoint;

typedef struct {
  int16_t temperature;
  int16_t low;
  int16_t high;
} WeatherDataViewNumbers;

void weather_app_view_model_set_highlow(WeatherAppMainWindowViewModel *model, int16_t high, int16_t low);

void weather_app_view_model_set_temperature(WeatherAppMainWindowViewModel *model, int16_t value);
void weather_app_view_model_set_icon(WeatherAppMainWindowViewModel *model, GDrawCommandImage *image);

WeatherDataViewNumbers weather_app_data_point_view_model_numbers(WeatherAppDataPoint *data_point);

GDrawCommandImage *weather_app_data_point_create_icon(WeatherAppDataPoint *data_point);

void weather_app_view_model_fill_strings_and_pagination(WeatherAppMainWindowViewModel *view_model, WeatherAppDataPoint *data_point);

void weather_view_model_fill_numbers(WeatherAppMainWindowViewModel *model, WeatherDataViewNumbers numbers);

void weather_app_view_model_fill_all(WeatherAppMainWindowViewModel *model, WeatherAppDataPoint *data_point);

void weather_app_view_model_fill_colors(WeatherAppMainWindowViewModel *model, GColor color);

void weather_app_view_model_deinit(WeatherAppMainWindowViewModel *model);

GColor weather_app_data_point_color(WeatherAppDataPoint *data_point);

int weather_app_num_data_points(void);

WeatherAppDataPoint *weather_app_data_point_at(int idx);
WeatherAppDataPoint *weather_app_data_point_delta(WeatherAppDataPoint *dp, int delta);


text:
import unittest

try:
    from g1.devtools import tests
except ImportError:
    tests = None

from nng import messages

class MessageTest(unittest.TestCase):

    def assert_chunk(self, chunk, data):
        self.assertEqual(bool(chunk), bool(data))
        self.assertEqual(len(chunk), len(data))
        self.assertEqual(chunk.copy(), data)
        self.assertEqual(chunk.memory_view, data)
        self.assertEqual(len(chunk.memory_view), len(data))

    @unittest.skipUnless(tests, 'g1.tests unavailable')
    def test_del_not_resurrecting(self):
        tests.assert_del_not_resurrecting(
            self, lambda: messages.Message(b'hello world')
        )

    def test_message(self):
        m = messages.Message()
        self.assert_chunk(m.header, b'')
        self.assert_chunk(m.body, b'')

        m.header.append(b'hello world')
        m.body.append(b'spam egg')
        self.assert_chunk(m.header, b'hello world')
        self.assert_chunk(m.body, b'spam egg')

        m.header.memory_view[0:3] = b'abc'
        m.body.memory_view[0:3] = b'def'
        self.assert_chunk(m.header, b'abclo world')
        self.assert_chunk(m.body, b'defm egg')

        m.header.clear()
        m.body.clear()
        self.assert_chunk(m.header, b'')
        self.assert_chunk(m.body, b'')

    def test_init_data(self):
        m = messages.Message(b'hello world')
        self.assert_chunk(m.header, b'')
        self.assert_chunk(m.body, b'hello world')

    def test_copy(self):
        m1 = messages.Message(b'hello world')
        m2 = m1.copy()
        self.assert_chunk(m2.header, b'')
        self.assert_chunk(m2.body, b'hello world')

if __name__ == '__main__':
    unittest.main()


text:
module Portefolio
  class User < ActiveRecord::Base
    authenticates_with_sorcery!

  attr_accessible :email, :password, :password_confirmation

  validates_confirmation_of :password
  validates_presence_of :password, :on => :create
  validates_presence_of :email
  validates_uniqueness_of :email

  end
end


text:
categories:
    - Release
tags:
    - gh-pages

title: 1.95.2
---

{{page.title}} is live and ready for [download](https://github.com/MaibornWolff/codecharta/releases/tag/{{page.title}}). This version brings the following:

### Changed

-   Restrict upload in custom configs view to custom configs. Custom configs uploaded in the custom configs view are now allowed to have an arbitrary file suffix [#2773](https://github.com/MaibornWolff/codecharta/pull/2773)

### Chore 👨💻 👩💻

-   Migrate reset-settings-button-component to Angular [#2774](https://github.com/MaibornWolff/codecharta/pull/2774)

### Fixed 🐞

-   Set files loaded via URL to multiple mode by default when delta mode is not selected [#2769](https://github.com/MaibornWolff/codecharta/pull/2769)


text:
<?php
class ControllerUpgradeUpgrade extends Controller {
	public function index() {
		$this->language->load('upgrade/upgrade');

		$this->document->setTitle($this->language->get('heading_title'));

		$data['heading_title'] = $this->language->get('heading_title');

		$data['text_upgrade'] = $this->language->get('text_upgrade');
		$data['text_server'] = $this->language->get('text_server');
		$data['text_steps'] = $this->language->get('text_steps');
		$data['text_error'] = $this->language->get('text_error');
		$data['text_clear'] = $this->language->get('text_clear');
		$data['text_admin'] = $this->language->get('text_admin');
		$data['text_user'] = $this->language->get('text_user');
		$data['text_setting'] = $this->language->get('text_setting');
		$data['text_store'] = $this->language->get('text_store');

		$data['entry_progress'] = $this->language->get('entry_progress');

		$data['button_continue'] = $this->language->get('button_continue');

		$data['store'] = HTTP_OPENCART;

		$data['total'] = count(glob(DIR_APPLICATION . 'model/upgrade/*.php'));

		$data['header'] = $this->load->controller('common/header');
		$data['footer'] = $this->load->controller('common/footer');
		$data['column_left'] = $this->load->controller('common/column_left');

		$this->response->setOutput($this->load->view('upgrade/upgrade', $data));
	}

	public function next() {
		$this->load->language('upgrade/upgrade');

		$json = array();

		if (isset($this->request->get['step'])) {
			$step = $this->request->get['step'];
		} else {
			$step = 1;
		}

		$files = glob(DIR_APPLICATION . 'model/upgrade/*.php');

		if (isset($files[$step - 1])) {
			// Get the upgrade file
			try {
				$this->load->model('upgrade/' . basename($files[$step - 1], '.php'));

				// All upgrade methods require a upgrade method
				$this->{'model_upgrade_' . str_replace('.', '', basename($files[$step - 1], '.php'))}->upgrade();

				$json['success'] = sprintf($this->language->get('text_progress'), basename($files[$step - 1], '.php'), $step, count($files));

				$json['next'] = str_replace('&', '&', $this->url->link('upgrade/upgrade/next', 'step=' . ($step + 1)));
			} catch(Exception $exception) {
				$json['error'] = sprintf($this->language->get('error_exception'), $exception->getCode(), $exception->getMessage(), $exception->getFile(), $exception->getLine());
			}
		} else {
			$json['success'] = $this->language->get('text_success');
		}

		$this->response->addHeader('Content-Type: application/json');
		$this->response->setOutput(json_encode($json));
	}
}


text:
API LIMITS

 0">{{providerName}} {{status.remaining}} / {{status.limit}}


text:
ctext is a small utility class to interact with a curses window analagously to how you would interact
with a screen.

There's an sprintf equivalent that interacts with the object who is associated with a curses WINDOW.

The utility class has a number of parameters which should be familiar:

  * scrollback buffer
  * append on bottom or on top
  * word wrap
  * automatic newline
  * scroll on append

Furthermore it can be manipulated using the following actions:

  * clear
  * up, down, left, right


text:
'use strict';

require: '?ngModel'
/* Directives */


text:
package com.bigbaddevil7.rustic.utility;

import com.bigbaddevil7.rustic.reference.Reference;
import cpw.mods.fml.common.FMLLog;
import org.apache.logging.log4j.Level;

/**
 * Created by bigbaddevil7 on 10/3/2014.
 */
public class LogHelper {
    public static void log(Level logLevel, Object object){// take the loglevel example "DEBUG", and takes a string what you want it to say
        FMLLog.log(Reference.MOD_NAME, logLevel, String.valueOf(object));
    }

    public static void all(Object object) {log(Level.ALL, object);}
    public static void debug(Object object) {log(Level.DEBUG, object);}
    public static void error(Object object) {log(Level.ERROR, object);}
    public static void fatal(Object object) {log(Level.FATAL, object);}
    public static void info(Object object) {log(Level.INFO, object);}
    public static void off(Object object) {log(Level.OFF, object);}
    public static void trace(Object object) {log(Level.TRACE, object);}
    public static void warn(Object object) {log(Level.WARN, object);}
}


text:
export { Hero } from './hero';
export { HeroRole } from './hero-role';
export { HeroUniverse } from './hero-universe';
export { HeroFilter } from './hero-filter';


text:
			<% for donation in @charity.donations.order("created_at desc") %>
			<% user = User.find(donation.user_id) unless donation.user_id == nil %>

				<% if donation.anonymous == false %>
					<% if donation.user_id %>
						<%= image_tag user.uploaded_image.thumb_avatar.url || user.image_url || user.gravatar_url || '/assets/user.png' %>
					<% else %>
						<%= image_tag '/assets/user.png' %>
					<% end %>
				<% else %>
					<%= image_tag '/assets/user.png' %>
				<% end %>

					<% if donation.anonymous == true %>
						Anonymous
					<% elsif donation.user_id == nil %>
						Guest
					<% else %>
						<%= link_to(user.name,user_path(user)) %>
					<% end %>

					<%= "#{number_to_currency(donation.amount, unit: Charity.find(donation.charity_id).currency_symbol)} " %>

						Donated on <%= donation.created_at.strftime("%d/%m/%Y") %>.

					<% if donation.user_id %>

							<% if (user.donations.count + user.donators.count) == 1 %>
								Donated only to this cause so far.
							<% else %>
								Donated to this and <%= (user.donations.count + user.donators.count) - 1 %> other causes.
							<% end %>

					<% end %>

				<% if donation.comment != "" %>

<%= donation.comment %>

				<% end %>

			<% end %>


text:
package net.gcolin.di.cglib;

import net.gcolin.di.cdi.ProxyGenerator;
import net.sf.cglib.proxy.Enhancer;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * a proxy generator using cglib.
 *
 * @author Gaël COLIN
 * @since 1.0
 */
public class CglibProxyGenerator implements ProxyGenerator {

  @Override
  public boolean test(Class<?> type) {
    return true;
  }

  @Override
  public Object create(InvocationHandler handler, Class<?> type, Constructor<?> constructor,
      Object[] args) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(type);
    enhancer.setCallback(new net.sf.cglib.proxy.InvocationHandler() {

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return handler.invoke(proxy, method, args);
      }
    });

    if (constructor != null && args.length > 0) {
      return enhancer.create(constructor.getParameterTypes(), args);
    }
    return enhancer.create();

  }

}


text:
@ECHO OFF
REM ==================================================
REM List all transaction' entries.
REM The hook is called only when adding or updating the file
REM to validate its name.
REM ==================================================
@SETLOCAL EnableExtensions EnableDelayedExpansion

SET SVNRepository=%1
SET SVNTransaction=%2
SET hookClassPath=%SVNRepository%\hooks\

REM Loads the list of changes
FOR /F "delims=" %%g IN ('svnlook.exe changed %SVNRepository% -t %SVNTransaction%') DO (
  SET changePath=%%g
  SET actionFlag=!changePath:~0,1!
  SET filePath=!changePath:~4, 255!

  REM Adding...
  IF !actionFlag! == A (FOR /f "delims=" %%v IN ('java -cp %hookClassPath%JamesHookFat.jar net.itfromhell.howit.jameshook.precommit.PreCommitInterdiction net.itfromhell.howit.TickingClockHook "%SVNRepository%" %SVNTransaction% !actionFlag! "!filePath!"') DO SET result=%%v)
  REM Updating...
  IF !actionFlag! == U (FOR /f "delims=" %%v IN ('java -cp %hookClassPath%JamesHookFat.jar net.itfromhell.howit.jameshook.precommit.PreCommitInterdiction net.itfromhell.howit.TickingClockHook "%SVNRepository%" %SVNTransaction% !actionFlag! "!filePath!"') DO SET result=%%v)

  REM If the first char is 1, something got wrong
  SET resultCode=!result:~0,1!
  if !resultCode! == 1 (GOTO ERROR_EXIT)
)

REM Success exit
GOTO GET_OUT

REM Fail exit
:ERROR_EXIT
ECHO ============================================================== >&2
ECHO.>&2
ECHO Your commit is blocked since the file name is not accepted.    >&2
ECHO File: !filePath! >&2
ECHO Reason: !result:~2,255! >&2
ECHO You should fix it to try again.                               >&2
ECHO.>&2
ECHO ============================================================== >&2
EXIT 1

:GET_OUT
REM No code must be printed allowing an eventual next script to execute


text:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.viromedia.virobridge">

    <application android:label="@string/app_name"
        android:supportsRtl="true">

    </application>

</manifest>


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<TITLE>
Uses of Class org.apache.fop.render.intermediate.AbstractXMLWritingIFDocumentHandler (Apache FOP 2.1 API)
</TITLE>

<META NAME="date" CONTENT="2016-01-07">

<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../../stylesheet.css" TITLE="Style">

      Overview
      Package
      Class
    Use
      Tree
      Deprecated
      Index
      Help

fop 2.1

 PREV
 NEXT

  FRAMES
 NO FRAMES

  All Classes

Uses of Class
org.apache.fop.render.intermediate.AbstractXMLWritingIFDocumentHandler

Packages that use AbstractXMLWritingIFDocumentHandler

org.apache.fop.render.intermediate

org.apache.fop.render.svg
SVG (Structured Vector Graphics) Renderer

Uses of AbstractXMLWritingIFDocumentHandler in org.apache.fop.render.intermediate

Subclasses of AbstractXMLWritingIFDocumentHandler in org.apache.fop.render.intermediate

 class
IFSerializer

          IFPainter implementation that serializes the intermediate format to XML.

Uses of AbstractXMLWritingIFDocumentHandler in org.apache.fop.render.svg

Subclasses of AbstractXMLWritingIFDocumentHandler in org.apache.fop.render.svg

 class
AbstractSVGDocumentHandler

          Abstract base class for SVG Painter implementations.

 class
SVGDocumentHandler

          IFDocumentHandler implementation
 that writes SVG 1.1.

 class
SVGPrintDocumentHandler

          IFDocumentHandler implementation
 that writes SVG Print.

      Overview
      Package
      Class
    Use
      Tree
      Deprecated
      Index
      Help

fop 2.1

 PREV
 NEXT

  FRAMES
 NO FRAMES

  All Classes

Copyright 1999-2016 The Apache Software Foundation. All Rights Reserved.


text:
<?php
namespace Onion\Framework\State\Interfaces;

interface HistoryInterface
{
    public function add(TransitionInterface $transition): void;
}


text:
module RiotLolApi
  module Model
    class Altimage

      def initialize(options = {})
        options.each do |key, value|
          self.class.send(:attr_accessor, key.to_sym)
          instance_variable_set("@#{key}", value)
        end
      end

    end
  end
end


text:
package provingground.learning
import scala.collection.View
import shapeless._
import scala.reflect.runtime.universe._
trait PostHistory[W, ID] {
  // the post itself and all its predecessors
  def findPost(web: W, index: ID): Option[(PostData[_, W, ID], Set[ID])]

  def predPosts(web: W, index: ID) =
    findPost(web, index).map(_._2).getOrElse(Set())

  // all posts as a view
  def allPosts(web: W): View[PostData[_, W, ID]]

  def apexPosts(web: W): Vector[PostData[_, W, ID]] = { // very inefficient since a lot of stuff is recomputed, should override if efficiency mattersI
    val v = allPosts(web).toVector
    val notApex = v.toSet.flatMap { (pd: PostData[_, W, ID]) =>
      predPosts(web, pd.id)
    }
    v.filterNot(p => notApex.contains(p.id))
  }

  def summary(web: W) = {
    allPosts(web).toVector.flatMap(pd => findPost(web, pd.id)).map {
      case (pd, preds) => (pd.id, pd.pw.tag.toString(), preds)
    }
  }

  def snapShot(web: W): WebState[W, ID] = WebState(web, apexPosts(web))

  def postTags(web: W): Vector[(TypeTag[_], ID, Option[Set[ID]])]

  def allTagged[Q](
      web: W
  )(implicit tag: TypeTag[Q]) =
    postTags(web).toSet.filter(_._1.tpe =:= tag.tpe).flatMap {
      case (_, id, _) => findPost(web, id).map(_._1)
    }

  def history(web: W, id: ID): LazyList[PostData[_, W, ID]] = {
    val next: (
        (Set[PostData[_, W, ID]], Set[ID])
    ) => (Set[PostData[_, W, ID]], Set[ID]) = {
      case (d, indices) =>
        val pairs = indices.map(findPost(web, _)).flatten
        (pairs.map(_._1), pairs.flatMap(_._2))
    }
    def stream: LazyList[(Set[PostData[_, W, ID]], Set[ID])] =
      ((Set.empty[PostData[_, W, (ID)]], Set(id))) #:: stream.map(next)
    stream.flatMap(_._1)
  }

  def redirects(web: W): Map[ID, Set[ID]]

  /**
    * latest answers in the query using history
    *
    * @param web the web with all posts
    * @param id where we query
    * @param answer transformation of posts
    * @return
    */
  def latestAnswers[Q](
      web: W,
      id: ID,
      answer: PostData[_, W, ID] => Option[Q]
  ): Set[Q] =
    findPost(web, id)
      .map {
        case (pd, preds) =>
          answer(pd)
            .map(Set(_))
            .getOrElse(
              preds.flatMap(pid => latestAnswers(web, pid, answer))
            )
      }
      .orElse(
        redirects(web)
          .get(id)
          .map(ids => ids.flatMap(rid => latestAnswers(web, rid, answer)))
      )
      .getOrElse(Set())

  def latestTagged[Q](
      web: W,
      id: ID
  )(implicit tag: TypeTag[Q]): Set[Q] =
    PostHistory
      .latestTaggedID(id, postTags(web), redirects(web))
      .flatMap { id =>
        findPost(web, id)
      }
      .map(_._1.content.asInstanceOf[Q])

  def previousAnswers[Q](
      web: W,
      id: ID
  )(implicit qw: Postable[Q, W, ID]): Vector[Q] =
    findPost(web, id)
      .map {
        case (pd, preds) =>
          val head = pd.getOpt[Q].toVector
          val tail = preds.toVector.flatMap(pid => previousAnswers(web, pid))
          head ++ tail
      }
      .orElse(
        redirects(web)
          .get(id)
          .map(ids => ids.toVector.flatMap(rid => previousAnswers(web, rid)))
      )
      .getOrElse(Vector())
      .distinct
}

object PostHistory {
  def latestTaggedID[Q, ID](
      id: ID,
      data: Vector[(TypeTag[_], ID, Option[Set[ID]])],
      redirects: Map[ID, Set[ID]]
  )(implicit tag: TypeTag[Q]): Set[ID] =
    data
      .find(_._2 == id)
      .map {
        case (tt, _, predOpt) =>
          if (tt.tpe =:= tag.tpe) Set(id)
          else
            predOpt
              .map(
                preds =>
                  preds.flatMap(pid => latestTaggedID(pid, data, redirects))
              )
              .getOrElse(Set.empty[ID])
      }
      .orElse(
        redirects
          .get(id)
          .map(ids => ids.flatMap(rid => latestTaggedID(rid, data, redirects)))
      )
      .getOrElse(Set())

  // data
  //   .find(_._1.tpe =:= tag.tpe)
  //   .map(x => Set(x._2))
  //   .orElse(
  //     redirects
  //       .get(id)
  //       .map(ids => ids.flatMap(rid => latestTaggedID(rid, data, redirects)))
  //   )
  //   .getOrElse(Set())
  case class Empty[W, ID]() extends PostHistory[W, ID] {
    def findPost(web: W, index: ID): Option[(PostData[_, W, ID], Set[ID])] =
      None
    def allPosts(web: W): View[PostData[_, W, ID]] = Seq().view
    def redirects(web: W): Map[ID, Set[ID]]        = Map()

    def postTags(
        web: W
    ): Vector[(reflect.runtime.universe.TypeTag[_], ID, Option[Set[ID]])] =
      Vector()
  }

  case class Or[W, ID](first: PostHistory[W, ID], second: PostHistory[W, ID])
      extends PostHistory[W, ID] {
    def findPost(web: W, index: ID): Option[(PostData[_, W, ID], Set[ID])] =
      first.findPost(web, index).orElse(second.findPost(web, index))
    def allPosts(web: W): View[PostData[_, W, ID]] =
      first.allPosts(web) ++ second.allPosts(web)
    def redirects(web: W): Map[ID, Set[ID]] =
      first.redirects(web) ++ second.redirects(web)

    def postTags(
        web: W
    ): Vector[(reflect.runtime.universe.TypeTag[_], ID, Option[Set[ID]])] =
      first.postTags(web) ++ second.postTags(web)
  }

  def get[W, B, ID](buffer: W => B)(
      implicit hg: HistoryGetter[W, B, ID]
  ): PostHistory[W, ID] = hg.getHistory(buffer)
}

trait HistoryGetter[W, B, ID] {
  def getHistory(buffer: W => B): PostHistory[W, ID]
}

object HistoryGetter {
  def get[W, B, ID](buffer: W => B)(
      implicit hg: HistoryGetter[W, B, ID]
  ): PostHistory[W, ID] = hg.getHistory(buffer)

  implicit def nilGetter[W, ID]: HistoryGetter[W, HNil, ID] =
    new HistoryGetter[W, HNil, ID] {
      def getHistory(buffer: W => HNil): PostHistory[W, ID] =
        PostHistory.Empty[W, ID]()
    }

  implicit def consGetter[W, B1, B2 <: HList, ID](
      implicit g1: HistoryGetter[W, B1, ID],
      g2: HistoryGetter[W, B2, ID]
  ): HistoryGetter[W, B1 :: B2, ID] =
    new HistoryGetter[W, B1 :: B2, ID] {
      def getHistory(buffer: W => B1 :: B2): PostHistory[W, ID] =
        PostHistory.Or(
          g1.getHistory((w: W) => buffer(w).head),
          g2.getHistory((w: W) => buffer(w).tail)
        )
    }

  implicit def bufferGetter[P, W, ID](
      implicit pw: Postable[P, W, ID]
  ): HistoryGetter[W, PostBuffer[P, ID], ID] =
    new HistoryGetter[W, PostBuffer[P, ID], ID] {
      def getHistory(buffer: W => PostBuffer[P, ID]): PostHistory[W, ID] =
        new PostHistory[W, ID] {
          def findPost(
              web: W,
              index: ID
          ): Option[(PostData[_, W, ID], Set[ID])] = buffer(web).find(index)
          def allPosts(web: W): View[PostData[_, W, ID]] =
            buffer(web).bufferData.view
          def redirects(web: W): Map[ID, Set[ID]] = Map()

          def postTags(web: W): Vector[
            (reflect.runtime.universe.TypeTag[_], ID, Option[Set[ID]])
          ] = buffer(web).tagData
        }
    }

  implicit def erasableBufferGetter[P, W, ID](
      implicit pw: Postable[P, W, ID]
  ): HistoryGetter[W, ErasablePostBuffer[P, ID], ID] =
    new HistoryGetter[W, ErasablePostBuffer[P, ID], ID] {
      def getHistory(
          buffer: W => ErasablePostBuffer[P, ID]
      ): PostHistory[W, ID] =
        new PostHistory[W, ID] {
          def findPost(
              web: W,
              index: ID
          ): Option[(PostData[_, W, ID], Set[ID])] = buffer(web).find(index)
          def allPosts(web: W): View[PostData[_, W, ID]] =
            buffer(web).bufferData.view
          def redirects(web: W): Map[ID, Set[ID]] = buffer(web).redirects

          def postTags(web: W): Vector[
            (reflect.runtime.universe.TypeTag[_], ID, Option[Set[ID]])
          ] = buffer(web).tagData
        }
    }

  implicit def postDiscardGetter[P, W, ID](
      implicit pw: Postable[P, W, ID]
  ): HistoryGetter[W, PostDiscarder[P, ID], ID] =
    new HistoryGetter[W, PostDiscarder[P, ID], ID] {
      def getHistory(buffer: W => PostDiscarder[P, ID]): PostHistory[W, ID] =
        new PostHistory[W, ID] {
          def findPost(
              web: W,
              index: ID
          ): Option[(PostData[_, W, ID], Set[ID])]       = None
          def allPosts(web: W): View[PostData[_, W, ID]] = Seq().view
          def redirects(web: W): Map[ID, Set[ID]]        = Map()

          def postTags(web: W): Vector[
            (reflect.runtime.universe.TypeTag[_], ID, Option[Set[ID]])
          ] = Vector()
        }
    }
}


text:
package levenshtein;

public class LevenshteinWagnerFischer {
    /**
     * Calculates the Levenshtein distance of two strings.
     * Uses a Wagner-Fischer algorithm.
     * @param s first string
     * @param t second string
     * @return Levenshtein distance
     * @see https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm
     */
    public static int distanceWagnerFischer(final char[] s, final char[] t) {
        if (s.length == 0) {
            // edge case: S is empty
            return t.length;
        } else if (t.length == 0) {
            // edge case: T is empty
            return s.length;
        }

        final int[][] d = new int[s.length + 1][t.length + 1];

        for (int i = 0; i <= s.length; i++) {
            // reset first row
            d[i][0] = i;
        }

        for (int i = 0; i <= t.length; i++) {
            // reset first column
            d[0][i] = i;
        }

        for (int it = 1; it <= t.length; it++) {
            for (int is = 1; is <= s.length; is++) {
                // up = deletion
                final int costDeletion = d[is - 1][it] + 1;
                // left = insertion
                final int costInsertion = d[is][it - 1] + 1;
                // cost for replacing the character in case it is different
                final int costReplacement = (s[is - 1] == t[it - 1]) ? 0 : 1;
                // diagonal = substitution (if necessary)
                final int costSubstitution = d[is - 1][it - 1] + costReplacement;

                d[is][it] = min(costDeletion, costInsertion, costSubstitution);
            }
        }

        return d[s.length][t.length];
    }

    private static int min(final int a, final int b, final int c) {
        return Math.min(a, Math.min(b, c));
    }
}


text:
from htmlgen.element import Element, VoidElement

class Span(Element):
    """An HTML in-line <span> element.

    <span> elements are inline elements without semantic meaning. They are
    containers for styling or scripting.

        >>> span1 = Span("Example", "text")
        >>> span2 = Span()
        >>> span2.append("Example text")
    """

    def __init__(self, *content):
        super().__init__("span")
        self.extend(content)

class Highlight(Element):
    """An HTML in-line highlighting (<b>) element.

    <b> elements are used to highlight words or sentences, without giving
    more importance to them.

    Note: Despite the name, <b> elements are not necessarily displayed in a
    bold font. Use CSS for styling purposes.

    Compare with the Strong, Alternate, and Emphasis elements.

    Example:

        >>> span = Span()
        >>> span.append("The ")
        >>> span.append(Highlight("swordfish"))
        >>> span.append(" is a member of the ")
        >>> span.append(Alternate("Xiphiidae"))
        >>> span.append(" family.")
    """

    def __init__(self, *content):
        super().__init__("b")
        self.extend(content)

class Strong(Element):
    """An HTML in-line element for strong importance or urgency (<strong>).

    Compare with the Highlight, Alternate, and Emphasis elements.

    Example:

        >>> Strong("It is imperative to turn off the froblunator after use!"))
    """

    def __init__(self, *content):
        super().__init__("strong")
        self.extend(content)

class Alternate(Element):
    """An HTML in-line element for alternate voice text (<i>).

    This includes the introduction of a term or thoughts.

    Note: Despite the name, <i> elements are not necessarily displayed in a
    italic font. Use CSS for styling purposes.

    Compare with the Highlight, Strong, and Emphasis elements.

    Example:

        >>> span = Span()
        >>> span.append("This is called a ")
        >>> span.append(Alternate("froblunator"))
        >>> span.append(".")
    """

    def __init__(self, *content):
        super().__init__("i")
        self.extend(content)

class Emphasis(Element):
    """An HTML stress emphasis (<em>) element.

    Compare with the Highlight, Strong, and Alternate elements.

    Example:

        >>> span = Span()
        >>> span.append(Emphasis("This"))
        >>> span.append(" is great.")
    """

    def __init__(self, *content):
        super().__init__("em")
        self.extend(content)

class Small(Element):
    """An HTML in-line element for side comments and small print (<small>).

    Note: Text inside <small> elements is not necessarily rendered with a
    smaller font size than surrounding text. Use CSS for styling purposes.

    Example:

        >>> Small("Copyright (C) 2010")
    """

    def __init__(self, *content):
        super().__init__("small")
        self.extend(content)

class LineBreak(VoidElement):
    """An HTML line break (<br>) element."""

    def __init__(self):
        super().__init__("br")


text:
import { base64StringToUint8Array, uint8ArrayToBase64String } from '@proton/shared/lib/helpers/encoding';

export const arrayToBase64 = (data: Uint8Array): string => uint8ArrayToBase64String(data) || '';

export const base64ToArray = (data: string): Uint8Array => base64StringToUint8Array(data);


text:
<!DOCTYPE html>

  <meta charset="utf-8">

  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>py_ice_cascade.examples.tests.test_uplift_only — py_ice_cascade 0.0.1 documentation</title>

    <link rel="stylesheet" href="../../../../_static/css/theme.css" type="text/css" />

    <link rel="top" title="py_ice_cascade 0.0.1 documentation" href="../../../../index.html"/>
        <link rel="up" title="Module code" href="../../../index.html"/>

             py_ice_cascade

                0.0.1

  <form id="rtd-search-form" class="wy-form" action="../../../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>

py_ice_cascade

        py_ice_cascade

Docs »

Module code »

py_ice_cascade.examples.tests.test_uplift_only

Source code for py_ice_cascade.examples.tests.test_uplift_only

"""
Unit tests for Python ICE-CASCADE uplift-only example case
"""

import os
import unittest
import py_ice_cascade.examples

[docs]class uplift_only_TestCase(unittest.TestCase):

[docs]    def test_run_successfully(self):
        """Confirm the example runs without error"""
        file_name = py_ice_cascade.examples.uplift_only()
        # TODO: confirm basic file atttributes
        os.remove(file_name)

        © Copyright 2016, Keith F. Ma.

  Built with Sphinx using a theme provided by Read the Docs.