Beispiel #1
0
    def _collect_soft_chain(self):
        """
        Build the soft-chain if it is not already defined and return
        the chain
        """
        if not self.nodes:
            files = ChainUtil.get_alter_files()
            self.nodes = ChainUtil.build_soft_chain(files)

        return self.nodes
Beispiel #2
0
    def _collect_soft_chain(self):
        """
        Build the soft-chain if it is not already defined and return
        the chain
        """
        if not self.nodes:
            files = ChainUtil.get_alter_files()
            self.nodes = ChainUtil.build_soft_chain(files)

        return self.nodes
Beispiel #3
0
    def run(self):
        """
        Print the current build chain in the console.

        Return the list of node IDs, which is used for testing.
        """
        # TODO: add a verbose mode, which shows alters as having been run or not

        (options, _) = self.parser.parse_args()

        list_reverse = options.listReverse

        list_tail = ChainUtil.build_chain()

        self.__set_is_applied_flag(list_tail)

        result = []

        if list_tail is None:
            sys.stdout.write("No alters found\n")
        else:
            normal_str = []
            temp_node = list_tail
            while temp_node is not None:
                result.append(temp_node.id)
                normal_str.append(temp_node.__str__(False))
                temp_node = temp_node.backref
            if not list_reverse:
                normal_str.reverse()
                result.reverse()
            sys.stdout.write("\n".join(normal_str) + "\n")

        return result
Beispiel #4
0
    def run(self):
        """
        Print the current build chain in the console.

        Return the list of node IDs, which is used for testing.
        """
        # TODO: add a verbose mode, which shows alters as having been run or not

        (options, _) = self.parser.parse_args()

        list_reverse = options.listReverse

        list_tail = ChainUtil.build_chain()

        self.__set_is_applied_flag(list_tail)

        result = []

        if list_tail is None:
            sys.stdout.write("No alters found\n")
        else:
            normal_str = []
            temp_node = list_tail
            while temp_node is not None:
                result.append(temp_node.id)
                normal_str.append(temp_node.__str__(False))
                temp_node = temp_node.backref
            if not list_reverse:
                normal_str.reverse()
                result.reverse()
            sys.stdout.write("\n".join(normal_str) + "\n")

        return result
Beispiel #5
0
    def run(self):
        """
        Run the "new" command as if it were its own executable. This means
        processing any options and performing the task of creating a new
        alter file.

        Note: This command assumes a starting point that has been created
        manually (and a working db directory exists)

        Return the node ID of the created files, which is used for testing.
        """
        (options, _) = self.parser.parse_args()

        timestamp = str(round(time() * 10)).replace('.', '')
        filename = timestamp + '-' + (options.filename or '_').replace('.sql', '')

        alter_list_tail = ChainUtil.build_chain()

        if alter_list_tail is not None:
            sys.stdout.write("Parent file:  %s\n" % alter_list_tail.filename)

        up_filename = filename + '-up.sql'
        try:
            alter_file = open(os.path.join(Constants.ALTER_DIR, up_filename), 'w')
            alter_file.write("-- direction: up\n")
            if alter_list_tail is not None:
                alter_file.write("-- backref: %s\n" % alter_list_tail.id)
            alter_file.write("-- ref: %s\n" % timestamp)
            alter_file.write("\n\n\n")
        except OSError, ex:
            raise WriteError("Could not write file '%s'\n\t=>%s" % (os.path.join(Constants.ALTER_DIR, up_filename), ex.message))
Beispiel #6
0
    def run(self):
        """
        Run the "new" command as if it were its own executable. This means
        processing any options and performing the task of creating a new
        alter file.

        Note: This command assumes a starting point that has been created
        manually (and a working db directory exists)

        Return the node ID of the created files, which is used for testing.
        """
        (options, args) = self.parser.parse_args()

        timestamp = str(round(time() * 10)).replace('.', '')
        filename = timestamp + '-' + (options.filename or '_').replace('.sql', '')

        alter_list_tail = ChainUtil.build_chain()

        if alter_list_tail is not None:
            sys.stdout.write("Parent file:  %s\n" % alter_list_tail.filename)

        up_filename = filename + '-up.sql'
        try:
            alter_file = open(os.path.join(Constants.ALTER_DIR, up_filename), 'w')
            alter_file.write("-- direction: up\n")
            if alter_list_tail is not None:
                alter_file.write("-- backref: %s\n" % alter_list_tail.id)
            alter_file.write("-- ref: %s\n" % timestamp)
            alter_file.write("\n\n\n")
        except OSError, ex:
            raise WriteError("Could not write file '%s'\n\t=>%s" % (os.path.join(Constants.ALTER_DIR, up_filename), ex.message))
Beispiel #7
0
    def test_creates_proper_alter_chain(self):
        sys.argv = make_argv(["-f", "1"])
        self.newCommand.run()
        sleep(0.15)
        sys.argv = make_argv(["-f", "2"])
        self.newCommand.run()

        chain_tail = ChainUtil.build_chain()
        self.assertTrue(chain_tail.backref is not None)
        self.assertTrue(chain_tail.backref.backref is None)
Beispiel #8
0
    def test_creates_proper_alter_chain(self):
        sys.argv = make_argv(['-f', '1'])
        self.newCommand.run()
        sleep(0.15)
        sys.argv = make_argv(['-f', '2'])
        self.newCommand.run()

        chain_tail = ChainUtil.build_chain()
        self.assertTrue(chain_tail.backref is not None)
        self.assertTrue(chain_tail.backref.backref is None)
Beispiel #9
0
    def run_alters(cls):
        cls.init()
        sys.argv = ['']
        cls.upCommand.run()
        tail = ChainUtil.build_chain()

        ids = []
        while tail is not None and tail.backref is not None:
            ids.append(tail.id)
            tail = tail.backref

        return ids
Beispiel #10
0
    def run_alters(cls):
        cls.init()
        sys.argv = ['']
        cls.upCommand.run()
        tail = ChainUtil.build_chain()

        ids = []
        while tail is not None and tail.backref is not None:
            ids.append(tail.id)
            tail = tail.backref

        return ids
Beispiel #11
0
    def help_test_missing_alter(self, search, error):
        AlterUtil.create_alters([1])
        AlterUtil.run_alters()

        alter_files = ChainUtil.get_alter_files()
        self.assertEqual(len(alter_files), 2)  # up and down
        os.remove([i for i in alter_files if search in i].pop())

        try:
            sys.argv = make_argv([])
            self.checkCommand.run()
        except error:
            pass
Beispiel #12
0
    def help_test_missing_alter(self, search, error):
        AlterUtil.create_alters([1])
        AlterUtil.run_alters()

        alter_files = ChainUtil.get_alter_files()
        self.assertEqual(len(alter_files), 2) # up and down
        os.remove([i for i in alter_files if search in i].pop())

        try:
            sys.argv = make_argv([])
            self.checkCommand.run()
        except error:
            pass
Beispiel #13
0
    def run(self, inline=False):
        """
        Check that the alter chain is valid

        """
        # TODO  Check that the alter chain is in line with the DB (but not necessarily up to date)
        # TODO  Make the verbose flag do something based on previous additions
        # TODO  Add flags to only perform certain checks (as described in the other todos)

        if not inline:
            (options, args) = self.parser.parse_args()

        self.files = ChainUtil.get_alter_files()

        # implicitly check validity of chain (integrity check)
        chain = ChainUtil.build_chain()

        # all other checks
        self.check_abandoned_alters(chain)
        self.check_missing_pair()

        if not inline:
            print("Everything looks good!\n")
Beispiel #14
0
    def run(self):
        (options, args) = self.parser.parse_args()

        # validate static_alter_dir set if flag used
        if options.write_to_file:
            options.include_rev_query = True
            if self.config.get('static_alter_dir') is None:
                raise Exception(
                    'static_alter_dir must be set in config.json to'
                    '\nuse -w/--write-to-file flag')
            self._setup_static_alter_dir()

        refs = args
        nodes = ChainUtil.build_chain()
        ref_nodes = []

        if len(refs) == 0:
            # entire chain
            refs = self._get_node_ids(nodes)
            refs.reverse()

        # validate valid refs
        for ref in refs:
            node = self._find_ref(ref, nodes)
            if node is False:
                raise MissingRefError("Ref '%s' could not be found" % ref,
                                      self.parser.format_help())
            else:
                ref_nodes.append(node)

        # gen SQL for each ref
        if options.write_to_file:
            # gen SQL for each ref, and save to individual files.
            for node in ref_nodes:
                sql = self.gen_sql_for_reflist([node], options)
                if options.down_alter:
                    filename = node.down_filename()
                else:
                    filename = node.filename
                fobj = open(
                    os.path.join(self.config['static_alter_dir'], filename),
                    'w')
                fobj.write(sql)
                fobj.close()
                print os.path.join(self.config['static_alter_dir'], filename)
        else:
            # gen SQL for refs in one call
            sql = self.gen_sql_for_reflist(ref_nodes, options)
            sys.stdout.write(sql)
Beispiel #15
0
    def run(self, inline=False):
        """
        Check that the alter chain is valid

        """
        # TODO  Check that the alter chain is in line with the DB (but not necessarily up to date)
        # TODO  Make the verbose flag do something based on previous additions
        # TODO  Add flags to only perform certain checks (as described in the other todos)

        if not inline:
            # (options, args) = self.parser.parse_args()
            self.parser.parse_args()

        self.files = ChainUtil.get_alter_files()

        # implicitly check validity of chain (integrity check)
        chain = ChainUtil.build_chain()

        # all other checks
        self.check_abandoned_alters(chain)
        self.check_missing_pair()

        if not inline:
            print("Everything looks good!\n")
Beispiel #16
0
    def run(self):
        (options, args) = self.parser.parse_args()

        # validate static_alter_dir set if flag used
        if options.write_to_file:
            options.include_rev_query = True
            if self.config.get('static_alter_dir') is None:
                raise Exception('static_alter_dir must be set in config.json to'
                                '\nuse -w/--write-to-file flag')
            self._setup_static_alter_dir()

        refs = args
        nodes = ChainUtil.build_chain()
        ref_nodes = []

        if len(refs) == 0:
            # entire chain
            refs = self._get_node_ids(nodes)
            refs.reverse()

        # validate valid refs
        for ref in refs:
            node = self._find_ref(ref, nodes)
            if node is False:
                raise MissingRefError("Ref '%s' could not be found" % ref, self.parser.format_help())
            else:
                ref_nodes.append(node)

        # gen SQL for each ref
        if options.write_to_file:
            # gen SQL for each ref, and save to individual files.
            for node in ref_nodes:
                sql = self.gen_sql_for_reflist([node], options)
                if options.down_alter:
                    filename = node.down_filename()
                else:
                    filename = node.filename
                fobj = open(os.path.join(self.config['static_alter_dir'], filename), 'w')
                fobj.write(sql)
                fobj.close()
                print os.path.join(self.config['static_alter_dir'], filename)
        else:
            # gen SQL for refs in one call
            sql = self.gen_sql_for_reflist(ref_nodes, options)
            sys.stdout.write(sql)
Beispiel #17
0
    def test_no_backref_on_single_alter(self):
        sys.argv = make_argv(["-f", "1"])
        self.newCommand.run()

        chain_tail = ChainUtil.build_chain()
        self.assertTrue(chain_tail.backref is None)
Beispiel #18
0
    def test_no_backref_on_single_alter(self):
        sys.argv = make_argv(['-f', '1'])
        self.newCommand.run()

        chain_tail = ChainUtil.build_chain()
        self.assertTrue(chain_tail.backref is None)
Beispiel #19
0
    def run(self):
        """
        Analogous to what the up_command definition does, but in reverse.
        """
        (options, args) = self.parser.parse_args()

        CheckCommand(self.context).run(inline=True)

        # check validity of options (can't really do this in OptionParser AFAIK)
        if len(args) == 0 and options.N is None:
            raise OptionsError("must specify either argument or number of down-alters to run", self.parser.format_help())

        # get current history
        history = self.db.get_commit_history()
        history = sorted(history, key=lambda h: h[0], reverse=True)

        # get current alter chain
        tail = ChainUtil.build_chain()
        alter_list = [tail]
        if None in alter_list:
            alter_list.remove(None)
        while tail is not None and tail.backref is not None:
            tail = tail.backref
            alter_list.append(tail)

        # parse the args given
        run_type, target_rev = self.parse_args(args)

        # collect the down-alters that we need to run depending on the command line
        # options and arguments that were given
        down_alters_to_run = []
        max_history_len = int(options.N or len(history))
        i = 0
        for (id, alter_id, alter_time) in history:
            if i == max_history_len:
                break
            if run_type == 'base':
                if i == (max_history_len - 1):
                    break
            elif run_type == 'all':
                pass
            else:
                if target_rev == alter_id:
                    i = (max_history_len - 1)

            i += 1
            alters = [a for a in alter_list if a.id == alter_id]
            if len(alters) > 0:
                alter = alters[0]
                down_alters_to_run.append(alter)
            else:
                # error depending on the force and verbose flags (missing alter to run)
                if options.force:
                    sys.stderr.write("Warning: missing alter: %s\n" % alter_id)
                    self.db.remove_commit(ref=alter_id)
                else:
                    raise MissingDownAlterError("missing alter: %s\n" % alter_id)

        # ensure that if a target_revision was specified that one was found in
        # in the list of alters to run (down)
        if (run_type == 'revision' and
              target_rev not in [a.id for a in down_alters_to_run]):
            raise MissingRefError('revision (%s) not found in alters that would be run' % target_rev)

        # run all the down-alters that we have collected
        for alter_to_run in down_alters_to_run:
            self.db.run_down(alter=alter_to_run,
                        force=options.force,
                        verbose=options.verbose)

        sys.stdout.write("Downgraded\n")
Beispiel #20
0
    def run(self):
        """
        Analogous to what the up_command definition does, but in reverse.
        """
        (options, args) = self.parser.parse_args()

        CheckCommand(self.context).run(inline=True)

        # check validity of options (can't really do this in OptionParser AFAIK)
        if len(args) == 0 and options.N is None:
            raise OptionsError("must specify either argument or number of down-alters to run", self.parser.format_help())

        # get current history
        history = self.db.get_commit_history()
        history = sorted(history, key=lambda h: h[0], reverse=True)

        # get current alter chain
        tail = ChainUtil.build_chain()
        alter_list = [tail]
        if None in alter_list:
            alter_list.remove(None)
        while tail is not None and tail.backref is not None:
            tail = tail.backref
            alter_list.append(tail)

        # parse the args given
        run_type, target_rev = self.parse_args(args)

        # collect the down-alters that we need to run depending on the command line
        # options and arguments that were given
        down_alters_to_run = []
        max_history_len = int(options.N or len(history))
        i = 0
        for (_, alter_id, _) in history:
            if i == max_history_len:
                break
            if run_type == 'base':
                if i == (max_history_len - 1):
                    break
            elif run_type == 'all':
                pass
            else:
                if target_rev == alter_id:
                    i = (max_history_len - 1)

            i += 1
            alters = [a for a in alter_list if a.id == alter_id]
            if len(alters) > 0:
                alter = alters[0]
                down_alters_to_run.append(alter)
            else:
                # error depending on the force and verbose flags (missing alter to run)
                if options.force:
                    sys.stderr.write("Warning: missing alter: %s\n" % alter_id)
                    self.db.remove_commit(ref=alter_id)
                else:
                    raise MissingDownAlterError("missing alter: %s\n" % alter_id)

        # ensure that if a target_revision was specified that one was found in
        # in the list of alters to run (down)
        if (run_type == 'revision' and
              target_rev not in [a.id for a in down_alters_to_run]):
            raise MissingRefError('revision (%s) not found in alters that would be run' % target_rev)

        # run all the down-alters that we have collected
        for alter_to_run in down_alters_to_run:
            self.db.run_down(alter=alter_to_run,
                        force=options.force,
                        verbose=options.verbose)

        sys.stdout.write("Downgraded\n")
Beispiel #21
0
    def run(self):
        """
        Update the DB by checking the current state (stored in the DB itself)
        and and bringing the DB up to date from the current list of alters.

        Returns nothing, but updated DB (via alters) and updated revision number
        in DB table

        Now that we have the history of what has _been_ run and the alter chain
        of all alters, we can determine what _needs_ to be run. First we will
        go up the history until it diverges with the chain. Then we'll run all
        of the "undos" for any history items that still exist and then run the
        list from where we left off.
        """
        (options, args) = self.parser.parse_args()

        CheckCommand(self.context).run(inline=True)

        # get history
        history = self.db.get_commit_history()
        history = sorted(history, key=lambda h: h[0])
        history_alters = [h[1] for h in history]

        # get current alter chain
        tail = ChainUtil.build_chain()
        alter_list = [tail]
        if None in alter_list:
            alter_list.remove(None)
        while tail is not None and tail.backref is not None:
            tail = tail.backref
            alter_list.append(tail)

        # find (and remove) synced alters from alter_list (so they are not run again)
        common_history = 0
        for (_id, alter_id, datetime) in history:
            if len(alter_list) == 0:
                break
            # don't count alters for other env's in common-history
            alter = alter_list.pop()
            while not self.should_run(alter):
                alter = alter_list.pop()

            if alter.id == alter_id:
                common_history += 1
            else:
                alter_list.append(alter)
                break

        # undo alters that are not in sync with alter chain if options.undo is true.
        if options.undo:
            uncommon_history = history[common_history:]
            if len(uncommon_history) > 0:
                # clean up alters from here
                uncommon_history.reverse()
                for (_id, alter_id, datetime) in uncommon_history:
                    alters = [a for a in alter_list if a.id == alter_id]
                    if len(alters) > 1:
                        msg = "Multiple alters found for a single id (%s)" % a.id
                        if not options.force:
                            raise MultipleDownAltersError(msg)
                        else:
                            sys.stderr.write(msg + "\n")
                    elif len(alters) == 0:
                        raise MissingDownAlterError("Missing down alter %s" % alter_id)
                    alter = alters[0]
                    self.db.run_down(alter)
                    if alter.id in history_alters:
                        history_alters.remove(alter.id)

        # Ensure that if a target ref was specified that one was found in
        # in the list of alters to run (up)
        if len(alter_list) and len(args) and args[0] not in [a.id for a in alter_list]:
            raise MissingRefError('revision (%s) not found in alters that would be run' % args[0])

        # Do alters that are in the alter chain and have not
        # been run yet
        max_ = int(options.N or len(alter_list))
        i = 0
        while not len(alter_list) == 0:
            if i == max_:
                break

            alter = alter_list.pop()

            if len(args) > 0:
                target_rev = args[0]
                if target_rev == alter.id:
                    i = (max_ - 1)

            i += 1
            if alter.id not in history_alters and self.should_run(alter):
                self.db.run_up(alter=alter,
                          force=options.force,
                          verbose=options.verbose)
            elif not self.should_run(alter):
                # possible to get a skipped alter in the event that it wasn't removed
                # in the common-history code (aka, running new alters)
                pass
            else:
                sys.stderr.write("Warning: alter " + str(alter.id) + " has already been " \
                        "run. Skipping\n")

        sys.stdout.write("Updated\n")
Beispiel #22
0
    def run(self):
        """
        Update the DB by checking the current state (stored in the DB itself)
        and and bringing the DB up to date from the current list of alters.

        Returns nothing, but updated DB (via alters) and updated revision number
        in DB table

        Now that we have the history of what has _been_ run and the alter chain
        of all alters, we can determine what _needs_ to be run. First we will
        go up the history until it diverges with the chain. Then we'll run all
        of the "undos" for any history items that still exist and then run the
        list from where we left off.
        """
        (options, args) = self.parser.parse_args()

        CheckCommand(self.context).run(inline=True)

        # get history
        history = self.db.get_commit_history()
        history = sorted(history, key=lambda h: h[0])
        history_alters = [h[1] for h in history]

        # get current alter chain
        tail = ChainUtil.build_chain()
        alter_list = [tail]
        if None in alter_list:
            alter_list.remove(None)
        while tail is not None and tail.backref is not None:
            tail = tail.backref
            alter_list.append(tail)

        # find (and remove) synced alters from alter_list (so they are not run again)
        common_history = 0
        for (_, alter_id, _) in history:
            if len(alter_list) == 0:
                break
            # don't count alters for other env's in common-history
            alter = alter_list.pop()
            while not self.should_run(alter):
                alter = alter_list.pop()

            if alter.id == alter_id:
                common_history += 1
            else:
                alter_list.append(alter)
                break

        # undo alters that are not in sync with alter chain if options.undo is true.
        if options.undo:
            uncommon_history = history[common_history:]
            if len(uncommon_history) > 0:
                # clean up alters from here
                uncommon_history.reverse()
                for (_, alter_id, _) in uncommon_history:
                    alters = [a for a in alter_list if a.id == alter_id]
                    if len(alters) > 1:
                        msg = "Multiple alters found for a single id (%s)" % alter_id
                        if not options.force:
                            raise MultipleDownAltersError(msg)
                        else:
                            sys.stderr.write(msg + "\n")
                    elif len(alters) == 0:
                        raise MissingDownAlterError("Missing down alter %s" % alter_id)
                    alter = alters[0]
                    self.db.run_down(alter)
                    if alter.id in history_alters:
                        history_alters.remove(alter.id)

        # Ensure that if a target ref was specified that one was found in
        # in the list of alters to run (up)
        if len(alter_list) and len(args) and args[0] not in [a.id for a in alter_list]:
            raise MissingRefError('revision (%s) not found in alters that would be run' % args[0])

        # Do alters that are in the alter chain and have not
        # been run yet
        max_ = int(options.N or len(alter_list))
        i = 0
        while not len(alter_list) == 0:
            if i == max_:
                break

            alter = alter_list.pop()

            if len(args) > 0:
                target_rev = args[0]
                if target_rev == alter.id:
                    i = (max_ - 1)

            i += 1
            if alter.id not in history_alters and self.should_run(alter):
                self.db.run_up(alter=alter,
                          force=options.force,
                          verbose=options.verbose)
            elif not self.should_run(alter):
                # possible to get a skipped alter in the event that it wasn't removed
                # in the common-history code (aka, running new alters)
                pass
            else:
                sys.stderr.write("Warning: alter " + str(alter.id) + " has already been " \
                        "run. Skipping\n")

        sys.stdout.write("Updated\n")