add a simple stack handling to be able to delay error handling
authorDavid Kalnischkies <kalnischkies@gmail.com>
Fri, 25 Jun 2010 17:16:12 +0000 (19:16 +0200)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Fri, 25 Jun 2010 17:16:12 +0000 (19:16 +0200)
apt-pkg/contrib/error.cc
apt-pkg/contrib/error.h
debian/changelog
test/libapt/globalerror_test.cc [new file with mode: 0644]
test/libapt/makefile

index 837d9e6..8cee21c 100644 (file)
@@ -181,7 +181,13 @@ bool GlobalError::PopMessage(std::string &Text) {
 }
                                                                        /*}}}*/
 // GlobalError::DumpErrors - Dump all of the errors/warns to cerr      /*{{{*/
-void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold) {
+void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold,
+                            bool const &mergeStack) {
+       if (mergeStack == true)
+               for (std::list<MsgStack>::const_reverse_iterator s = Stacks.rbegin();
+                    s != Stacks.rend(); ++s)
+                       Messages.insert(Messages.begin(), s->Messages.begin(), s->Messages.end());
+
        for (std::list<Item>::const_iterator m = Messages.begin();
             m != Messages.end(); m++)
                if (m->Type >= trashhold)
@@ -211,3 +217,27 @@ bool GlobalError::empty(MsgType const &trashhold) const {
        return true;
 }
                                                                        /*}}}*/
+// GlobalError::PushToStack                                            /*{{{*/
+void GlobalError::PushToStack() {
+       MsgStack pack(Messages, PendingFlag);
+       Stacks.push_back(pack);
+       Discard();
+}
+                                                                       /*}}}*/
+// GlobalError::RevertToStack                                          /*{{{*/
+void GlobalError::RevertToStack() {
+       Discard();
+       MsgStack pack = Stacks.back();
+       Messages = pack.Messages;
+       PendingFlag = pack.PendingFlag;
+       Stacks.pop_back();
+}
+                                                                       /*}}}*/
+// GlobalError::MergeWithStack                                         /*{{{*/
+void GlobalError::MergeWithStack() {
+       MsgStack pack = Stacks.back();
+       Messages.insert(Messages.begin(), pack.Messages.begin(), pack.Messages.end());
+       PendingFlag = PendingFlag || pack.PendingFlag;
+       Stacks.pop_back();
+}
+                                                                       /*}}}*/
index fc7b38f..7373516 100644 (file)
@@ -206,7 +206,8 @@ public:                                                                     /*{{{*/
         *  \param[out] out output stream to write the messages in
         *  \param WithoutNotice output notices or not
         */
-       void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING);
+       void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING,
+                       bool const &mergeStack = true);
 
        /** \brief dumps the list of messages to std::cerr
         *
@@ -219,6 +220,28 @@ public:                                                                    /*{{{*/
                DumpErrors(std::cerr, trashhold);
        }
 
+       /** \brief put the current Messages into the stack
+        *
+        *  All "old" messages will be pushed into a stack to
+        *  them later back, but for now the Message query will be
+        *  empty and performs as no messages were present before.
+        *
+        * The stack can be as deep as you want - all stack operations
+        * will only operate on the last element in the stack.
+        */
+       void PushToStack();
+
+       /** \brief throw away all current messages */
+       void RevertToStack();
+
+       /** \brief merge current and stack together */
+       void MergeWithStack();
+
+       /** \brief return the deep of the stack */
+       size_t StackCount() const {
+               return Stacks.size();
+       }
+
        GlobalError();
                                                                        /*}}}*/
 private:                                                               /*{{{*/
@@ -244,6 +267,16 @@ private:                                                           /*{{{*/
        std::list<Item> Messages;
        bool PendingFlag;
 
+       struct MsgStack {
+               std::list<Item> const Messages;
+               bool const PendingFlag;
+
+               MsgStack(std::list<Item> const &Messages, bool const &Pending) :
+                        Messages(Messages), PendingFlag(Pending) {};
+       };
+
+       std::list<MsgStack> Stacks;
+
        bool InsertErrno(MsgType type, const char* Function,
                         const char* Description, va_list const &args);
        bool Insert(MsgType type, const char* Description,
index 3e7b16d..46e3711 100644 (file)
@@ -19,8 +19,9 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low
   * apt-pkg/contrib/error.{cc,h}:
     - complete rewrite but use the same API
     - add NOTICE and DEBUG as new types of a message
+    - add a simple stack handling to be able to delay error handling
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Fri, 25 Jun 2010 08:01:14 +0200
+ -- David Kalnischkies <kalnischkies@gmail.com>  Fri, 25 Jun 2010 19:15:21 +0200
 
 apt (0.7.26~exp7) experimental; urgency=low
 
diff --git a/test/libapt/globalerror_test.cc b/test/libapt/globalerror_test.cc
new file mode 100644 (file)
index 0000000..b275225
--- /dev/null
@@ -0,0 +1,77 @@
+#include <apt-pkg/error.h>
+
+#include "assert.h"
+#include <string>
+
+int main(int argc,char *argv[])
+{
+       equals(_error->empty(), true);
+       equals(_error->PendingError(), false);
+       equals(_error->Notice("%s Notice", "A"), false);
+       equals(_error->empty(), true);
+       equals(_error->empty(GlobalError::DEBUG), false);
+       equals(_error->PendingError(), false);
+       equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false);
+       equals(_error->PendingError(), true);
+       std::string text;
+       equals(_error->PopMessage(text), false);
+       equals(_error->PendingError(), true);
+       equals(text, "A Notice");
+       equals(_error->PopMessage(text), true);
+       equals(text, "Something horrible happend 2 times");
+       equals(_error->empty(GlobalError::DEBUG), true);
+       equals(_error->PendingError(), false);
+       equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false);
+       equals(_error->PendingError(), true);
+       equals(_error->empty(GlobalError::FATAL), false);
+       _error->Discard();
+
+       equals(_error->empty(), true);
+       equals(_error->PendingError(), false);
+       equals(_error->Notice("%s Notice", "A"), false);
+       equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false);
+       equals(_error->PendingError(), true);
+       equals(_error->empty(GlobalError::NOTICE), false);
+       _error->PushToStack();
+       equals(_error->empty(GlobalError::NOTICE), true);
+       equals(_error->PendingError(), false);
+       equals(_error->Warning("%s Warning", "A"), false);
+       equals(_error->empty(GlobalError::ERROR), true);
+       equals(_error->PendingError(), false);
+       _error->RevertToStack();
+       equals(_error->empty(GlobalError::ERROR), false);
+       equals(_error->PendingError(), true);
+       equals(_error->PopMessage(text), false);
+       equals(_error->PendingError(), true);
+       equals(text, "A Notice");
+       equals(_error->PopMessage(text), true);
+       equals(text, "Something horrible happend 2 times");
+       equals(_error->PendingError(), false);
+       equals(_error->empty(), true);
+
+       equals(_error->Notice("%s Notice", "A"), false);
+       equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false);
+       equals(_error->PendingError(), true);
+       equals(_error->empty(GlobalError::NOTICE), false);
+       _error->PushToStack();
+       equals(_error->empty(GlobalError::NOTICE), true);
+       equals(_error->PendingError(), false);
+       equals(_error->Warning("%s Warning", "A"), false);
+       equals(_error->empty(GlobalError::ERROR), true);
+       equals(_error->PendingError(), false);
+       _error->MergeWithStack();
+       equals(_error->empty(GlobalError::ERROR), false);
+       equals(_error->PendingError(), true);
+       equals(_error->PopMessage(text), false);
+       equals(_error->PendingError(), true);
+       equals(text, "A Notice");
+       equals(_error->PopMessage(text), true);
+       equals(text, "Something horrible happend 2 times");
+       equals(_error->PendingError(), false);
+       equals(_error->empty(), false);
+       equals(_error->PopMessage(text), false);
+       equals(text, "A Warning");
+       equals(_error->empty(), true);
+
+       return 0;
+}
index ee3401b..5005826 100644 (file)
@@ -30,13 +30,19 @@ SOURCE = getlistoffilesindir_test.cc
 include $(PROGRAM_H)
 
 # Program for testing CommandLine reconstruction
-PROGRAM = commandlineasstring${BASENAME}
+PROGRAM = CommandlineAsString${BASENAME}
 SLIBS = -lapt-pkg
 SOURCE = commandlineasstring_test.cc
 include $(PROGRAM_H)
 
 # Program for testing debians version comparing
-PROGRAM = compareversion${BASENAME}
+PROGRAM = CompareVersion${BASENAME}
 SLIBS = -lapt-pkg
 SOURCE = compareversion_test.cc
 include $(PROGRAM_H)
+
+# test the GlobalError stack class
+PROGRAM = GlobalError${BASENAME}
+SLIBS = -lapt-pkg
+SOURCE = globalerror_test.cc
+include $(PROGRAM_H)