Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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