def command_template(context: click.Context, **kwargs: tp.Any) -> None: # extract common arguments and plot config from context plot_config: PlotConfig = PlotConfig(False) try: generator_instance = generator_cls(plot_config, **kwargs) plots = generator_instance.generate() plot = plots[0] if len(plots) > 1: def set_plot(selected_plot: Plot) -> None: nonlocal plot plot = selected_plot cli_list_choice( "The given plot generator creates multiple plots" " please select one:", plots, lambda p: p.name, set_plot) cmap = create_lazy_commit_map_loader(context.obj['project'], None, 'HEAD', None)() extend_with_smooth_revs(context.obj['case_study'], cmap, context.obj['boundary_gradient'], context.obj['ignore_blocked'], plot, context.obj['merge_stage']) store_case_study(context.obj['case_study'], context.obj['path']) except PlotGeneratorFailed as ex: print(f"Failed to create plot generator {generator_cls.NAME}: " f"{ex.message}")
def __gen_sample(ctx: click.Context, distribution: str, end: str, start: str, num_rev: int, only_code_commits: bool) -> None: """ Add revisions based on a sampling Distribution. Distribution: The sampling method to use """ sampling_method: NormalSamplingMethod = NormalSamplingMethod \ .get_sampling_method_type( distribution )() project_repo_path = get_local_project_git_path(ctx.obj['project']) if end != "HEAD" and not is_commit_hash(end): end = get_commits_before_timestamp(end, project_repo_path)[0].hash if start is not None and not is_commit_hash(start): commits_before = get_commits_before_timestamp(start, project_repo_path) if commits_before: start = commits_before[0].hash else: start = get_initial_commit(project_repo_path).hash cmap = create_lazy_commit_map_loader(ctx.obj['project'], None, end, start)() extend_with_distrib_sampling(ctx.obj['case_study'], cmap, sampling_method, ctx.obj['merge_stage'], num_rev, ctx.obj['ignore_blocked'], only_code_commits) store_case_study(ctx.obj['case_study'], ctx.obj['path'])
def gen(self) -> None: """Generate the case study using the selected strategy, project and strategy specific arguments.""" cmap = create_lazy_commit_map_loader(self.selected_project, None, 'HEAD', None)() version = self.cs_version.value() case_study = CaseStudy(self.revision_list_project, version) paper_config = vara_cfg()["paper_config"]["current_config"].value path = Path(vara_cfg()["paper_config"]["folder"].value) / ( paper_config + f"/{self.revision_list_project}_{version}.case_study") if self.strategie_forms.currentIndex( ) == GenerationStrategie.SAMPLE.value: sampling_method = NormalSamplingMethod.get_sampling_method_type( self.sampling_method.currentText()) extend_with_distrib_sampling(case_study, cmap, sampling_method(), 0, self.num_revs.value(), True, self.code_commits.clicked) elif self.strategie_forms.currentIndex( ) == GenerationStrategie.SELECT_REVISION.value: selected_rows = self.revision_list.selectionModel().selectedRows(0) selected_commits = [row.data() for row in selected_rows] extend_with_extra_revs(case_study, cmap, selected_commits, 0) self.revision_list.clearSelection() self.revision_list.update() elif self.strategie_forms.currentIndex( ) == GenerationStrategie.REVS_PER_YEAR.value: extend_with_revs_per_year( case_study, cmap, 0, True, get_local_project_git_path(self.selected_project), self.revs_per_year.value(), self.seperate.checkState()) store_case_study(case_study, path)
def __gen_specific(ctx: click.Context, revisions: tp.List[str]) -> None: """ Adds a list of specified revisions to the CS. Revisions: Revisions to add """ cmap = create_lazy_commit_map_loader(ctx.obj['project'], None, 'HEAD', None)() extend_with_extra_revs(ctx.obj['case_study'], cmap, revisions, ctx.obj['merge_stage']) store_case_study(ctx.obj['case_study'], ctx.obj['path'])
def __gen_release(ctx: click.Context, release_type: ReleaseType) -> None: """ Extend a case study with revisions marked as a release. This relies on the project to determine appropriate revisions. release_type: Release type to consider """ cmap = create_lazy_commit_map_loader(ctx.obj['project'], None, 'HEAD', None)() extend_with_release_revs(ctx.obj['case_study'], cmap, release_type, ctx.obj['ignore_blocked'], ctx.obj['merge_stage']) store_case_study(ctx.obj['case_study'], ctx.obj['path'])
def __gen_bug_commits(ctx: click.Context, report_type: tp.Type['BaseReport']) -> None: """ Extend a case study with revisions that either introduced or fixed a bug as determined by the given SZZ tool. REPORT_TYPE: report to use for determining bug regions """ cmap = create_lazy_commit_map_loader(ctx.obj['project'], None, 'HEAD', None)() extend_with_bug_commits(ctx.obj['case_study'], cmap, report_type, ctx.obj['merge_stage'], ctx.obj['ignore_blocked']) store_case_study(ctx.obj['case_study'], ctx.obj['path'])
def __gen_per_year(ctx: click.Context, revs_per_year: int, separate: bool) -> None: """ Add a number of revisions per year. revs-per-year: number of revisions to generate per year """ cmap = create_lazy_commit_map_loader(ctx.obj['project'], None, 'HEAD', None)() extend_with_revs_per_year(ctx.obj['case_study'], cmap, ctx.obj['merge_stage'], ctx.obj['ignore_blocked'], ctx.obj['git_path'], revs_per_year, separate) store_case_study(ctx.obj['case_study'], ctx.obj['path'])
def draw_cves( axis: axes.Axes, project: tp.Type[Project], revisions: tp.List[FullCommitHash], cve_line_width: int, cve_color: str, label_size: int, vertical_alignment: str ) -> None: """ Annotates CVEs for a project in an existing plot. Args: axis: the axis to use for the plot project: the project to add CVEs for revisions: a list of revisions included in the plot in the order they appear on the x-axis cve_line_width: the line width of CVE annotations cve_color: the color of CVE annotations label_size: the label size of CVE annotations vertical_alignment: the vertical alignment of CVE annotations """ cmap = create_lazy_commit_map_loader(project.NAME)() revision_time_ids = [cmap.time_id(rev) for rev in revisions] cve_provider = CVEProvider.get_provider_for_project(project) for revision, cves in cve_provider.get_revision_cve_tuples(): cve_time_id = cmap.time_id(revision) if cve_time_id in revision_time_ids: index = float(revisions.index(revision)) else: # revision not in sample; draw line between closest samples index = len([x for x in revision_time_ids if x < cve_time_id]) - 0.5 transform = axis.get_xaxis_transform() for cve in cves: axis.axvline( index, label=cve.cve_id, linewidth=cve_line_width, color=cve_color ) axis.text( index + 0.1, 0, cve.cve_id, transform=transform, rotation=90, size=label_size, color=cve_color, va=vertical_alignment )
def draw_bugs(axis: axes.Axes, project: tp.Type[Project], revisions: tp.List[FullCommitHash], bug_line_width: int, bug_color: str, label_size: int, vertical_alignment: str) -> None: """ Annotates bugs for a project in an existing plot. Args: axis: the axis to use for the plot project: the project to add bugs for revisions: a list of revisions included in the plot in the order they appear on the x-axis bug_line_width: the line width of bug annotations bug_color: the color of bug annotations label_size: the label size of bug annotations vertical_alignment: the vertical alignment of bug annotations """ cmap = create_lazy_commit_map_loader(project.NAME)() revision_time_ids = [cmap.time_id(rev) for rev in revisions] bug_provider = BugProvider.get_provider_for_project(project) for rawbug in bug_provider.find_raw_bugs(): bug_time_id = cmap.time_id(rawbug.fixing_commit) if bug_time_id in revision_time_ids: index = float(revisions.index(rawbug.fixing_commit)) else: # revision not in sample; draw line between closest samples index = len([x for x in revision_time_ids if x < bug_time_id]) - 0.5 label = " ".join([f"#{rawbug.issue_id}"]) transform = axis.get_xaxis_transform() axis.axvline(index, label=label, linewidth=bug_line_width, color=bug_color) axis.text(index + 0.1, 0, label, transform=transform, rotation=90, size=label_size, color=bug_color, va=vertical_alignment)
def get_status( case_study: CaseStudy, experiment_type: tp.Type[VersionExperiment], longest_cs_name: int, sep_stages: bool, sort: bool, use_color: bool = False, total_status_occurrences: tp.Optional[tp.DefaultDict[ FileStatusExtension, tp.Set[ShortCommitHash]]] = None ) -> str: """ Return a string representation that describes the current status of the case study. Args: case_study: to print the status for experiment_type: experiment type to print files for longest_cs_name: amount of chars that should be considered for sep_stages: print each stage separeted sort: sort the output order of the case studies use_color: add color escape sequences for highlighting total_status_occurrences: mapping from all occured status to a set of all revisions (total amount of revisions) Returns: a full string representation of all case studies """ status = get_short_status(case_study, experiment_type, longest_cs_name, use_color, total_status_occurrences) + "\n" if sort: cmap = create_lazy_commit_map_loader(case_study.project_name)() def rev_time(rev: tp.Tuple[ShortCommitHash, FileStatusExtension]) -> int: return cmap.short_time_id(rev[0]) if sep_stages: stages = case_study.stages for stage_num in range(0, case_study.num_stages): status += f" Stage {stage_num}" stage_name = stages[stage_num].name if stage_name: status += f" ({stage_name})" status += "\n" tagged_revs = _combine_tagged_revs_for_experiment( case_study, experiment_type, stage_num) if sort: tagged_revs = sorted(tagged_revs, key=rev_time, reverse=True) for tagged_rev_state in tagged_revs: status += f" {tagged_rev_state[0].hash} " \ f"[{tagged_rev_state[1].get_colored_status()}]\n" else: tagged_revs = list( dict.fromkeys( _combine_tagged_revs_for_experiment(case_study, experiment_type))) if sort: tagged_revs = sorted(tagged_revs, key=rev_time, reverse=True) for tagged_rev_state in tagged_revs: status += f" {tagged_rev_state[0].hash} " \ f"[{tagged_rev_state[1].get_colored_status()}]\n" return status