docs: def analyze(self,file_revisions, save_if_empty = False, snapshot=None):
  
          """
          Handling dependencies:
  
          * First, genreate a list of file revisions for this snapshot
          * Then, check which ones of of them already exist
          * For the existing ones, check their dependencies
          * If any of the dependencies are outdated, add the dependent file revision to the analyze list
  
          How to handle hashes? Dependencies should be included in the hash sum.
  
          * Just load the files based on their SHA values
          * Check if dependencies match with the current set based on SHA values
          * If not, re-analyze the file revision
          * After analysis, calculate the hash value based on path, SHA and dependencies
          """
  
          logger.debug("Analyzing code environment...")
  
          if snapshot is None:
              snapshot = Snapshot()
              snapshot.configuration = self.project.configuration
  
          file_revisions_by_pk = dict([(fr.hash,fr) for fr in file_revisions])
  
          filtered_file_revisions = self.filter_file_revisions(file_revisions)
          filtered_file_revisions_by_pk = dict([(fr.hash,fr) for fr in filtered_file_revisions])
  
          excluded_file_revisions = [file_revisions_by_pk[pk]
                                      for pk in file_revisions_by_pk.keys()
                                      if not pk in filtered_file_revisions_by_pk
                                    ]
  
          logger.info("Excluding %d file revisions" % len(excluded_file_revisions))
  
          file_revisions = filtered_file_revisions
          file_revisions_by_pk = filtered_file_revisions_by_pk
  
          max_file_revisions = 10000
  
          if len(file_revisions) > max_file_revisions:
  
              logger.warning("Too many file revisions (%d) in snapshot, truncating at %d" %
                           (len(file_revisions),max_file_revisions))
              file_revisions_by_pk = dict(sorted(file_revisions_by_pk.items(),
                                                 key = lambda x:x[0])[:max_file_revisions])
              file_revisions = file_revisions_by_pk.values()
  
          i = 0
          chunk_size = 50
          existing_file_revisions = []
          file_revisions_by_pk_keys = file_revisions_by_pk.keys()
  
          #we only check 50 keys at a time and then incrementally save them
          while i < len(file_revisions_by_pk_keys):
              file_revisions_by_pk_chunk = file_revisions_by_pk_keys[i:i+chunk_size]
              if not file_revisions_by_pk_chunk:
                  break
              existing_file_revisions.extend(list(self.project.backend.filter(FileRevision,{
                      'project' : self.project,
                      'hash' : {'$in' : file_revisions_by_pk_chunk}
                      })))
              i+=chunk_size
  
          existing_file_revisions_by_pk = dict([(fr.hash,fr) for fr in existing_file_revisions])
          new_file_revisions = [file_revision for file_revision in file_revisions
                                  if not file_revision.hash in existing_file_revisions_by_pk]
  
          new_file_revisions = []
  
          for file_revision in file_revisions:
              if not file_revision.hash in existing_file_revisions_by_pk:
                  file_revision.configuration = self.project.configuration
                  new_file_revisions.append(file_revision)
              elif existing_file_revisions_by_pk[file_revision.hash].configuration != self.project.configuration:
                  #we replace the pk and configuration values of the new file_revision object, so that
                  #it will overwrite the old version...
                  file_revision.pk = existing_file_revisions_by_pk[file_revision.hash].pk
                  file_revision.configuration = self.project.configuration
                  new_file_revisions.append(file_revision)
  
          file_revisions_dict = {}
  
          for file_revision in existing_file_revisions+new_file_revisions:
              file_revisions_dict[file_revision.path] = file_revision
  
          logger.info("Analyzing %d new file revisions (%d are already analyzed)" % (
                  len(new_file_revisions),
                  len(existing_file_revisions)
                  ))
          i = 0
  
          #We set the project information in the snapshot.
          snapshot.project = self.project
          snapshot.file_revisions = file_revisions_dict.values()
          self.env['snapshot'] = snapshot
  
          try:
              while i < len(new_file_revisions):
                  j = i+10 if i+10 < len(new_file_revisions) else len(new_file_revisions)
                  logger.info("Analyzing and saving: %d - %d (%d remaining)" %
                      (i, j, len(new_file_revisions) - i ))
                  file_revisions_slice = new_file_revisions[i:j]
                  analyzed_file_revisions = self.analyze_file_revisions(file_revisions_slice)
                  logger.info("Annotating and saving file revisions...")
                  self.save_file_revisions(snapshot,analyzed_file_revisions)
                  i+=10
              logger.info("Summarizing file revisions...")
              snapshot.summary = self.summarize(file_revisions_dict.values())
          finally:
              del self.env['snapshot']
  
          snapshot.analyzed = True
  
          logger.info("Saving snapshot...")
  
          with self.project.backend.transaction():
              self.project.backend.save(snapshot)
  
          logger.info("Done analyzing snapshot %s" % snapshot.pk)
  
          return snapshot