示例#1
0
def smart_repo(empty_repo: Repo, runner: CliRunner) -> SmartRepo:
    runner.invoke(smart_git.install, [empty_repo.working_dir, r'E:\env\LLVM\bin\libclang.dll', '--silent'])
    repo = SmartRepo(empty_repo.working_dir)
    try:
        yield repo
    finally:
        repo.git.clear_cache()
        repo.close()
示例#2
0
def test_rename_add_merge(smart_repo: SmartRepo):
    added_line_path = CursorPath(
        ('a.c', 'main()', (CursorKind.COMPOUND_STMT, 0),
         (CursorKind.COMPOUND_ASSIGNMENT_OPERATOR, 0)))
    variable_path = CursorPath(('a.c', 'main()', (CursorKind.COMPOUND_STMT, 0),
                                (CursorKind.DECL_STMT, 0), 'a'))

    file_added = FileAdded('a.c', smart_repo.contents('a.c', 'initial'))
    line_added = SubASTInserted(smart_repo,
                                smart_repo.contents('a.c', 'add-line'),
                                added_line_path)
    renamed = VariableRenamed(variable_path, 'b')

    final_contents = as_lines('', 'int main() {', '    int b = 0;',
                              '    b += 1;', '    return b;', '}')

    assert get_changes(smart_repo, 'other-to-master') \
        == [[file_added], [renamed], [SubASTInserted(smart_repo, final_contents, added_line_path)]]
    assert tuple(smart_repo.rev_parse('other-to-master').parents) == (
        smart_repo.rev_parse('rename'), smart_repo.rev_parse('add-line'))
    assert get_changes(smart_repo, 'master-to-other') \
        == [[file_added], [line_added], [renamed]]
    assert tuple(smart_repo.rev_parse('master-to-other').parents) == (
        smart_repo.rev_parse('add-line'), smart_repo.rev_parse('rename'))

    assert smart_repo.contents('a.c', 'other-to-master')\
        == smart_repo.contents('a.c', 'master-to-other') \
        == final_contents
示例#3
0
 def detect(cls, repo: SmartRepo,
            diff: git.DiffIndex) -> Iterable['SubASTInserted']:
     for m in diff.iter_change_type('M'):
         with repo.ast(m.a_blob) as a_ast, file_from_blob(
                 m.b_blob) as b_file:
             b_file.seek(0)
             b_ast = repo.get_cindex().parse(b_file.name)
             for inserted_path in cls.detect_ast_insertions(
                     a_ast.cursor, b_ast.cursor, CursorPath([m.a_path])):
                 yield SubASTInserted(repo, b_file.readlines(),
                                      inserted_path)
示例#4
0
 def __init__(self, repo: SmartRepo, file_lines: List[bytes],
              ast_path: CursorPath):
     with file_from_text(file_lines, ast_path.file) as file:
         translation_unit = repo.get_cindex().parse(file.name)
     cursor = ast_path.locate(translation_unit, ast_path.file)
     parent_cursor = ast_path.drop(1).locate(translation_unit,
                                             ast_path.file)
     siblings = list(parent_cursor.get_children())
     insertion_point = siblings.index(cursor) - 1
     self.parent_path = ast_path.drop(1)
     if insertion_point == -1:
         from_location = cursor.extent.start
         self.predecessor_path = None
         if len(siblings) > 1:
             to_location = SourceLocation.from_offset(
                 translation_unit, siblings[1].extent.start.file,
                 siblings[1].extent.start.offset - 1)
         else:
             to_location = cursor.extent.end
     else:
         from_location = siblings[insertion_point].extent.end
         self.predecessor_path = ast_path.drop(1).appended(
             parent_cursor, siblings[insertion_point])
         to_location = cursor.extent.end
     self.from_location = from_location.offset
     self.to_location = to_location.offset
     self.ast_path = ast_path
     self.file_lines = file_lines
示例#5
0
def test_apply(smart_repo: SmartRepo):
    state = TreeBackedRepoState(smart_repo, smart_repo.head.commit.tree)
    change = VariableRenamed(smart_repo.find_cursor('a.c', lambda cur: cur.kind == CursorKind.VAR_DECL
                                                                       and cur.spelling == 'a'), 'meow')
    change.apply(smart_repo, state)
    assert state['a.c'] == as_lines('int main() {',
                                    '    int meow = 0;',
                                    '    return meow + (meow - 1);',
                                    '}')
示例#6
0
def get_repo(repo_path: str,
             *expected_statuses: RepoStatus) -> (SmartRepo, RepoStatus):
    """
    Open a GitPython Repo object for the given repository path.

    :param repo_path: path to the git repository.
    :param expected_statuses: in which repo status(es) the repo at repo_path should be. An Abort is thrown if it is
                              found in a different status.
    """
    current_status = RepoStatus.of(repo_path)
    if current_status not in expected_statuses:
        click.echo('{} should be {}, but is {}'.format(
            repo_path, 'either ' + ' or '.join(status.name
                                               for status in expected_statuses)
            if len(expected_statuses) > 1 else expected_statuses[0].name,
            current_status.name),
                   err=True)
        raise click.Abort
    return SmartRepo(repo_path), current_status
 def apply(self, repo: SmartRepo, repo_state: RepoState) -> None:
     file_text = repo_state[self.path.file]
     with file_from_text(file_text, self.path.file) as file:
         translation_unit = repo.get_cindex().parse(file.name)
         variable = self.path.locate(translation_unit, self.path.file)
         usages = search_ast(translation_unit, self.path.file,
                             lambda cursor: cursor.kind == CursorKind.DECL_REF_EXPR
                                            and cursor.get_definition() == variable)
         replacements = [Replacement(variable.location.line - 1, variable.location.column - 1,
                                     variable.location.column + len(variable.spelling) - 1, self.new_name)]
         for usage_path in usages:
             usage = usage_path.locate(translation_unit, self.path.file)
             range: SourceRange = usage.extent
             start: SourceLocation = range.start
             end: SourceLocation = range.end
             assert start.line == end.line
             assert file_text[start.line - 1][start.column - 1:end.column - 1] == variable.spelling.encode('utf-8')
             replacements.append(Replacement(start.line - 1, start.column - 1, end.column - 1, self.new_name))
         file_text = apply_replacements(file_text, replacements)
     repo_state[self.path.file] = file_text
示例#8
0
def get_changes(repo: SmartRepo, revision: str='HEAD') -> List[List[Change]]:
    changes_file_contents = repo.contents(CHANGES_FILE_NAME, revision)
    if changes_file_contents is None:
        return []
    return decode_changes(repo, changes_file_contents)
示例#9
0
def test_detect(smart_repo: SmartRepo):
    a = smart_repo.find_cursor('a.c', lambda c: c.spelling == 'b').drop(1).appended('a')
    assert get_changes(smart_repo) == [[FileAdded('a.c', smart_repo.contents('a.c', 'initial'))],
                                       [VariableRenamed(a, 'b')]]
 def detect(cls: Type['VariableRenamed'], repo: SmartRepo, diff: git.DiffIndex) -> Iterable['VariableRenamed']:
     for m in diff.iter_change_type('M'):
         with file_from_blob(m.a_blob) as a, file_from_blob(m.b_blob) as b:
             for renamed, new_name in RenamingDetector(repo.get_cindex()).get_renamed_variables(m.a_path, a.name,
                                                                                                b.name).items():
                 yield VariableRenamed(renamed, new_name)