]> git.tdb.fi Git - builder.git/blob - plugins/builtin/copy.cpp
Allow plugins to create additional targets in SourcePackages
[builder.git] / plugins / builtin / copy.cpp
1 #ifndef _WIN32
2 #include <unistd.h>
3 #include <sys/stat.h>
4 #endif
5 #include <msp/builder/builder.h>
6 #include <msp/builder/installedfile.h>
7 #include <msp/fs/dir.h>
8 #include <msp/fs/stat.h>
9 #include <msp/fs/utils.h>
10 #include <msp/io/file.h>
11 #include <msp/io/print.h>
12 #include "copy.h"
13
14 using namespace std;
15 using namespace Msp;
16
17 Copy::Copy(Builder &b):
18         Tool(b, "CP")
19 {
20         set_run_internal(_run);
21 }
22
23 Target *Copy::create_target(const vector<Target *> &sources, const string &arg)
24 {
25         FileTarget &file_tgt = dynamic_cast<FileTarget &>(*sources.front());
26         InstalledFile *inst = new InstalledFile(builder, *file_tgt.get_package(), file_tgt, arg);
27         inst->set_tool(*this);
28         return inst;
29 }
30
31 bool Copy::_run(const InstalledFile &install)
32 {
33         const FileTarget &source = install.get_source();
34         const FS::Path &src_path = source.get_path();
35         const FS::Path &dst_path = install.get_path();
36
37         try
38         {
39                 IO::File in(src_path.str());
40                 IO::File out(dst_path.str(), IO::M_WRITE);
41
42                 // Actual transfer loop
43                 char buf[16384];
44                 while(!in.eof())
45                 {
46                         unsigned len = in.read(buf, sizeof(buf));
47                         out.write(buf, len);
48                 }
49         }
50         catch(const exception &e)
51         {
52                 IO::print(IO::cerr, "%s\n", e.what());
53                 return false;
54         }
55
56 #ifndef _WIN32
57         // Preserve file permissions
58         struct stat st;
59         if(stat(src_path.str().c_str(), &st)==0)
60                 chmod(dst_path.str().c_str(), st.st_mode&0777);
61
62         const FS::Path &link = install.get_symlink();
63         if(!link.empty())
64         {
65                 FS::Path relpath = FS::relative(dst_path, FS::dirname(link));
66                 if(FS::exists(link))
67                         FS::unlink(link);
68                 symlink(relpath.str().c_str(), link.str().c_str());
69         }
70 #endif
71
72         return true;
73 }