def test_git_invocation(tmp_path):
    """ Tests for the git/git_output functions. """
    repo_path = tmp_path / 'repo'
    repo_path.mkdir()
    assert repo_path.is_dir()  # Ensure the dir is there for us to work with.
    repo_dir = str(repo_path)

    git('init', git_dir=repo_dir)

    (repo_path / 'initial').write_text(u'initial')
    git('add', 'initial', git_dir=repo_dir)

    # Check that we can report an error on failure.
    with pytest.raises(GitError) as err:
        git('add', 'foo', git_dir=repo_dir)
    assert err.value.stderr.startswith('fatal')
    assert repr(err.value).startswith('GitError')

    # Check that errors can be ignored.
    git('add', 'foo', git_dir=repo_dir, ignore_error=True)

    output = git_output('commit', '-m', 'initial', git_dir=repo_dir)
    assert len(output) > 0

    # Ensure that the output is stripped.
    output = git_output('rev-list', 'HEAD', git_dir=repo_dir)
    assert '\n' not in output
    output = git_output('rev-list', 'HEAD', git_dir=repo_dir, strip=False)
    assert '\n' in output

    # Ensure that commit exists works only for commit hashes.
    hash = output.strip()
    assert commit_exists(hash)
    assert not commit_exists('HEAD')
    assert not commit_exists(hash + 'abc')
    assert not commit_exists('000000')

    # Ensure that we can get the directory of the checkout even when the
    # working directory is a subdirectory.
    os.chdir(repo_dir)
    dir_a = get_current_checkout_directory()
    (repo_path / 'subdir').mkdir()
    cwd = os.getcwd()
    os.chdir(os.path.join(repo_dir, 'subdir'))
    dir_b = get_current_checkout_directory()
    os.chdir(cwd)
    assert dir_a == dir_b

    assert read_file_or_none('HEAD', 'initial') == 'initial'
    assert read_file_or_none(hash, 'initial') == 'initial'
    assert read_file_or_none('HEAD', 'path/does-not-exist') is None
    assert read_file_or_none('foo', 'initial') is None
def find_am_configs(remote: str = 'origin') -> List[AMTargetBranchConfig]:
    contents: Optional[str] = read_file_or_none(
        f'{remote}/repo/apple-llvm-config/am',
        f'apple-llvm-config/am/am-config.json')
    if not contents:
        return []
    configs = json.loads(contents)
    if not configs:
        return []
    return [AMTargetBranchConfig(json_dict) for json_dict in configs]
 def dispatch(self, params):
     ci_job_config_filename = f'apple-llvm-config/ci-jobs/{self.ci_jobs}.json'
     log.debug('Test plan %s: loading ci config %s', self.name,
               ci_job_config_filename)
     file_contents = read_file_or_none('origin/repo/apple-llvm-config/pr',
                                       ci_job_config_filename)
     if not file_contents:
         raise RuntimeError(f'ci config {ci_job_config_filename} not found')
     ci_job_config_json = json.loads(file_contents)
     ci_job_config = JenkinsCIConfig(ci_job_config_json)
     params.update(self.params)
     log.debug('Test plan %s: dispatching ci job requests for params: %s',
               self.name, params)
     ci_job_config.dispatch(params, self.name)
 def dispatch_test_plan_for_pull_request(self, name: str, pr_number: int):
     """ Loads a test plan and dispatches it for a given pull request. """
     test_plans_filename = 'apple-llvm-config/ci-test-plans.json'
     log.debug('Test plan dispatcher: loading test plans %s',
               test_plans_filename)
     file_contents = read_file_or_none('origin/repo/apple-llvm-config/pr',
                                       test_plans_filename)
     if not file_contents:
         raise TestPlanNotFoundError(name)
     test_plans: Dict[str, TestPlan] = {}
     tp = json.loads(file_contents)['test-plans']
     for k in tp:
         test_plans[k] = TestPlan(k, tp[k])
     if name not in test_plans:
         raise TestPlanNotFoundError(name)
     log.debug('Test plan dispatcher: invoking %s for pull request #%s',
               name, str(pr_number))
     test_plans[name].dispatch({'pullRequestID': str(pr_number)})