<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::str::FromStr;

use bodyparser;
use bldr_core::build_config::{BLDR_CFG, BuildCfg};
use github_api_client::GitHubClient;
use hab_core::package::Plan;
use http_gateway::http::controller::*;
use iron::status;
use persistent;
use protocol::originsrv::{OriginProject, OriginProjectGet};
use protocol::scheduler::{Group, GroupCreate};
use router::Router;

use error::Error;
use headers::*;
use types::*;

pub enum GitHubEvent {
    Push,
    Ping,
}

impl FromStr for GitHubEvent {
    type Err = Error;

    fn from_str(event: &str) -> Result<Self, Self::Err> {
        match event {
            "ping" => Ok(GitHubEvent::Ping),
            "push" => Ok(GitHubEvent::Push),
            _ => Err(Error::UnknownGitHubEvent(event.to_string())),
        }
    }
}

enum HandleResult<T> {
    Ok(T),
    Err(Response),
}

pub fn handle_event(req: &mut Request) -> IronResult<Response> {
    let event = match req.headers.get::<XGitHubEvent>() {
        Some(&XGitHubEvent(ref event)) => {
            match GitHubEvent::from_str(event) {
                Ok(event) => event,
                Err(err) => return Ok(Response::with((status::BadRequest, err.to_string()))),
            }
        }
        _ => return Ok(Response::with(status::BadRequest)),
    };
    // JW TODO: Authenticate hook
    match event {
        GitHubEvent::Ping => Ok(Response::with(status::Ok)),
        GitHubEvent::Push => handle_push(req),
    }
}

pub fn repo_file_content(req: &mut Request) -> IronResult<Response> {
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let session = req.extensions.get::<Authenticated>().unwrap();
    let params = req.extensions.get::<Router>().unwrap();
    let path = match params.find("path") {
        Some(path) => path,
        None => return Ok(Response::with(status::BadRequest)),
    };
    let install_id = match params.find("install_id") {
        Some(install_id) => {
            match install_id.parse::<u32>() {
                Ok(install_id) => install_id,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        None => return Ok(Response::with(status::BadRequest)),
    };
    let token = {
        match github.app_installation_token(install_id) {
            Ok(token) => token,
            Err(err) => {
                return Ok(Response::with((status::BadGateway, err.to_string())));
            }
        }
    };
    let repo = {
        let repo = match params.find("repo") {
            Some(repo) => repo,
            None => return Ok(Response::with(status::BadRequest)),
        };
        let repos = match github.repositories(session.get_token(), install_id) {
            Ok(repos) => repos,
            Err(err) => return Ok(Response::with((status::BadGateway, err.to_string()))),
        };
        match repos.into_iter().find(|r| r.name == repo) {
            Some(repo) => repo,
            None => return Ok(Response::with(status::NotFound)),
        }
    };
    match github.contents(&token, repo.id, path) {
        Ok(search) => Ok(render_json(status::Ok, &search)),
        Err(err) => Ok(Response::with((status::BadGateway, err.to_string()))),
    }
}

pub fn search_code(req: &mut Request) -> IronResult<Response> {
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();<commit_msg>Use GitHub token to read files from remote instead of our own token<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::str::FromStr;

use bodyparser;
use bldr_core::build_config::{BLDR_CFG, BuildCfg};
use github_api_client::GitHubClient;
use hab_core::package::Plan;
use http_gateway::http::controller::*;
use iron::status;
use persistent;
use protocol::originsrv::{OriginProject, OriginProjectGet};
use protocol::scheduler::{Group, GroupCreate};
use router::Router;

use error::Error;
use headers::*;
use types::*;

pub enum GitHubEvent {
    Push,
    Ping,
}

impl FromStr for GitHubEvent {
    type Err = Error;

    fn from_str(event: &str) -> Result<Self, Self::Err> {
        match event {
            "ping" => Ok(GitHubEvent::Ping),
            "push" => Ok(GitHubEvent::Push),
            _ => Err(Error::UnknownGitHubEvent(event.to_string())),
        }
    }
}

enum HandleResult<T> {
    Ok(T),
    Err(Response),
}

pub fn handle_event(req: &mut Request) -> IronResult<Response> {
    let event = match req.headers.get::<XGitHubEvent>() {
        Some(&XGitHubEvent(ref event)) => {
            match GitHubEvent::from_str(event) {
                Ok(event) => event,
                Err(err) => return Ok(Response::with((status::BadRequest, err.to_string()))),
            }
        }
        _ => return Ok(Response::with(status::BadRequest)),
    };
    // JW TODO: Authenticate hook
    match event {
        GitHubEvent::Ping => Ok(Response::with(status::Ok)),
        GitHubEvent::Push => handle_push(req),
    }
}

pub fn repo_file_content(req: &mut Request) -> IronResult<Response> {
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let session = req.extensions.get::<Authenticated>().unwrap();
    let params = req.extensions.get::<Router>().unwrap();
    let path = match params.find("path") {
        Some(path) => path,
        None => return Ok(Response::with(status::BadRequest)),
    };
    let install_id = match params.find("install_id") {
        Some(install_id) => {
            match install_id.parse::<u32>() {
                Ok(install_id) => install_id,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        None => return Ok(Response::with(status::BadRequest)),
    };
    let token = {
        match github.app_installation_token(install_id) {
            Ok(token) => token,
            Err(err) => {
                return Ok(Response::with((status::BadGateway, err.to_string())));
            }
        }
    };
    let repo = {
        let repo = match params.find("repo") {
            Some(repo) => repo,
            None => return Ok(Response::with(status::BadRequest)),
        };
        let repos = match github.repositories(session.get_auth_token(), install_id) {
            Ok(repos) => repos,
            Err(err) => return Ok(Response::with((status::BadGateway, err.to_string()))),
        };
        match repos.into_iter().find(|r| r.name == repo) {
            Some(repo) => repo,
            None => return Ok(Response::with(status::NotFound)),
        }
    };
    match github.contents(&token, repo.id, path) {
        Ok(search) => Ok(render_json(status::Ok, &search)),
        Err(err) => Ok(Response::with((status::BadGateway, err.to_string()))),
    }
}

pub fn search_code(req: &mut Request) -> IronResult<Response> {
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
{'fraction_non_alphanumeric': 0.15130674002751032, 'fraction_numerical': 0.0025009378516943855, 'mean_word_length': 2.8881866796305298, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7041435', 'n_tokens_mistral': 2402, 'n_tokens_neox': 2356, 'n_words': 567}