]> git.tdb.fi Git - builder.git/blobdiff - plugins/builtin/copy.cpp
Rearrange sources into subdirectories
[builder.git] / plugins / builtin / copy.cpp
diff --git a/plugins/builtin/copy.cpp b/plugins/builtin/copy.cpp
new file mode 100644 (file)
index 0000000..0633ff9
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef _WIN32
+#include <unistd.h>
+#include <sys/stat.h>
+#endif
+#include <msp/builder/builder.h>
+#include <msp/builder/installedfile.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 "copy.h"
+
+using namespace std;
+using namespace Msp;
+
+Copy::Copy(Builder &b):
+       Tool(b, "CP")
+{
+       set_run_internal(_run);
+}
+
+Target *Copy::create_target(const vector<Target *> &sources, const string &arg)
+{
+       FileTarget &file_tgt = dynamic_cast<FileTarget &>(*sources.front());
+       InstalledFile *inst = new InstalledFile(builder, *file_tgt.get_package(), file_tgt, arg);
+       inst->set_tool(*this);
+       return inst;
+}
+
+bool Copy::_run(const InstalledFile &install)
+{
+       const FileTarget &source = install.get_source();
+       const FS::Path &src_path = source.get_path();
+       const FS::Path &dst_path = install.get_path();
+
+       try
+       {
+               IO::File in(src_path.str());
+               IO::File out(dst_path.str(), IO::M_WRITE);
+
+               // Actual transfer loop
+               char buf[16384];
+               while(!in.eof())
+               {
+                       unsigned len = in.read(buf, sizeof(buf));
+                       out.write(buf, len);
+               }
+       }
+       catch(const exception &e)
+       {
+               IO::print(IO::cerr, "%s\n", e.what());
+               return false;
+       }
+
+#ifndef _WIN32
+       // Preserve file permissions
+       struct stat st;
+       if(stat(src_path.str().c_str(), &st)==0)
+               chmod(dst_path.str().c_str(), st.st_mode&0777);
+
+       const FS::Path &link = install.get_symlink();
+       if(!link.empty())
+       {
+               FS::Path relpath = FS::relative(dst_path, FS::dirname(link));
+               if(FS::exists(link))
+                       FS::unlink(link);
+               symlink(relpath.str().c_str(), link.str().c_str());
+       }
+#endif
+
+       return true;
+}