]> git.tdb.fi Git - builder.git/blob - source/installmap.cpp
Refactor transitive dependencies to work on all targets
[builder.git] / source / installmap.cpp
1 #include <msp/fs/utils.h>
2 #include "component.h"
3 #include "filetarget.h"
4 #include "installmap.h"
5 #include "sourcepackage.h"
6 #include "templatefile.h"
7
8 using namespace std;
9 using namespace Msp;
10
11 void InstallMap::add_mapping(const FS::Path &src, const FS::Path &inst)
12 {
13         Entry e;
14         e.source = src;
15         e.install = inst;
16         entries.push_back(e);
17 }
18
19 FS::Path InstallMap::get_install_location(const FileTarget &target) const
20 {
21         const Component *comp = target.get_component();
22         unsigned overlay_depth = 0;
23         if(comp && !comp->get_overlays().empty())
24         {
25                 // Check if the target resides in an overlay directory
26                 const Component::OverlayList &overlays = comp->get_overlays();
27                 string last_dir = FS::basename(FS::dirname(target.get_path()));
28                 for(Component::OverlayList::const_iterator i=overlays.begin(); i!=overlays.end(); ++i)
29                         if(last_dir==*i)
30                                 overlay_depth = 1;
31         }
32
33         FS::Path source = target.get_path();
34         if(comp)
35         {
36                 /* Check if the target is a generated source file, residing in the
37                 temporary directory */
38                 const SourcePackage &pkg = comp->get_package();
39                 int temp_depth = FS::descendant_depth(source, pkg.get_temp_directory());
40                 if(temp_depth>0)
41                 {
42                         // If it is, use the generating template's directory instead
43                         const Target::Dependencies &deps = target.get_dependencies();
44                         for(Target::Dependencies::const_iterator i=deps.begin(); i!=deps.end(); ++i)
45                                 if(const TemplateFile *tmpl = dynamic_cast<const TemplateFile *>(*i))
46                                 {
47                                         source = FS::dirname(tmpl->get_path())/FS::basename(source);
48                                         break;
49                                 }
50                 }
51         }
52
53         /* Look for a mapping entry matching both the target's original location
54         and default install location */
55         FS::Path install = target.get_install_location();
56         for(list<Entry>::const_iterator i=entries.begin(); i!=entries.end(); ++i)
57         {
58                 int source_depth = FS::descendant_depth(source, i->source);
59                 if(source_depth>=0)
60                 {
61                         FS::Path install_base = FS::common_ancestor(install, i->install);
62                         if(install_base.size()>1)
63                         {
64                                 install = i->install/source.subpath(i->source.size(), source_depth-1-overlay_depth);
65                                 break;
66                         }
67                 }
68         }
69
70         return install;
71 }
72
73
74 InstallMap::Loader::Loader(InstallMap &m, const FS::Path &s):
75         DataFile::ObjectLoader<InstallMap>(m),
76         source_base(s)
77 {
78         add("map", &Loader::map);
79 }
80
81 void InstallMap::Loader::map(const string &src, const string &inst)
82 {
83         obj.add_mapping(source_base/src, inst);
84 }