text: # -*- encoding: utf-8 -*-
  #
  # Copyright © 2017 Red Hat, Inc.
  #
  # 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.
  
  import copy
  
  import daiquiri
  
  import github
  
  LOG = daiquiri.getLogger(__name__)
  
  
  def is_configured(g_repo, branch, rule, data):
  
      if data is None:
          return rule is None
      elif rule is None:
          return False
  
      # NOTE(sileht): Transform the payload into rule
      del data['url']
  
      if "required_status_checks" in data:
          del data["required_status_checks"]["url"]
          del data["required_status_checks"]["contexts_url"]
          data["required_status_checks"]["contexts"] = sorted(
              data["required_status_checks"]["contexts"])
      else:
          data["required_status_checks"] = None
  
      if "required_pull_request_reviews" in data:
          del data["required_pull_request_reviews"]["url"]
      else:
          data["required_pull_request_reviews"] = None
  
      del data["enforce_admins"]["url"]
      data["enforce_admins"] = data["enforce_admins"]["enabled"]
  
      if "restrictions" not in data:
          data["restrictions"] = None
  
      rsc = rule["protection"].get("required_status_checks")
      if rsc and "contexts" in rsc:
          rsc["contexts"] = sorted(rsc["contexts"])
  
      configured = rule['protection'] == data
      if not configured:  # pragma: no cover
          LOG.warning("Misconfigured branch: %s != %s",
                      data, rule['protection'],
                      branch=branch, repository=g_repo.full_name)
      return configured
  
  
  def protect(g_repo, branch, rule):
      if g_repo.organization and rule['protection'][
              'required_pull_request_reviews']:
          rule = copy.deepcopy(rule)
          rule['protection']['required_pull_request_reviews'][
              'dismissal_restrictions'] = {}
  
      # NOTE(sileht): Not yet part of the API
      # maybe soon https://github.com/PyGithub/PyGithub/pull/527
      return g_repo._requester.requestJsonAndCheck(
          'PUT',
          "{base_url}/branches/{branch}/protection".format(
              base_url=g_repo.url, branch=branch),
          input=rule['protection'],
          headers={'Accept': 'application/vnd.github.luke-cage-preview+json'}
      )
  
  
  def unprotect(g_repo, branch):
      # NOTE(sileht): Not yet part of the API
      # maybe soon https://github.com/PyGithub/PyGithub/pull/527
      try:
          g_repo._requester.requestJsonAndCheck(
              'DELETE',
              "{base_url}/branches/{branch}/protection".format(
                  base_url=g_repo.url, branch=branch),
              headers={'Accept': 'application/vnd.github.luke-cage-preview+json'}
          )
      except github.GithubException as e:  # pragma: no cover
          if e.status == 404 and e.data["message"] == 'Branch not protected':
              return
          raise
  
  
  def get_protection(g_repo, branch):
      try:
          headers, data = g_repo._requester.requestJsonAndCheck(
              "GET", g_repo.url + "/branches/" + branch + '/protection',
              headers={'Accept': 'application/vnd.github.luke-cage-preview+json'}
          )
          return data
      except github.GithubException as e:
          if e.status == 404 and e.data["message"] == "Branch not protected":
              return None
          else:  # pragma: no cover
              raise
  
  
  def configure_protection_if_needed(g_repo, branch, rule):
  
      data = get_protection(g_repo, branch)
      if not is_configured(g_repo, branch, rule, data):
          # NOTE(sileht): Updating some value are a bit broken, like setting
          # null to disable an already set required_pull_request_reviews or
          # required_status_checks. So to be sure we setup what we want
          # remove everything and then protect the branch
          unprotect(g_repo, branch)
          if rule is not None:
              headers, data = protect(g_repo, branch, rule)
          else:
              data = get_protection(g_repo, branch)
  
          if not is_configured(g_repo, branch, rule, data):  # pragma: no cover
              raise RuntimeError("Branch %s of %s is still misconfigured, "
                                 "abandoning" % (branch, g_repo.full_name))
  