def run(self): if len(self.raw_args) < 2: sys.stderr.write("Usage: checkmate git diff [snapshot-pk-1] [snapshot-pk-2]\n") return -1 snapshot_a_pk,snapshot_b_pk = self.raw_args[:2] try: snapshot_a = self.backend.get(GitSnapshot,{'pk' : snapshot_a_pk}) except GitSnapshot.DoesNotExist: sys.stderr.write("Snapshot does not exist: %s\n" % snapshot_a_pk) return -1 try: snapshot_b = self.backend.get(GitSnapshot,{'pk' : snapshot_b_pk}) except GitSnapshot.DoesNotExist: sys.stderr.write("Snapshot does not exist: %s\n" % snapshot_b_pk) return -1 code_environment = CodeEnvironment([],{},{}) diff = code_environment.diff_snapshots(snapshot_a,snapshot_b) for key,values in diff.issues.items(): if not values: continue print key for value in values: print value.analyzer,value.description
def analyze_and_generate_diffs(self,branch,snapshots,diff_list): analyzed_snapshots = {} new_analyzed_snapshots = {} if 'project_settings' in self.opts: project_settings = self.opts['project_settings'] else: project_settings = self.project.settings #we look for a .checkmate.yml file in the main branch of the project #if we find it, we either replace the project settings, update them #or do nothing, depending on the desired configuration. try: git_settings = self.project.git.get_settings() if git_settings is not None: if git_settings.get('overwrite_project_settings',False): project_settings = git_settings elif not project_settings.get('ignore_git_settings',False): project_settings.update(git_settings) except ValueError: logger.warning("Error when loading checkmate settings from git...") git_settings = {} code_environment = CodeEnvironment(self.project, global_settings=self.settings, project_settings=project_settings) code_environment.env['branch'] = branch code_environment.env['project'] = self.project for git_snapshot in snapshots: try: query = {'sha' : git_snapshot.sha, 'project' : self.project} git_snapshot = self.backend.get(GitSnapshot,query,include = ('snapshot',)) snapshot = git_snapshot.snapshot #we check if the snapshot is analyzed and if the analysis configuration matches if snapshot.analyzed and snapshot.configuration == self.project.configuration: analyze_snapshot = False else: analyze_snapshot = True snapshot.configuration = self.project.configuration except GitSnapshot.DoesNotExist: analyze_snapshot = True snapshot = Snapshot() snapshot.configuration = self.project.configuration except GitSnapshot.MultipleDocumentsReturned: logger.error("Multiple snapshots returned, deleting...") with self.backend.transaction(): self.backend.filter(GitSnapshot,query).delete() analyze_snapshot = True if analyze_snapshot: try: file_revisions = self.project.git.get_file_revisions(git_snapshot.sha) except: logger.error("Cannot fetch file revisions for snapshot %s in project %s" % (git_snapshot.sha,self.project.pk) ) continue code_environment.file_revisions = file_revisions git_snapshot.snapshot = code_environment.analyze(file_revisions, save_if_empty = True, snapshot=snapshot) new_analyzed_snapshots[git_snapshot.sha] = git_snapshot with self.backend.transaction(): git_snapshot.snapshot.hash = git_snapshot.sha self.backend.save(git_snapshot.snapshot) git_snapshot.project = self.project self.backend.save(git_snapshot) analyzed_snapshots[git_snapshot.sha] = git_snapshot snapshot_pairs = [] for diff_params in diff_list: try: snapshot_pairs.append([analyzed_snapshots[diff_params['snapshot_a']] ,analyzed_snapshots[diff_params['snapshot_b']]]) except KeyError: continue diffs = [] for git_snapshot_a,git_snapshot_b in snapshot_pairs: diff = None try: query = {'snapshot_a' : git_snapshot_a.snapshot, 'snapshot_b' : git_snapshot_b.snapshot} diff = self.backend.get(Diff,query) except Diff.DoesNotExist: logger.debug("Generating a diff between snapshots %s and %s" % (git_snapshot_a.sha, git_snapshot_b.sha)) #if the configuration of the diff does not match the project configuration, we regenerate it if diff is None or diff.configuration != self.project.configuration: if diff is not None: diff.configuration = self.project.configuration diff,diff_file_revisions,diff_issue_occurrences = code_environment.diff_snapshots( git_snapshot_a.snapshot, git_snapshot_b.snapshot, save = True, diff = diff) diffs.append(diff) return analyzed_snapshots,diffs
def run(self): if not self.opts['branch']: branch_name = self.project.git.get_default_branch() else: branch_name = self.opts['branch'] if branch_name is None: raise eslf.CommandException("No default branch defined!") try: branch = self.backend.get(GitBranch, {'project.pk' : self.project.pk,'name' : branch_name }) diffs = [] except GitBranch.DoesNotExist: raise self.CommandException("Cannot load branch %s" % branch_name) if self.opts['type'] == 'last_analysis': if not branch.get('last_analyzed_snapshot'): raise self.CommandException("No data about last analyzed snapshot available for branch %s" % branch_name) git_snapshot_a = branch.last_analyzed_snapshot.eager if not 'head_snapshot' in branch: raise self.CommandException("No data about head snapshot available for branch %s" % branch_name) git_snapshot_b = branch.head_snapshot.eager if git_snapshot_a['sha'] == git_snapshot_b['sha']: raise self.CommandException("No changes since last analysis!") elif self.opts['type'] in ('weekly','daily','monthly'): if self.opts['from']: if isinstance(self.opts['from'],(str,unicode)): try: from_date = datetime.datetime.strptime(self.opts['from'],"%Y-%m-%d") except ValueError: raise self.CommandException("Invalid date format or value for `from` parameter (use YYYY-mm-dd)") else: try: from_date = self.project.git.get_snapshots(branch = branch_name,limit = 1)[0]\ .committer_date + datetime.timedelta(days = 1) except IndexError: raise self.CommandException("No snapshots on branch %s" % branch_name) dt = get_first_date_for_group(from_date,self.opts['type'],1+self.opts['offset']) if self.opts['type'] == 'daily': deltat = datetime.timedelta(days = 1) elif self.opts['type'] == 'weekly': deltat = datetime.timedelta(days = 7) elif self.opts['type'] == 'monthly': deltat = datetime.timedelta(days = calendar.monthrange(dt.year,dt.month)[1]) snapshots = self.project.git.get_snapshots(branch = branch_name, since = dt.ctime(), until = (dt+deltat).ctime()) if not snapshots: raise self.CommandException("No snapshots on branch %s" % branch_name) grouped_snapshots = group_snapshots_by_date(snapshots,self.opts['type']) snapshots_list = grouped_snapshots.values()[0] sha_a,sha_b = snapshots_list[0]['sha'],snapshots_list[-1]['sha'] try: git_snapshot_a = self.backend.get(GitSnapshot,{'sha' : sha_a, 'snapshot.project' : self.project}) except GitSnapshot.DoesNotExist: raise self.CommandException("Unknown snapshot: %s" % sha_a) try: git_snapshot_b = self.backend.get(GitSnapshot,{'sha' : sha_b, 'snapshot.project' : self.project}) except GitSnapshot.DoesNotExist: raise self.CommandException("Unknown snapshot: %s" % sha_b) else: if len(self.extra_args) != 2: raise self.CommandException("You need to specify exactly two commit SHAs to be diffed!") sha_a,sha_b = self.extra_args try: git_snapshot_a = self.backend.get(GitSnapshot,{'sha' : sha_a, 'snapshot.project' : self.project}) except GitSnapshot.DoesNotExist: raise self.CommandException("Unknown snapshot: %s" % sha_a) try: git_snapshot_b = self.backend.get(GitSnapshot,{'sha' : sha_b, 'snapshot.project' : self.project}) except GitSnapshot.DoesNotExist: raise self.CommandException("Unknown snapshot: %s" % sha_b) #We generate the diff, or fetch it from the database in case it already exists. if 'settings' in self.opts: settings = self.opts['settings'] else: settings = self.project.get('settings',{}) try: diff = self.backend.get(Diff,{'snapshot_a' : git_snapshot_a.snapshot, 'snapshot_b' : git_snapshot_b.snapshot}) except Diff.DoesNotExist: code_environment = CodeEnvironment(self.project, [], settings=settings) diff,diff_file_revisions,diff_issue_occurrences = code_environment.diff_snapshots(git_snapshot_a.snapshot, git_snapshot_b.snapshot,save = True) return diff