Add an example that does some directory operations
authorMikko Rasa <tdb@tdb.fi>
Mon, 9 Jul 2012 14:45:46 +0000 (17:45 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 9 Jul 2012 16:12:53 +0000 (19:12 +0300)
Build
examples/syncdir.cpp [new file with mode: 0644]

diff --git a/Build b/Build
index fc7b33a27b94569f6851d500f6996d96a02ef60c..8478fc5bd405f8d75f06be224f86ba0f3da9386a 100644 (file)
--- a/Build
+++ b/Build
@@ -102,6 +102,15 @@ package "mspcore"
                };
        };
 
+       program "syncdir"
+       {
+               source "examples/syncdir.cpp";
+               build_info
+               {
+                       library "mspcore";
+               };
+       };
+
        tarball "@src"
        {
                source "License.txt";
diff --git a/examples/syncdir.cpp b/examples/syncdir.cpp
new file mode 100644 (file)
index 0000000..7d4789a
--- /dev/null
@@ -0,0 +1,97 @@
+#include <algorithm>
+#include <msp/core/application.h>
+#include <msp/core/getopt.h>
+#include <msp/fs/dir.h>
+#include <msp/fs/stat.h>
+#include <msp/fs/utils.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include <msp/strings/format.h>
+
+using namespace std;
+using namespace Msp;
+
+class SyncDir: public RegisteredApplication<SyncDir>
+{
+private:
+       FS::Path source;
+       FS::Path destination;
+
+public:
+       SyncDir(int, char **);
+
+       int main();
+private:
+       void sync_directory(const FS::Path &, const FS::Path &);
+       void copy_file(const FS::Path &, const FS::Path &);
+};
+
+SyncDir::SyncDir(int argc, char **argv)
+{
+       if(argc<3)
+               throw usage_error("Missing arguments", format("Usage: %s <source> <destination>", argv[0]));
+
+       source = argv[1];
+       destination = argv[2];
+}
+
+int SyncDir::main()
+{
+       sync_directory(source, destination);
+       return 0;
+}
+
+void SyncDir::sync_directory(const FS::Path &src, const FS::Path &dest)
+{
+       IO::print("Syncing %s to %s\n", src, dest);
+
+       FS::Stat st = FS::stat(dest);
+       if(!st)
+               FS::mkpath(dest, 0755);
+       else if(!st.is_directory())
+       {
+               FS::unlink(dest);
+               FS::mkdir(dest, 0755);
+       }
+
+       list<string> src_files = FS::list_files(src);
+       for(list<string>::const_iterator i=src_files.begin(); i!=src_files.end(); ++i)
+       {
+               const string &fn = *i;
+               FS::Stat ss = FS::stat(src/fn);
+               if(ss.is_directory())
+                       sync_directory(src/fn, dest/fn);
+               else
+               {
+                       FS::Stat ds = FS::stat(dest/fn);
+                       if(!ds || ds.get_size()!=ss.get_size())
+                               copy_file(src/fn, dest/fn);
+               }
+       }
+
+       list<string> dest_files = FS::list_files(dest);
+       for(list<string>::const_iterator i=dest_files.begin(); i!=dest_files.end(); ++i)
+       {
+               if(find(src_files.begin(), src_files.end(), *i)==src_files.end())
+               {
+                       const string &fn = *i;
+                       IO::print("Removing obsolete %s\n", dest/fn);
+                       if(FS::is_dir(dest/fn))
+                               FS::rmpath(dest/fn);
+                       else
+                               FS::unlink(dest/fn);
+               }
+       }
+}
+
+void SyncDir::copy_file(const FS::Path &src, const FS::Path &dest)
+{
+       IO::File in(src.str(), IO::M_READ);
+       IO::File out(dest.str(), IO::M_WRITE);
+       char buf[16384];
+       while(!in.eof())
+       {
+               unsigned len = in.read(buf, sizeof(buf));
+               out.write(buf, len);
+       }
+}