]> gitweb.hamatoma.de Git - crepublib/commitdiff
ReDirRandom, ReDirDelete
authorhama <hama@siduction.net>
Wed, 4 Mar 2015 12:23:49 +0000 (13:23 +0100)
committerhama <hama@siduction.net>
Wed, 4 Mar 2015 12:23:49 +0000 (13:23 +0100)
base/ReSeqArray.hpp
cunit/cuReDirTools.cpp
cunit/cuReTraverser.cpp
cunit/testall.cpp
os/ReDirTools.cpp
os/ReDirTools.hpp
os/ReTraverser.hpp

index eeee484ee312c96e826aca273c8ec24623c23e29..7505d790b1b1b0aa1e73b99b00ee4f625154a215 100644 (file)
@@ -38,7 +38,7 @@ public:
        ReSeqArray(const ReSeqArray& source);
        ReSeqArray& operator =(const ReSeqArray& source);
 public:
-       Index add(Index index, const Byte* source, size_t sourceLength,
+       Index add(Index index, const Byte* source, size_t sourceLength = (size_t)-1,
            Tag tag = 0);
        bool binarySearch(const Byte* toFind, int length, Index& index, Tag* tag =
            NULL) const;
@@ -51,7 +51,7 @@ public:
                return m_list.length() / m_entrySize;
        }
        void dump(FILE* fp, const char* prefix) const;
-       Index find(const Byte* toFind, size_t length, Tag* tag = NULL) const;
+       Index find(const Byte* toFind, size_t length = -1, Tag* tag = NULL) const;
        bool get(Index index, ReByteBuffer& value, Tag* tag = NULL) const;
        /** Returns whether the comparisons inside the list are case insensitive.
         * @return <code>true</code> the comparisons inside the list are case insensitive
@@ -67,7 +67,8 @@ public:
                return m_sorted;
        }
        void remove(Index index);
-       void set(Index index, const Byte* source, size_t sourceLength, Tag tag);
+       void set(Index index, const Byte* source, size_t sourceLength = -1,
+               Tag tag = 0);
        void setCapacity(int maxIndices, int maxStringSpace);
        void setSizes(int sizeOfTag, int sizeOfLength, size_t constantLength =
            INDIVIDUAL_SIZE);
index 2ee6c15b55504f99e417defd2383fbd96cb35d1b..851eec40d8986944954e6c480affda494ae2700b 100644 (file)
@@ -14,6 +14,20 @@ static const char* s_empty[] = { NULL };
 // count of seconds from 1.1.1970 until 1.1.1980:\r
 const int tenYear = (365 * 10 + 2) * 24 * 3600;\r
 \r
+const char* s_allFiles[] = { //\r
+       " 1.txt", //\r
+       "*dir1", //\r
+       "*dir2", //\r
+       "*dir1/cache", //\r
+       "*dir1/dir1_1", //\r
+    "*dir1/dir1_2", //\r
+    "*dir1/dir1_2/dir1_2_1", //\r
+    " dir1/dir1_2/dir1_2_1/x1.txt", //\r
+    " dir1/dir1_2/dir1_2_1/x2.txt", //\r
+    " dir2/2.x", //\r
+    " dir1/cache/cache.txt", //\r
+    NULL };\r
+\r
 class TestReDirTools: public ReTestUnit {\r
 public:\r
        TestReDirTools() :\r
@@ -37,6 +51,101 @@ private:
        bool m_testAll;\r
        ReLogger* m_logger;\r
 private:\r
+       void run() {\r
+               testRandom();\r
+               testDelete();\r
+               testChecksumBuild();\r
+               if (m_testAll) {\r
+                       testDirOptions();\r
+                       checkSetFilterFromProgramArgs();\r
+                       testList2();\r
+                       testToolStatistic();\r
+                       testBasic();\r
+                       testDirStatistic();\r
+                       testCopyFile();\r
+                       testList();\r
+                       testToolSync();\r
+                       testBatch();\r
+                       testChecksumBuild();\r
+                       testDelete();\r
+                       testRandom();\r
+               }\r
+       }\r
+       void testRandom(){\r
+               const char* argv[] = { "random", "-l10", "-s", "90", "100",\r
+                   NULL };\r
+               ReDirRandom(m_logger).run(-1, argv);\r
+       }\r
+       void testDelete() {\r
+               rebuildTree();\r
+               ReByteBuffer nameCurrent;\r
+               buildFilename("current", nameCurrent);\r
+               ReByteBuffer optOutput("--output-file=");\r
+               optOutput.append(nameCurrent);\r
+               const char* argv[] = { "delete", "-p;x*.txt", optOutput.str(), m_base\r
+                   .str(), NULL };\r
+               const char* existing[] = { //\r
+                       " 1.txt", //\r
+                       "*dir1", //\r
+                       "*dir2", //\r
+                       "*dir1/cache", //\r
+                       "*dir1/dir1_1", //\r
+                       "*dir1/dir1_2", //\r
+                       "*dir1/dir1_2/dir1_2_1", //\r
+                       " dir2/2.x", //\r
+                       " dir1/cache/cache.txt", //\r
+                   NULL };\r
+               const char* notExisting[] = { //\r
+                       " dir1/dir1_2/dir1_2_1/x1.txt", //\r
+                       " dir1/dir1_2/dir1_2_1/x2.txt", //\r
+                   NULL };\r
+               ReDirDelete(m_logger).run(-1, argv);\r
+               mustExist(existing);\r
+               mayNotExist(notExisting);\r
+\r
+               const char* argv2[] = { "delete", optOutput.str(), m_base\r
+                   .str(), NULL };\r
+               ReDirDelete(m_logger).run(-1, argv2);\r
+               mayNotExist(s_allFiles);\r
+       }\r
+       void mustExist(const char** names){\r
+               ReByteBuffer name;\r
+               struct stat info;\r
+               for (int ix = 0; names[ix] != NULL; ix++){\r
+                       const char* arg = names[ix];\r
+                       name = m_base;\r
+                       name.ensureLastChar(OS_SEPARATOR_CHAR);\r
+                       name.append(arg + 1);\r
+                       name.replaceAll("/", -1, OS_SEPARATOR, -1);\r
+                       if (stat(name.str(), &info) != 0)\r
+                               checkEqu("missing", name);\r
+                       bool isDir = arg[0] == '*';\r
+                       if (isDir && ! S_ISDIR(info.st_mode))\r
+                               checkEqu("file not dir", name);\r
+                       if (! isDir && S_ISDIR(info.st_mode))\r
+                               checkEqu("dir not file", name);\r
+               }\r
+       }\r
+       void mayNotExist(const char** names){\r
+               ReByteBuffer name;\r
+               struct stat info;\r
+               for (int ix = 0; names[ix] != NULL; ix++){\r
+                       const char* arg = names[ix];\r
+                       name = m_base;\r
+                       name.ensureLastChar(OS_SEPARATOR_CHAR);\r
+                       name.append(arg + 1);\r
+                       name.replaceAll("/", -1, OS_SEPARATOR, -1);\r
+                       if (stat(name.str(), &info) == 0)\r
+                               checkEqu("exists", name);\r
+               }\r
+       }\r
+       int secOfFileTime(ReFileTime_t data) {\r
+#if defined __linux__\r
+               return data.tv_sec;\r
+#elif defined __WIN32__\r
+               return (int) ReDirStatus_t::filetimeToTime(&data);\r
+#endif\r
+       }\r
        const char* makeDir(const char* relPath) {\r
                m_buffer = m_base;\r
                m_buffer.append(relPath);\r
@@ -59,68 +168,49 @@ private:
                }\r
        }\r
        void initTree() {\r
-               makeFile("1.txt");\r
-               makeDir("dir1");\r
-               makeDir("dir2");\r
-               makeDir("dir1/cache");\r
-               makeDir("dir1/dir1_1");\r
-               makeDir("dir1/dir1_2");\r
-               makeDir("dir1/dir1_2/dir1_2_1");\r
-               makeFile("dir1/dir1_2/dir1_2_1/x1.txt");\r
-               makeFile("dir1/dir1_2/dir1_2_1/x2.txt");\r
-               makeFile("dir2/2.x");\r
-               makeFile("dir1/cache/cache.txt");\r
+               for (int ix = 0; s_allFiles[ix] != 0; ix++){\r
+                       const char* name = s_allFiles[ix];\r
+                       if (name[0] == '*')\r
+                               makeDir(name + 1);\r
+                       else\r
+                               makeFile(name + 1);\r
+               }\r
        }\r
-       void run() {\r
+       void rebuildTree() {\r
+               ReDirectory::deleteTree(m_base.str(), false);\r
                initTree();\r
-               if (m_testAll) {\r
-                       testChecksumBuild();\r
-                       testList2();\r
-                       testToolStatistic();\r
-                       testBasic();\r
-                       testDirOptions();\r
-                       checkSetFilterFromProgramArgs();\r
-                       testDirStatistic();\r
-                       testCopyFile();\r
-                       testList();\r
-                       testToolSync();\r
-                       testBatch();\r
-               }\r
        }\r
-       void testChecksumBuild(){\r
+       void testChecksumBuild() {\r
+               rebuildTree();\r
                ReByteBuffer nameCurrent;\r
                buildFilename("current", nameCurrent);\r
                ReByteBuffer optOutput("--output-file=");\r
                optOutput.append(nameCurrent);\r
-               const char* argv[] = { "dt", "checksum", "-P;*;-cache", "-tr", "-p;*.txt",\r
-                   "-s4711", "-arpd64", "-cBuild",\r
-                   optOutput.str(), m_base.str(), NULL };\r
+               const char* argv[] = { "dt", "checksum", "-P;*;-cache", "-tr",\r
+                   "-p;*.txt", "-s4711", "-arpd64", "-cBuild", optOutput.str(), m_base\r
+                       .str(), NULL };\r
                ReDirTools tools;\r
                tools.main(-1, (char**) argv);\r
                // checkFile(nameCurrent, "");\r
-               const char* argv2[] = { "dt", "checksum", "-P;*;-cache", "-tr", "-p;*.txt",\r
-                   "-s4711", "-arpd64", "-cCompare",\r
-                   optOutput.str(), m_base.str(), NULL };\r
+               const char* argv2[] = { "dt", "checksum", "-P;*;-cache", "-tr",\r
+                   "-p;*.txt", "-s4711", "-arpd64", "-cCompare", optOutput.str(),\r
+                   m_base.str(), NULL };\r
                tools.main(-1, (char**) argv2);\r
        }\r
        // F:\temp\retestunit\dirtool\r
        void testList2() {\r
+               rebuildTree();\r
                const char* argv[] = { "dt", "list", "-r", m_base.str(), NULL };\r
                ReDirTools tools;\r
                tools.main(4, (char**) argv);\r
        }\r
        void testList() {\r
+               rebuildTree();\r
                const char* argv[] = { "list", m_base.str(), NULL };\r
                ReDirList(m_logger).run(2, argv);\r
        }\r
-       int secOfFileTime(ReFileTime_t data) {\r
-#if defined __linux__\r
-               return data.tv_sec;\r
-#elif defined __WIN32__\r
-               return (int) ReDirStatus_t::filetimeToTime(&data);\r
-#endif\r
-       }\r
        void testCopyFile() {\r
+               rebuildTree();\r
 #if defined __linux__\r
                ReByteBuffer src(m_base);\r
                src.append("dir1/dir1_2/dir1_2_1/x1.txt");\r
@@ -129,7 +219,7 @@ private:
                ReByteBuffer buffer;\r
                buffer.ensureSize(5);\r
                ReDirSync::copyFile(src.str(), NULL, trg.str(), buffer,\r
-                       ReLogger::globalLogger());\r
+                   ReLogger::globalLogger());\r
                checkFileEqu(src.str(), trg.str());\r
 #else\r
                log(false, "testCopyFile not implemented");\r
@@ -225,6 +315,7 @@ private:
                        checkT(false);\r
        }\r
        void testBasic() {\r
+               rebuildTree();\r
                ReTraverser traverser(m_base.str());\r
                RePatternList patterns;\r
                // exclude */cache/*\r
@@ -247,6 +338,7 @@ private:
                checkF(hash.get("cache.txt", buffer));\r
        }\r
        void testDirStatistic() {\r
+               rebuildTree();\r
                ReDirStatistic stat(m_logger);\r
                const ReStringList& list = stat.calculate(m_base.str(), 1);\r
                ReByteBuffer buffer;\r
@@ -257,7 +349,7 @@ private:
                buffer.set(list.strOf(0), list.strLengthOf(0));\r
                checkT(buffer.startsWith("1\t"));\r
                expected.set(m_base.str(), m_base.length()).append("dir1", -1).append(\r
-                   OS_SEPARATOR);\r
+               OS_SEPARATOR);\r
                // .append(OS_SEPARATOR, -1)\r
                checkT(buffer.endsWith(expected.str()));\r
 \r
@@ -269,13 +361,13 @@ private:
                buffer.set(list.strOf(0), list.strLengthOf(0));\r
                checkT(buffer.startsWith("      0.000074 MB       3       4\t"));\r
                expected.set(m_base.str(), m_base.length()).append("dir1", -1).append(\r
-                   OS_SEPARATOR);\r
+               OS_SEPARATOR);\r
                checkT(buffer.endsWith(expected.str()));\r
 \r
                buffer.set(list.strOf(1), list.strLengthOf(1));\r
                checkT(buffer.startsWith("      0.000008 MB       1       0\t"));\r
                expected.set(m_base.str(), m_base.length()).append("dir2", -1).append(\r
-                   OS_SEPARATOR);\r
+               OS_SEPARATOR);\r
                checkT(buffer.endsWith(expected.str()));\r
 \r
                buffer.set(list.strOf(2), list.strLengthOf(2));\r
@@ -313,6 +405,7 @@ private:
                }\r
        }\r
        void testTouch() {\r
+               rebuildTree();\r
                ReByteBuffer nameCurrent;\r
                buildFilename("current", nameCurrent);\r
                ReByteBuffer optOutput("--output-file=");\r
@@ -342,6 +435,7 @@ private:
 \r
        }\r
        void testBatch() {\r
+               rebuildTree();\r
                ReByteBuffer nameCurrent;\r
                buildFilename("current", nameCurrent);\r
                ReByteBuffer optOutput("--output-file=");\r
@@ -351,15 +445,16 @@ private:
                    "-cmyscript", optOutput.str(), m_base.str(), NULL };\r
                tools.main(7, (char**) argv);\r
 #if defined __linux__\r
-               static const char* content = "#! /bin/sh*\n"\r
-               "myscript '*dirtool/dir1'\n"\r
-               "myscript '*dirtool/dir2'\n"\r
-               "myscript '*dirtool/dir1/dir1_1'\n"\r
-               "myscript '*dirtool/dir1/dir1_2'\n"\r
-               "myscript '*dirtool/dir1/cache'\n"\r
-               "myscript '*dirtool/dir1/dir1_2/dir1_2_1'\n"\r
-               "# === filtered:        0 file(s)     0.000000 MByte       6 dirs(s) */sec\n"\r
-               "# ===    total:        4 file(s)     0.000067 MByte       6 dirs(s) * sec";\r
+               static const char* content =\r
+                   "#! /bin/s*h\n"\r
+                           "myscript '*dirtool/dir1'\n"\r
+                           "myscript '*dirtool/dir2'\n"\r
+                           "myscript '*dirtool/dir1/dir1_1'\n"\r
+                           "myscript '*dirtool/dir1/dir1_2'\n"\r
+                           "myscript '*dirtool/dir1/cache'\n"\r
+                           "myscript '*dirtool/dir1/dir1_2/dir1_2_1'\n"\r
+                           "# === filtered:        0 file(s)     0.000000 MByte       6 dirs(s) */sec\n"\r
+                           "# ===    total:        4 file(s)     0.000067 MByte       6 dirs(s) * sec";\r
 #elif defined __WIN32__\r
                static const char* content = "rem this batch is created by*dirtool\n"\r
                "call myscript *dirtool\\dir1\"\n"\r
@@ -374,11 +469,13 @@ private:
                checkFile(nameCurrent, content);\r
        }\r
        void testToolStatistic() {\r
+               rebuildTree();\r
                ReDirTools tools;\r
                const char* argv[] = { "dt", "stat", "-P;*;-cache", m_base.str(), "2" };\r
                tools.main(5, (char**) argv);\r
        }\r
        void testToolSync() {\r
+               rebuildTree();\r
                ReDirTools tools;\r
                ReByteBuffer source(m_base);\r
                source.append("dir1");\r
index 01e2c247e0eee301da4eaba6386bba5b01ad3b53..708f8ab61f47072faffe4e81e31c731af9b26d51 100644 (file)
@@ -115,18 +115,30 @@ private:
                traverser.setDirPattern(&patterns);
                int level = 0;
                ReDirStatus_t* entry;
-               ReHashList hash;
+               ReHashList hashPath;
+               ReSeqArray listChanged;
+               int state = 0;
                while ((entry = traverser.rawNextFile(level)) != NULL) {
-                       hash.put(ReByteBuffer(entry->node(), -1), entry->m_path);
-                       logF(false, "%d: %-12s %2d %s", level, entry->node(),
+                       const char* node = entry->node();
+                       hashPath.put(ReByteBuffer(node, -1), entry->m_path);
+                       if (traverser.hasChangedPath(state))
+                               listChanged.add(-1, node);
+                       logF(false, "%d: %-12s %2d %s", level, node,
                            int(entry->fileSize()), entry->m_path.str());
                }
-               checkOneFile("x1.txt", "dir1_2_1", hash);
-               checkOneFile("x2.txt", "dir1_2_1", hash);
-               checkOneFile("dir1_2_1", "dir1_2", hash);
-               checkOneFile("dir1_1", "dir1", hash);
-               checkOneFile("dir1_2", "dir1", hash);
-               checkF(hash.get("cache.txt", buffer));
+               checkOneFile("x1.txt", "dir1_2_1", hashPath);
+               checkOneFile("x2.txt", "dir1_2_1", hashPath);
+               bool changed1 = listChanged.find("x1.txt") != (size_t) -1;
+               bool changed2 = listChanged.find("x2.txt") != (size_t) -1;
+               checkT(changed1 != changed2);
+               checkOneFile("dir1_2_1", "dir1_2", hashPath);
+               checkT(listChanged.find("dir1_2_1") >= 0);
+               checkOneFile("dir1_1", "dir1", hashPath);
+               checkOneFile("dir1_2", "dir1", hashPath);
+               changed1 = listChanged.find("dir1_1") != (size_t) -1;
+               changed2 = listChanged.find("dir1_2") != (size_t) -1;
+               checkT(changed1 != changed2);
+               checkF(hashPath.get("cache.txt", buffer));
        }
 };
 extern void testReTraverser(void);
index f853161f66690d605f21dcf1968e4b811ab37c3c..38f4fb99e0986477bffd0f52f3ec8ad9e997bd8f 100644 (file)
@@ -60,6 +60,8 @@ void testString() {
 void testOs() {
        void testReDirTools();
        testReDirTools();
+               void testReTraverser();
+               testReTraverser();
 
        if (s_testAll) {
                void testReTraverser();
index 89b64c60f9c85688fec41c391c0b577c19d23874..7f45b22b242ae3ce3208d0174963f7a0b1b148a0 100644 (file)
@@ -34,6 +34,7 @@ enum LOCATION_DIRTOOL {
        LC_COMPARE_STORAGE_6,           // 50120\r
        LC_COMPARE_STORAGE_7,           // 50121\r
        LC_COMPARE_DIR_1,                       // 50122\r
+       LC_DELETE_1,                            // 50123\r
 };\r
 const char* ReDirTools::m_version = "2015.02.25";\r
 ReLogger* ReDirTools::m_logger = NULL;\r
@@ -61,6 +62,15 @@ const char* s_batchUsage[] = {
     "   then it follows the full filename of the found file",\r
     "   use --arguments or --script to configure the output line",\r
     NULL };\r
+const char* s_deleteExamples[] = {\r
+    "dirtool delete --basename-pattern=;*~;*.bak e:\\data",\r
+    "dirtool delete /tmp/log",\r
+    NULL };\r
+\r
+const char* s_deleteUsage[] = {\r
+    "<command>: delete [<opts>] <dir_or_file1> [<dir_or_file2> ...]",\r
+    "   delete the specified files",\r
+    NULL };\r
 const char* s_batchExamples[] = {\r
     "dirtool batch -cbackup.bat --basename-pattern=;*.txt;*.doc e:\\data",\r
     "dirtool batch --type=r '--arguments=backup.sh !basename! !path!' usr etc",\r
@@ -85,6 +95,17 @@ const char* s_checksumExamples[] = { "dirtool ch --buffer-size=512 e:\\data",
     "dirtool checksum --command=Compare /home",\r
     "dirtool checksum -cUpdate -O/var/log/checksum.log /home",\r
     NULL };\r
+const char* s_randomUsage[] = {\r
+       "<command>: r(andom) <opts> count until [from]",\r
+       "  displays random numbers.",\r
+       "  <count> count of generated numbers",\r
+       "  <until> the maximum (including) value of the numbers",\r
+       "  <from>  the minimum (including) value of the numbers. Default: 1",\r
+       NULL };\r
+const char* s_randomExamples[] = { "dirtool ra --multiple -w3 10 33",\r
+       "dirtool rand -s 6 49",\r
+       "dirtool rand --sort --width=1 5 50",\r
+       NULL };\r
 \r
 static const char* s_statisticUsage[] =\r
     { "<command>: st(atistic)  [<opts>] <path1> [<path2> ...] [<depth>]",\r
@@ -701,12 +722,17 @@ bool ReTool::trace(const char* currentFile) {
 /**\r
  * Evaluates the arguments and calls the main function.\r
  *\r
- * @param argc                 number of arguments\r
+ * @param argc                 number of arguments. If -1: <code>argv</code> ends with <code>NULL</code>\r
  * @param argv                 program arguments\r
  * @param minArguments the command needs at least so many non option arguments\r
  */\r
 void ReTool::run(int argc, const char** argv) {\r
        try {\r
+               if (argc < 0){\r
+                       for (argc = 0; argv[argc] != NULL; argc++){\r
+                               // nothing to do\r
+                       }\r
+               }\r
                m_programArgs.init(argc, argv);\r
                if (m_programArgs.getArgCount() < m_minArguments)\r
                        m_programArgs.help(i18n("too few arguments"), false, stdout);\r
@@ -1402,7 +1428,47 @@ ReDigest& ReDirChecksum::calculateChecksum(const char* name,
        return digest;\r
 }\r
 \r
+/**\r
+ * Constructor.\r
+ *\r
+ * @param logger       logger for error handling\r
+ */\r
+ReDirDelete::ReDirDelete(ReLogger* logger) :\r
+           ReTool(s_deleteUsage, s_deleteExamples, 0, 0, 0, true, logger) {\r
+       addStandardFilterOptions();\r
+}\r
 \r
+/**\r
+ * Deletes the specified files/directories.\r
+ */\r
+void ReDirDelete::doIt() {\r
+       m_traverser.setDepthFirst(true);\r
+       processFileArguments();\r
+       printSummary();\r
+}\r
+\r
+/**\r
+ * Processes one directory.\r
+ *\r
+ * @param entry        the properties of the directory to process\r
+ */\r
+void ReDirDelete::processDir(ReDirStatus_t* entry) {\r
+       _rmdir(entry->fullName());\r
+}\r
+/**\r
+ * Processes one file.\r
+ *\r
+ * @param entry        the properties of the file to process\r
+ */\r
+void ReDirDelete::processFile(ReDirStatus_t* entry) {\r
+       const char* name = entry->fullName();\r
+       if (m_verboseLevel >= V_NORMAL){\r
+               fprintf(m_output, "%s\n", name);\r
+       }\r
+       if (unlink(name) != 0)\r
+               m_logger->sayF(LOG_ERROR | CAT_FILE, LC_DELETE_1,\r
+                       i18n("cannot delete ($1): $2")).arg(errno).arg(name).end();\r
+}\r
 \r
 /**\r
  * Constructor.\r
@@ -1468,6 +1534,72 @@ void ReDirList::processFile(ReDirStatus_t* entry) {
        }\r
 }\r
 \r
+/**\r
+ * Constructor.\r
+ *\r
+ * @param logger       logger for error handling\r
+ */\r
+ReDirRandom::ReDirRandom(ReLogger* logger) :\r
+           ReTool(s_randomUsage, s_randomExamples, 2, 0, 0, true, logger) {\r
+       m_hasStandardArgs = false;\r
+       m_programArgs.addBool("multiple", i18n("result can contain a value multiple times"),\r
+           'm', "--multiple", false);\r
+       m_programArgs.addInt("perline", i18n("number of values per line"),\r
+           'l', "--values-per-line", 10);\r
+       m_programArgs.addBool("sort", i18n("the result is sorted"),\r
+           's', "--sort", false);\r
+       m_programArgs.addInt("width", i18n("output format: minimum width of the numbers"\r
+               "   0: width of the maximum"),\r
+           'w', "--min-width", 0);\r
+}\r
+\r
+/**\r
+ * Lists the metadata of the specified files.\r
+ */\r
+void ReDirRandom::doIt() {\r
+       bool multiple = m_programArgs.getBool("multiple");\r
+       bool sort = m_programArgs.getBool("sort");\r
+       int count = atol(m_programArgs.getArg(0));\r
+       int to = atol(m_programArgs.getArg(1));\r
+       int from = 1;\r
+       if (m_programArgs.getArgCount() > 2)\r
+               from = atol(m_programArgs.getArg(2));\r
+       ReShiftRandom rand;\r
+       rand.setSeed(rand.nearTrueRandom());\r
+       int factor = to <= 1000 ? 1000 * 1000 : 1;\r
+       int numbersPerLine = m_programArgs.getInt("perline");\r
+       int width = m_programArgs.getInt("width");\r
+       if (width <= 0)\r
+               width = ReByteBuffer("").appendInt(to).length();\r
+       ReByteBuffer format("%");\r
+       format.appendInt(width).append("d%s");\r
+       int found = 0;\r
+       ReSeqArray values(count);\r
+       ReByteBuffer value;\r
+       if (! multiple && count >= to - from + 1)\r
+               help(i18n("not realy random: all possible values requested. Do you mean '--multiple'?"));\r
+       while(found < count){\r
+               value.setLength(0).appendInt(rand.nextInt(from * factor, to * factor)\r
+                       / factor, "%010d");\r
+               int ix = (int) values.find(value.str());\r
+               if (! multiple && ix != -1)\r
+                       continue;\r
+               found++;\r
+               values.add(-1, value.str());\r
+       }\r
+       if (sort)\r
+               values.sort();\r
+       for (int ii = 0; ii < count; ii++){\r
+               values.get(ii, value);\r
+               int val = atol(value.str());\r
+               printf(format.str(), val,\r
+                       ii % numbersPerLine == numbersPerLine - 1 ? "\n" : " ");\r
+       }\r
+       if (count % numbersPerLine != 0)\r
+               printf("\n");\r
+}\r
+\r
+\r
 /**\r
  * Calculates the statistic of a directory tree.\r
  *\r
@@ -2305,28 +2437,26 @@ void ReDirTools::help(int argc, const char* argv[]) {
                argv++;\r
                const char* arg0 = argv[0];\r
                if (isArg("batch", arg0)) {\r
-                       ReDirBatch batch(m_logger);\r
-                       batch.help(NULL);\r
+                       ReDirBatch(m_logger).help(NULL);\r
                } else if (isArg("checksum", arg0)) {\r
-                       ReDirChecksum sum(m_logger);\r
-                       sum.help(NULL);\r
+                       ReDirChecksum(m_logger).help(NULL);\r
+               } else if (_stricmp("delete", arg0) == 0) {\r
+                       ReDirDelete(m_logger).help(NULL);\r
                } else if (isArg("list", arg0)) {\r
-                       ReDirList list(m_logger);\r
-                       list.help(NULL);\r
+                       ReDirList(m_logger).help(NULL);\r
                } else if (isArg("help", arg0)) {\r
                        printField(s_helpSummary);\r
+               } else if (isArg("random", arg0)) {\r
+                       ReDirRandom(m_logger).help(NULL);\r
                } else if (isArg("statistic", arg0)) {\r
-                       ReDirStatistic stat(m_logger);\r
-                       stat.help(NULL);\r
+                       ReDirStatistic(m_logger).help(NULL);\r
                } else if (isArg("test", arg0)) {\r
                        void testAll();\r
                        testAll();\r
                } else if (isArg("touch", arg0)) {\r
-                       ReDirTouch touch(m_logger);\r
-                       touch.help(NULL);\r
+                       ReDirTouch(m_logger).help(NULL);\r
                } else if (isArg("which", arg0)) {\r
-                       ReDirWhich which(m_logger);\r
-                       which.help(NULL);\r
+                       ReDirWhich(m_logger).help(NULL);\r
                } else\r
                        printf("+++ unknown sub command: %s\n", arg0);\r
        }\r
@@ -2368,10 +2498,14 @@ int ReDirTools::main(int argc, char* orgArgv[]) {
                ReDirBatch(m_logger).run(argc, argv);\r
        else if (isArg("checksum", arg0))\r
                ReDirChecksum(m_logger).run(argc, argv);\r
+       else if (_stricmp("delete", arg0) == 0)\r
+               ReDirDelete(m_logger).run(argc, argv);\r
        else if (isArg("help", arg0))\r
                tools.help(argc, argv);\r
        else if (isArg("list", arg0))\r
                ReDirList(m_logger).run(argc, argv);\r
+       else if (isArg("random", arg0))\r
+               ReDirRandom(m_logger).run(argc, argv);\r
        else if (isArg("statistic", arg0))\r
                ReDirStatistic(m_logger).run(argc, argv);\r
        else if (isArg("synchronize", arg0))\r
index 3777e5cfe0a6dc2b09f6bbd129f982d5ce36096e..9e4cde2f225a71e74e8544a1ddfd66ad1929aa00 100644 (file)
@@ -145,23 +145,6 @@ protected:
        bool m_isExe;
 };
 
-/**
- * List file attributes of files.
- */
-class ReDirList: public ReTool {
-public:
-       ReDirList(ReLogger* logger);
-protected:
-       virtual void doIt();
-       virtual void processDir(ReDirStatus_t* entry);
-       virtual void processFile(ReDirStatus_t* entry);
-protected:
-       int m_widthOwner;
-       bool m_shortFormat;
-       bool m_withRights;
-       bool m_numerical;
-
-};
 class ReDigest;
 /**
  * Calculates / compares the checksum of files.
@@ -202,25 +185,42 @@ protected:
 };
 
 /**
- * Sychronizes two directory trees.
+ * List file attributes of files.
  */
-class ReDirSync: public ReTool {
+class ReDirDelete: public ReTool {
 public:
-       ReDirSync(ReLogger* logger);
+       ReDirDelete(ReLogger* logger);
 protected:
        virtual void doIt();
-       void copyFile(ReDirStatus_t* entry, const char* target);
-       void makeDirWithParents(ReByteBuffer& path, int minWidth,
-           ReTraverser& traverser);
+       virtual void processDir(ReDirStatus_t* entry);
+       virtual void processFile(ReDirStatus_t* entry);
+};
+
+/**
+ * List file attributes of files.
+ */
+class ReDirList: public ReTool {
 public:
-       static bool copyFile(const char* source, ReFileProperties_t* properties,
-           const char* target, ReByteBuffer& buffer, ReLogger* logger = NULL);
-       static bool makeDirectory(const char* directory, int minLength,
-           ReFileProperties_t* properties, ReLogger* logger = NULL);
-       static bool setProperties(const char* fullName,
-           ReFileProperties_t* properties, ReLogger* logger = NULL);
+       ReDirList(ReLogger* logger);
 protected:
-       ReByteBuffer m_buffer;
+       virtual void doIt();
+       virtual void processDir(ReDirStatus_t* entry);
+       virtual void processFile(ReDirStatus_t* entry);
+protected:
+       int m_widthOwner;
+       bool m_shortFormat;
+       bool m_withRights;
+       bool m_numerical;
+};
+
+/**
+ * Displays random numbers.
+ */
+class ReDirRandom: public ReTool {
+public:
+       ReDirRandom(ReLogger* logger);
+protected:
+       virtual void doIt();
 };
 
 class ReDirStatisticData: public ReDirTreeStatistic {
@@ -260,6 +260,28 @@ private:
        time_t m_lastTrace;
 };
 
+/**
+ * Sychronizes two directory trees.
+ */
+class ReDirSync: public ReTool {
+public:
+       ReDirSync(ReLogger* logger);
+protected:
+       virtual void doIt();
+       void copyFile(ReDirStatus_t* entry, const char* target);
+       void makeDirWithParents(ReByteBuffer& path, int minWidth,
+           ReTraverser& traverser);
+public:
+       static bool copyFile(const char* source, ReFileProperties_t* properties,
+           const char* target, ReByteBuffer& buffer, ReLogger* logger = NULL);
+       static bool makeDirectory(const char* directory, int minLength,
+           ReFileProperties_t* properties, ReLogger* logger = NULL);
+       static bool setProperties(const char* fullName,
+           ReFileProperties_t* properties, ReLogger* logger = NULL);
+protected:
+       ReByteBuffer m_buffer;
+};
+
 /**
  * Changes the filetime of files.
  */
index d97add56ce655473a8d18977e8371d41915c9547..ba65297d811005487c1679d03f4ba05067c533dd 100644 (file)
@@ -201,12 +201,28 @@ public:
        inline int files() const {
                return m_files;
        }
+       /** Returns whether the current directory has changed since the last call.
+        * @param state         IN/OUT: stored info about the current directory.
+        *                                      The value has no interest for the caller
+        * @return                      <code>true</code>: the path has been changed
+        */
+       inline bool hasChangedPath(int& state){
+               bool rc = m_directories > state; state = m_directories;
+               return rc;
+       }
        ReDirStatus_t* rawNextFile(int& level);
        ReDirStatus_t* nextFile(int& level, ReDirEntryFilter_t* filter = NULL);
+       /** Sets the tree traversal algorithm.
+        * @param depthFirst    <code>true</code>: files of the subdirectories will
+        *                      be returned earlier
+        */
+       void setDepthFirst(bool depthFirst){
+               m_passNoForDirSearch = depthFirst ? 1 : 2;
+       }
        /** Sets directory filter (pattern list).
         * @param pattern       pattern list for the subdirs to be entered
         */
-       void setDirPattern(RePatternList* pattern) {
+       inline void setDirPattern(RePatternList* pattern) {
                m_dirPatterns = pattern;
                if (pattern != NULL)
                        m_dirPatterns->setIgnoreCase(true);
@@ -214,13 +230,13 @@ public:
        /** Sets the maximal depth.
         * @param value     the value to set
         */
-       void setMaxLevel(int value) {
+       inline void setMaxLevel(int value) {
                m_maxLevel = value;
        }
        /** Sets the minimal depth.
         * @param value     the value to set
         */
-       void setMinLevel(int value) {
+       inline void setMinLevel(int value) {
                m_minLevel = value;
        }
        void setPropertiesFromFilter(ReDirEntryFilter_t* filter);