Exemple #1
0
    def update(self, force_rebuild=False):
        """ Adds/updates all items in repo to index. Note: querying will call this automatically."""

        # if we've already updated the index during this script run, we're done!
        if self.index_updated:
            return False

        # if the index is not based on the current commit, rebuild from scratch
        if not self.index_based_on_current_commit():
            force_rebuild = True

        if force_rebuild:
            # get a new clean/empty index
            index = self.get_index(force_rebuild)
            index_writer = index.writer()

            # index all documents
            documents = self.document_iterator()
            activity_description = 'Rebuilding'
        else:
            # use the current index
            index = self.get_index()
            index_writer = index.writer()

            # delete uncommitted files that are in index already
            for filepath in self.get_indexed_uncommitted_files():
                index_writer.delete_by_term('path', filepath)

            # get list of uncommitted files and persist it
            uncommitted_files = lib_git.get_uncommitted_oval()
            self.set_indexed_uncommitted_files(uncommitted_files)

            # if there are no uncommitted files to index, we're done
            if not uncommitted_files:
                index_writer.commit()
                return False

            # index only uncommitted files
            documents = self.document_iterator(uncommitted_files)
            activity_description = 'Updating'

        # add all definition files to index
        counter = 0
        for document in documents:
            counter = counter + 1
            self.status_spinner(counter, '{0} {1} index'.format(activity_description, self.index_name), self.item_label)
            if 'deleted' in document and document['deleted']:
                index_writer.delete_by_term('path', document['path'])
                #self.message('debug', 'Deleting from index:\n\t{0} '.format(document['path']))
            else:
                index_writer.add_document(**document)
                #self.message('debug', 'Upserting to index:\n\t{0} '.format(document['path']))
        index_writer.commit()
        self.status_spinner(counter, '{0} {1} index'.format(activity_description, self.index_name), self.item_label, True)

        # update indexed commit
        self.set_indexed_commit_hash()
        self.index_updated = True
def get_changed_ids_from_git():
    try:
        changed_files = lib_git.get_uncommitted_oval()
        if not changed_files or changed_files is None:
            return None

        change_list = []
        for file in changed_files:
            change_list.add(lib_repo.path_to_oval_id(file))

        return change_list

    except Exception:
        if main.verbose:
            print("## Error while querying git for changes: ", format(Exception))
        return None
Exemple #3
0
    def update(self, force_rebuild=False):
        """ Adds/updates all items in repo to index. Note: querying will call this automatically."""

        # if we've already updated the index during this script run, we're done!
        if self.index_updated:
            return False

        # we only need to do this once per script lifetime
        self.index_updated = True
        
        # if the index is not based on the current commit, rebuild from scratch
        if not self.index_based_on_current_commit():
            force_rebuild = True

        if force_rebuild:
            # get a new clean/empty index
            index = self.get_index(force_rebuild)

            # get a high-performance writer as per: https://pythonhosted.org/Whoosh/batch.html
            index_writer = index.writer(procs=4, multisegment=True)

            # index all documents
            documents = self.document_iterator()
            activity_description = 'Rebuilding'

            # update indexed commit
            self.set_indexed_commit_hash()
        else:
            # use the current index
            index = self.get_index()
            index_writer = index.writer()

            # delete uncommitted files that are in index already
            for filepath in self.get_indexed_uncommitted_files():
                index_writer.delete_by_term('path', filepath)

            # get list of uncommitted files and persist it
            uncommitted_files = lib_git.get_uncommitted_oval()
            self.set_indexed_uncommitted_files(uncommitted_files)

            # nothing to update? done!
            if not uncommitted_files:
                index_writer.commit()
                return

            # index only uncommitted files
            documents = self.document_iterator(uncommitted_files)
            activity_description = 'Updating'
        
        # add all definition files to index
        counter = 0
        try:
            for document in documents:
                counter = counter + 1
                self.status_spinner(counter, '{0} {1} index'.format(activity_description, self.index_name), self.item_label)
                if 'deleted' in document and document['deleted']:
                    index_writer.delete_by_term('oval_id', self.whoosh_escape(document['oval_id']))
                    #self.message('debug', 'Deleting from index:\n\t{0} '.format(self.whoosh_escape(document['oval_id'])))
                else:
                    index_writer.add_document(**document)
                    #self.message('debug', 'Upserting to index:\n\t{0} '.format(document['path']))
        except lib_xml.InvalidXmlError as e:
            # abort: cannot build index
            self.message('ERROR CANNOT BUILD INDEX', 'Invalid xml fragment\n\tFile: {0}\n\tMessage: {1}'.format(e.path, e.message))
            self.message('ERROR', 'deleting index and aborting execution')
            index_writer.commit()
            self.index.close()
            shutil.rmtree(self.get_index_path())
            sys.exit(1)

        self.status_spinner(counter, '{0} {1} index'.format(activity_description, self.index_name), self.item_label, True)
        index_writer.commit()
def main():
    
    SCHEMA_VERSION = '5.11.1'

    global verbose
    global debug
    global autoaccept
    
    parser = argparse.ArgumentParser(description='Performs all of the identified QA tasks against an OVAL submission in the repository')
    output_options = parser.add_argument_group('verbosity options')
    output_options.add_argument('-v', '--verbose', default=False, action="store_true", help='Verbose progress messages')
    output_options.add_argument('-d', '--debug', default=False, action="store_true", help='Include debug information on errors')
#     output_options.add_argument('-a', '--autoaccept', default=False, action="store_true", help='Automatically continue without prompting when it is safe to do so')

    args = vars(parser.parse_args())

    if args['verbose']:
        verbose = True
        
    if args['debug']:
        debug = True
        
#     if args['autoaccept']:
#         autoaccept = True
    
    # Grab some things we're going to need later
    # First, build the schema path cache
    element_index = lib_search.ElementsIndex(message)
    schema_path_cache = {}
    for schema_version in lib_repo.get_schema_versions():
        schema_path_cache[schema_version] = lib_repo.get_oval_def_schema(schema_version)

    
    # 1. Locate all uncommitted changes to the local repository
    if verbose:
        print("\n + 1:  looking for uncommitted changes")
    change_list = lib_git.get_uncommitted_oval()
    if change_list is None or len(change_list) < 1:
        print("\n-------- This update does not include any changes of significance --------\n")
        return


    # 1.1 Determine which of these changes are due to removed files    
    if verbose:
        print("   +++ Number of changed items to QA: {0}".format(len(change_list)))
    remove_list = find_removed_items(change_list)
    
    # 1.2 Issue warning (prompt to continue) if any of the changes are a deleted item
    if verbose:
        print("  + 1.2: Determining if any changes are deleted items...")
    if remove_list is not None and len(remove_list) > 0:
        print("\n  -------- The following files were removed as a part of this update --------\n")
        show_files(remove_list)
        # TODO:  Offer the option to inspect the OVALIDs in the removed files and 
        #    build a list of what items, if any, refer to them
        response = input("\n :: Accept these changes (N[o] / y[es] / s[how affected]): ")
        if response == 's' or response == 'S':
            show_affected(remove_list)
            response = input("\n :::: Accept these changes (N[o] / y[es]): ")
            if response != 'y' and response != 'Y':
                return
        elif response != 'y' and response != 'Y':
            return
        # 1.3 Don't include removed files as part of the update
        change_list = [file for file in change_list if file not in remove_list]
        
        
    elif verbose:
        print("    +++ No removed items found")
        
    

    # 2. Remove all changes that are semantically the same as existing elements (except for states)
    if verbose:
        print("\n + 2: Removing items that don't contain meaningful changes...")
    change_list = prune_unchanged_elements(change_list)
    
    # 2.1 If that means we have no changes left, there is nothing else to do
    if len(change_list) < 1:
        print("\n  ----- This update does not include any changes of significance")
        return
    print("\n  ---- Number of changed elements to process: {0}\n".format(len(change_list)))
    
    
    # 3. For each element in the list that is a definition, check:
    if verbose:
        print(" + 3: Checking correctness of definition metadata")
        

    def_list = [ path for path in change_list if lib_repo.get_element_type_from_path(path) == 'definition']
    if def_list is not None and len(def_list) > 0:
        valid_metadata = 1
        if verbose:
            print("   +++ Number of definitions in this update: {0}".format(len(def_list)))
        for def_path in def_list:
            def_element = lib_xml.load_standalone_element(def_path)

            ode = lib_oval.OvalElement(def_element)
            od  = lib_oval.OvalDefinition(ode.getElement())

            def_id = od.getId()

        # 3.1 If this is an update, does it change any existing metadata?
        # 3.2 Check existence and accuracy of definition metadata (<status> and date)
        #  - INITIAL SUBMISSION or DRAFT on new submission
        #  - INTERIM if updating a previous definition
        #  - ?

            # no <dates> - invalid
            # @version == 0:
            #   no <submitted> - invalid
            #   <status_change>s > 0 - invalid
            #   <status> != "INITIAL SUBMISSION" - invalid
            # @ version > 0:
            #   last <status_change> != <status> - invalid
            def_status_change = od.get_last_status_change()
            if def_status_change["Version"] == "0":
                if "Submitted" not in def_status_change or def_status_change["Submitted"] is None:
                    print("   ++++ Definition ID %s is NOT valid:" % def_id)
                    print("    - New definitions must contain a submitted element")
                    valid_metadata = 0

                if def_status_change["StatusChange"]:
                    print("   ++++ Definition ID %s is NOT valid:" % def_id)
                    print("    - New definitions should not contain a status change element")
                    valid_metadata = 0

                if def_status_change["Status"] != "INITIAL SUBMISSION":
                    print("   ++++ Definition ID %s is NOT valid:" % def_id)
                    print("    - New definitions must have a status of INITIAL SUBMISSION")
                    valid_metadata = 0
            else:
                defstatus = def_status_change["Status"]
                lscstatus = def_status_change["StatusChange"]["Status"]
                if (defstatus != lscstatus):
                    print("   ++++ Definition ID %s is NOT valid:" % def_id)
                    print("    - Last status change (%s) does not match definition status (%s)" % (lscstatus, defstatus))
                    valid_metadata = 0

        if valid_metadata == 0:
            print("\n   ++++ Definition Metadata is Invalid.  Exiting...")
            return

    elif verbose:
        print("   +++ No definitions to check")
    
    
    # 4. Schema validate the changes
    # First, generate an OVAL document
    if verbose:
        print("\n + 4: Schema validating changes...")
        
    schema_path = lib_repo.get_oval_def_schema(SCHEMA_VERSION)
    for element_file in change_list:
        try:
            lib_xml.schema_validate(element_file, schema_path, True)
        except Exception as e:
            print('    Schema validation failed:\n\t{0}'.format(e.message))
            print("\n ### Offending file {0}".format(element_file))
            return

    if verbose:
        print(" ++++ Schema validations passed")
        print("\n + 5: Updating elements...")    

    # 5. On passing all of the above, make these changes for all elements:


    oval_id_map = {}
    affected_elements = set()
    update_elements = {}
    for path in change_list:
        oval_element = lib_xml.load_standalone_element(path)
        update_elements[path] = oval_element
        #  5.1 If it's a definition, determine and set the minimum schema version
        ovalid = oval_element.get("id")
        if verbose:
            print("\n  ---- Processing submitted element {0}".format(ovalid))
            
        if lib_repo.get_element_type_from_path(path) == 'definition':
            if verbose:
                print("    --- Is a definition:  determining minimum schema version")
#             min_schema = determine_definition_minimum_schema_version(path, element_index, schema_path_cache)
            min_schema = determine_definition_minimum_schema_version(oval_element, element_index, schema_path_cache)
            if min_schema and min_schema is not None:
                if verbose:
                    print("    ---- Determined minimum schema version to be {0}".format(min_schema))
                set_minimum_schema_version(oval_element, min_schema)
        
        #  5.2 For each element that is not using an OVALID in the CIS namespace:
        is_update = True
        if not is_repository_id(ovalid):
            is_update = False
            element_type = lib_repo.get_element_type_from_path(path)
            new_id = generate_next_ovalid(element_type, element_index)
            if verbose:
                print("    ---- Change submission ID from '{0}' to '{1}'".format(ovalid, new_id))
            oval_element.set("id", new_id)
            #      5.2.1 Set to a unique OVALID in the CIS namespace
            #      5.2.2 Update all references from the old OVALID
            oval_id_map[ovalid] = new_id
        
        #  5.3 Set/update version numbers as necessary.  The previous step can be used to determine new vice update
        if is_update:
        #    5.3.1 If this is an update, find the current version and increment by one
            if verbose:
                print("     ---- Is an update:  incrementing version")
            increment_version(oval_element)
            # Find all upstream elements and add them, as unique, to the list of items to change
            if lib_repo.get_element_type_from_path(path) != 'definition':
                if verbose:
                    print("     ---- Not a definition.  Finding affected upstream elements...")
                affected = find_affected(ovalid, element_index)
                if affected is not None and len(affected) > 0:
                    if verbose:
                        print("     ---- Number of elements affected: {0}".format(len(affected)))
                    affected_elements = set().union(affected_elements, affected)
                else:
                    if verbose:
                        print("     >>>>> Warning: found no affected elements for this update.  Possible orphan.")
        else:
        #        Otherwise, set it to 1
            oval_element.set("version", "1")
        #  5.4 Canonicalize all altered elements (if possible)
        
    # Now that we know all the elements affected by an update we can increment their IDs once
    if len(affected_elements) > 0:
        if verbose:
            print("\n ------- This update affects {0} upstream elements:  incrementing the version number for each...".format(len(affected_elements)))
        for file in affected_elements:
            oval_element = lib_xml.load_standalone_element(file)
            if oval_element is not None:
                increment_version(oval_element)
                #oval_element = normalize_ids(oval_element, oval_id_map)
                update_elements[file] = oval_element
    
    
    #  6 Write the element, and remove the old if the path changed
    print("\n=============== Complete ===================")
    print("All automated checks have completed successfully, but the following")
    print(" manual checks need to be made prior to accepting this submission:")
    print("   * Metadata for definitions is complete and accurate")
    print("   * Existing metadata has not been changed")
    print("   * Contains a meaningful change")
    print("   * Does not contain any harmful actions or unacceptable language")

    for x in oval_id_map:
        print(" -- Convert %s to %s" % (x, oval_id_map[x]))

    response = input("\n :::: Save all changes now? (N[o] / y[es]): ")
    if response != 'y' and response != 'Y':
        return

    for path in update_elements:
        oval_element = normalize_ids(update_elements[path], oval_id_map)
        if not oval_element or oval_element is None:
            continue
        new_path = lib_repo.get_element_repository_path(oval_element)
        if verbose:
            print("## Writing {0}".format(new_path))
        save_element(oval_element, new_path)
        
        if new_path != path:
            if verbose:
                print("### Deleting {0}".format(path))
            try:
                os.remove(path)
            except Exception:
                print("#### Exception/Skipping Deleting {0}".format(path))
            
    
    # 7. Prompt for a message to use for the commit
    # 7.1 Commit and push the changes
    
    return
def main():
    
    SCHEMA_VERSION = '5.11.1'

    global verbose
    global debug
    global autoaccept
    
    parser = argparse.ArgumentParser(description='Performs all of the identified QA tasks against an OVAL submission in the repository')
    output_options = parser.add_argument_group('verbosity options')
    output_options.add_argument('-v', '--verbose', default=False, action="store_true", help='Verbose progress messages')
    output_options.add_argument('-d', '--debug', default=False, action="store_true", help='Include debug information on errors')
#     output_options.add_argument('-a', '--autoaccept', default=False, action="store_true", help='Automatically continue without prompting when it is safe to do so')

    args = vars(parser.parse_args())

    if args['verbose']:
        verbose = True
        
    if args['debug']:
        debug = True
        
#     if args['autoaccept']:
#         autoaccept = True
    
    # Grab some things we're going to need later
    # First, build the schema path cache
    element_index = lib_search.ElementsIndex(message)
    schema_path_cache = {}
    for schema_version in lib_repo.get_schema_versions():
        schema_path_cache[schema_version] = lib_repo.get_oval_def_schema(schema_version)

    
    # 1. Locate all uncommitted changes to the local repository
    if verbose:
        print("\n + 1:  looking for uncommitted changes")
    change_list = lib_git.get_uncommitted_oval()
    if change_list is None or len(change_list) < 1:
        print("\n-------- This update does not include any changes of significance --------\n")
        return


    # 1.1 Determine which of these changes are due to removed files    
    if verbose:
        print("   +++ Number of changed items to QA: {0}".format(len(change_list)))
    remove_list = find_removed_items(change_list)
    
    # 1.2 Issue warning (prompt to continue) if any of the changes are a deleted item
    if verbose:
        print("  + 1.2: Determining if any changes are deleted items...")
    if remove_list is not None and len(remove_list) > 0:
        print("\n  -------- The following files were removed as a part of this update --------\n")
        show_files(remove_list)
        # TODO:  Offer the option to inspect the OVALIDs in the removed files and 
        #    build a list of what items, if any, refer to them
        response = input("\n :: Accept these changes (N[o] / y[es] / s[how affected]): ")
        if response == 's' or response == 'S':
            show_affected(remove_list)
            response = input("\n :::: Accept these changes (N[o] / y[es]): ")
            if response != 'y' and response != 'Y':
                return
        elif response != 'y' and response != 'Y':
            return
        # 1.3 Don't include removed files as part of the update
        change_list = [file for file in change_list if file not in remove_list]
        
        
    elif verbose:
        print("    +++ No removed items found")
        
    

    # 2. Remove all changes that are semantically the same as existing elements (except for states)
    if verbose:
        print("\n + 2: Removing items that don't contain meaningful changes...")
    change_list = prune_unchanged_elements(change_list)
    
    # 2.1 If that means we have no changes left, there is nothing else to do
    if len(change_list) < 1:
        print("\n  ----- This update does not include any changes of significance")
        return
    print("\n  ---- Number of changed elements to process: {0}\n".format(len(change_list)))
    
    
    # 3. For each element in the list that is a definition, check:
    if verbose:
        print(" + 3: Checking correctness of definition metadata")
        

    def_list = [ path for path in change_list if lib_repo.get_element_type_from_path(path) == 'definition']
    if def_list is not None and len(def_list) > 0:
        valid_metadata = 1
        if verbose:
            print("   +++ Number of definitions in this update: {0}".format(len(def_list)))
        for def_path in def_list:
            def_element = lib_xml.load_standalone_element(def_path)

            ode = lib_oval.OvalElement(def_element)
            od  = lib_oval.OvalDefinition(ode.getElement())

            def_id = od.getId()

        # 3.1 If this is an update, does it change any existing metadata?
        # 3.2 Check existence and accuracy of definition metadata (<status> and date)
        #  - INITIAL SUBMISSION or DRAFT on new submission
        #  - INTERIM if updating a previous definition
        #  - ?

            # no <dates> - invalid
            # @version == 0:
            #   no <submitted> - invalid
            #   <status_change>s > 0 - invalid
            #   <status> != "INITIAL SUBMISSION" - invalid
            # @ version > 0:
            #   last <status_change> != <status> - invalid
            def_status_change = od.get_last_status_change()
            if def_status_change["Version"] == "0":
                if "Submitted" not in def_status_change or def_status_change["Submitted"] is None:
                    print("   ++++ Definition ID %s is NOT valid:" % def_id)
                    print("    - New definitions must contain a submitted element")
                    valid_metadata = 0

                if def_status_change["StatusChange"]:
                    print("   ++++ Definition ID %s is NOT valid:" % def_id)
                    print("    - New definitions should not contain a status change element")
                    valid_metadata = 0

                if def_status_change["Status"] != "INITIAL SUBMISSION":
                    print("   ++++ Definition ID %s is NOT valid:" % def_id)
                    print("    - New definitions must have a status of INITIAL SUBMISSION")
                    valid_metadata = 0
            else:
                defstatus = def_status_change["Status"]
                lscstatus = def_status_change["StatusChange"]["Status"]
                if (defstatus != lscstatus):
                    print("   ++++ Definition ID %s is NOT valid:" % def_id)
                    print("    - Last status change (%s) does not match definition status (%s)" % (lscstatus, defstatus))
                    valid_metadata = 0

        if valid_metadata == 0:
            print("\n   ++++ Definition Metadata is Invalid.  Exiting...")
            return

    elif verbose:
        print("   +++ No definitions to check")
    
    
    # 4. Schema validate the changes
    # First, generate an OVAL document
    if verbose:
        print("\n + 4: Schema validating changes...")
        
    schema_path = lib_repo.get_oval_def_schema(SCHEMA_VERSION)
    for element_file in change_list:
        try:
            lib_xml.schema_validate(element_file, schema_path, True)
        except Exception as e:
            print('    Schema validation failed:\n\t{0}'.format(e.message))
            print("\n ### Offending file {0}".format(element_file))
            return

    if verbose:
        print(" ++++ Schema validations passed")
        print("\n + 5: Updating elements...")    

    # 5. On passing all of the above, make these changes for all elements:


    oval_id_map = {}
    affected_elements = set()
    update_elements = {}
    for path in change_list:
        oval_element = lib_xml.load_standalone_element(path)
        update_elements[path] = oval_element
        #  5.1 If it's a definition, determine and set the minimum schema version
        ovalid = oval_element.get("id")
        if verbose:
            print("\n  ---- Processing submitted element {0}".format(ovalid))
            
        if lib_repo.get_element_type_from_path(path) == 'definition':
            if verbose:
                print("    --- Is a definition:  determining minimum schema version")
#             min_schema = determine_definition_minimum_schema_version(path, element_index, schema_path_cache)
            min_schema = determine_definition_minimum_schema_version(oval_element, element_index, schema_path_cache)
            if min_schema and min_schema is not None:
                if verbose:
                    print("    ---- Determined minimum schema version to be {0}".format(min_schema))
                set_minimum_schema_version(oval_element, min_schema)
        
        #  5.2 For each element that is not using an OVALID in the CIS namespace:
        is_update = True
        if not is_repository_id(ovalid):
            is_update = False
            element_type = lib_repo.get_element_type_from_path(path)
            new_id = generate_next_ovalid(element_type, element_index)
            if verbose:
                print("    ---- Change submission ID from '{0}' to '{1}'".format(ovalid, new_id))
            oval_element.set("id", new_id)
            #      5.2.1 Set to a unique OVALID in the CIS namespace
            #      5.2.2 Update all references from the old OVALID
            oval_id_map[ovalid] = new_id
        
        #  5.3 Set/update version numbers as necessary.  The previous step can be used to determine new vice update
        if is_update:
        #    5.3.1 If this is an update, find the current version and increment by one
            if verbose:
                print("     ---- Is an update:  incrementing version")
            increment_version(oval_element)
            # Find all upstream elements and add them, as unique, to the list of items to change
            if lib_repo.get_element_type_from_path(path) != 'definition':
                if verbose:
                    print("     ---- Not a definition.  Finding affected upstream elements...")
                affected = find_affected(ovalid, element_index)
                if affected is not None and len(affected) > 0:
                    if verbose:
                        print("     ---- Number of elements affected: {0}".format(len(affected)))
                    affected_elements = set().union(affected_elements, affected)
                else:
                    if verbose:
                        print("     >>>>> Warning: found no affected elements for this update.  Possible orphan.")
        else:
        #        Otherwise, set it to 1
            oval_element.set("version", "1")
        #  5.4 Canonicalize all altered elements (if possible)
        
    # Now that we know all the elements affected by an update we can increment their IDs once
    if len(affected_elements) > 0:
        if verbose:
            print("\n ------- This update affects {0} upstream elements:  incrementing the version number for each...".format(len(affected_elements)))
        for file in affected_elements:
            oval_element = lib_xml.load_standalone_element(file)
            if oval_element is not None:
                increment_version(oval_element)
                #oval_element = normalize_ids(oval_element, oval_id_map)
                update_elements[file] = oval_element
    
    
    #  6 Write the element, and remove the old if the path changed
    print("\n=============== Complete ===================")
    print("All automated checks have completed successfully, but the following")
    print(" manual checks need to be made prior to accepting this submission:")
    print("   * Metadata for definitions is complete and accurate")
    print("   * Existing metadata has not been changed")
    print("   * Contains a meaningful change")
    print("   * Does not contain any harmful actions or unacceptable language")

    for x in oval_id_map:
        print(" -- Convert %s to %s" % (x, oval_id_map[x]))

    response = input("\n :::: Save all changes now? (N[o] / y[es]): ")
    if response != 'y' and response != 'Y':
        return

    for path in update_elements:
        oval_element = normalize_ids(update_elements[path], oval_id_map)
        if not oval_element or oval_element is None:
            continue
        new_path = lib_repo.get_element_repository_path(oval_element)
        if verbose:
            print("## Writing {0}".format(new_path))
        save_element(oval_element, new_path)
        
        if new_path != path:
            if verbose:
                print("### Deleting {0}".format(path))
            os.remove(path)
            
    
    # 7. Prompt for a message to use for the commit
    # 7.1 Commit and push the changes
    
    return
    def update(self, force_rebuild=False):
        """ Adds/updates all items in repo to index. Note: querying will call this automatically."""

        # if we've already updated the index during this script run, we're done!
        if self.index_updated:
            return False

        # we only need to do this once per script lifetime
        self.index_updated = True

        # if the index is not based on the current commit, rebuild from scratch
        if not self.index_based_on_current_commit():
            force_rebuild = True

        if force_rebuild:
            # get a new clean/empty index
            index = self.get_index(force_rebuild)

            # disabled high-performance writer (https://pythonhosted.org/Whoosh/batch.html), causing thread/lock issues
            # index_writer = index.writer(procs=4, multisegment=True)
            index_writer = index.writer()

            # index all documents
            documents = self.document_iterator()
            activity_description = 'Rebuilding'

            # update indexed commit
            self.set_indexed_commit_hash()
        else:
            # use the current index
            index = self.get_index()
            index_writer = index.writer()

            # delete uncommitted files that are in index already
            for filepath in self.get_indexed_uncommitted_files():
                index_writer.delete_by_term('path', filepath)

            # get list of uncommitted files and persist it
            uncommitted_files = lib_git.get_uncommitted_oval()
            self.set_indexed_uncommitted_files(uncommitted_files)

            # nothing to update? done!
            if not uncommitted_files:
                index_writer.commit()
                return

            # index only uncommitted files
            documents = self.document_iterator(uncommitted_files)
            activity_description = 'Updating'

        # add all definition files to index
        counter = 0
        try:
            for document in documents:
                counter = counter + 1
                self.status_spinner(
                    counter, '{0} {1} index'.format(activity_description,
                                                    self.index_name),
                    self.item_label)
                if 'deleted' in document and document['deleted']:
                    try:
                        index_writer.delete_by_term(
                            'oval_id', self.whoosh_escape(document['oval_id']))
                    except:
                        self.message(
                            'debug',
                            'Something was marked as needing to be deleted but it wasnt in the index'
                        )
                    #self.message('debug', 'Deleting from index:\n\t{0} '.format(self.whoosh_escape(document['oval_id'])))
                    #index_writer.delete_by_term('oval_id', self.whoosh_escape(document['oval_id']))
                    #self.message('debug', 'Deleting from index:\n\t{0} '.format(self.whoosh_escape(document['oval_id'])))
                else:
                    index_writer.add_document(**document)
                    #self.message('debug', 'Upserting to index:\n\t{0} '.format(document['path']))
        except lib_xml.InvalidXmlError as e:
            # abort: cannot build index
            self.message(
                'ERROR CANNOT BUILD INDEX',
                'Invalid xml fragment\n\tFile: {0}\n\tMessage: {1}'.format(
                    e.path, e.message))
            self.message('ERROR', 'deleting index and aborting execution')
            index_writer.commit()
            self.index.close()
            shutil.rmtree(self.get_index_path())
            sys.exit(1)

        self.status_spinner(
            counter, '{0} {1} index'.format(activity_description,
                                            self.index_name), self.item_label,
            True)
        index_writer.commit()