]> git.tdb.fi Git - builder.git/blob - source/datatransform.cpp
Refactor transitive dependencies to work on all targets
[builder.git] / source / datatransform.cpp
1 #include <msp/fs/dir.h>
2 #include <msp/fs/stat.h>
3 #include <msp/fs/utils.h>
4 #include <msp/strings/format.h>
5 #include <msp/strings/regex.h>
6 #include "builder.h"
7 #include "cache.h"
8 #include "component.h"
9 #include "datatransform.h"
10 #include "file.h"
11 #include "sourcepackage.h"
12
13 using namespace std;
14 using namespace Msp;
15
16 DataTransform::DataTransform(Builder &b, const Component &c, const FS::Path &p):
17         FileTarget(b, c.get_package(), p)
18 {
19         component = &c;
20
21         if(FS::Stat st = FS::lstat(FS::dirname(path)))
22                 dir_mtime = st.get_modify_time();
23 }
24
25 void DataTransform::find_dependencies()
26 {
27         list<string> files;
28         Cache &cache = component->get_package().get_cache();
29         const Time::TimeStamp &cache_mtime = cache.get_mtime();
30         if(mtime<cache_mtime && dir_mtime<cache_mtime && cache.has_key(this, "files"))
31                 files = cache.get_values(this, "files");
32         else
33         {
34                 builder.get_logger().log("files", format("Reading imports from %s", path.str()));
35                 IO::File in(path.str());
36                 DataFile::Parser parser(in, path.str());
37
38                 list<string> dir_files;
39                 while(!in.eof())
40                 {
41                         DataFile::Statement st = parser.parse();
42                         if(st.keyword=="for_each")
43                         {
44                                 // There's bound to be at least one file: the transform itself
45                                 if(dir_files.empty())
46                                 {
47                                         FS::Path dir = FS::dirname(path);
48                                         builder.get_logger().log("files", format("Traversing %s", dir.str()));
49                                         dir_files = list_files(dir);
50                                 }
51
52                                 for(DataFile::Statement::Arguments::const_iterator i=st.args.begin(); i!=st.args.end(); ++i)
53                                 {
54                                         Regex re(i->get<string>());
55                                         for(list<string>::const_iterator j=dir_files.begin(); j!=dir_files.end(); ++j)
56                                                 if(re.match(*j))
57                                                         files.push_back(*j);
58                                 }
59                         }
60                         else if(st.keyword=="file" && st.args.size()==1)
61                                 files.push_back(st.args.front().get<string>());
62                 }
63
64                 cache.set_values(this, "files", files);
65         }
66
67         for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
68         {
69                 FS::Path file_path = FS::dirname(path)/ *i;
70                 if(Target *tgt = builder.get_vfs().get_target(file_path))
71                         add_transitive_dependency(*tgt);
72                 else
73                         add_transitive_dependency(*new File(builder, *package, file_path));
74         }
75 }