1 # |
1 # |
2 # Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
2 # Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
3 # All rights reserved. |
3 # All rights reserved. |
4 # This component and the accompanying materials are made available |
4 # This component and the accompanying materials are made available |
5 # under the terms of the License "Eclipse Public License v1.0" |
5 # under the terms of the License "Eclipse Public License v1.0" |
6 # which accompanies this distribution, and is available |
6 # which accompanies this distribution, and is available |
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
13 # |
13 # |
14 # Description: |
14 # Description: |
15 # Filter class for copying files in serial in python. This |
15 # Filter class for copying files in serial in python. This |
16 # is important in cluster builds where file copying is |
16 # is important in cluster builds where file copying is |
17 # very inefficient. |
17 # very inefficient. |
18 # The one-to-many <copy> tag is searched for and copy |
18 # The one-to-many <finalcopy> tag is searched for and copy |
19 # instructions are built up in a hash table. |
19 # instructions are built up in a hash table. |
20 # <copy source='sourcefilename'>destfilename1 destfilename2 . . . .destfilenameN</copy> |
20 # <finalcopy source='sourcefilename'>destfilename1 destfilename2 . . . .destfilenameN</copy> |
21 # destinations must be full filenames not directories. |
21 # destinations must be full filenames not directories. |
22 # |
22 # |
23 # This filter monitors build progress |
23 # This filter monitors build progress |
24 # via the <progress> tags and flushes copies as build |
24 # via the <progress> tags and flushes copies as build |
25 # stages end (e.g. after resource so resources are ready for the next stage) |
25 # stages end (e.g. after resource so resources are ready for the next stage) |
47 |
48 |
48 def write(self, text): |
49 def write(self, text): |
49 "process some log text" |
50 "process some log text" |
50 |
51 |
51 for line in text.splitlines(): |
52 for line in text.splitlines(): |
52 if line.startswith("<copy"): |
53 if line.startswith("<finalcopy"): |
53 source_start=line.find("source='") |
54 source_start = line.find("source='") |
54 source=line[source_start+8:line.find("'", source_start+8)] |
55 source = line[source_start+8:line.find("'", source_start+8)] |
55 destinations = line[line.find(">",source_start)+1:line.find("</copy>")].split(" ") |
56 destinations = line[line.find(">",source_start)+1:line.find("</finalcopy>")].split(" ") |
56 |
57 |
57 if source in self.files: |
58 if source in self.files: |
58 self.files[source].update(destinations) |
59 self.files[source].update(destinations) |
59 else: |
60 else: |
60 self.files[source] = set(destinations) |
61 self.files[source] = set(destinations) |
61 elif line.startswith("<progress:end object_type='makefile' task='build'"): |
62 elif line.startswith("<progress:end object_type='makefile' task='build'"): |
62 self.flushcopies() # perform copies at end of each invocation of the make engine |
63 self.flushcopies() # perform copies at end of each invocation of the make engine |
63 # to ensure dependencies are in place for the next one. |
64 # to ensure dependencies are in place for the next one. |
64 |
65 |
65 return self.ok |
66 return self.ok |
66 |
67 |
67 |
68 |
68 def summary(self): |
69 def summary(self): |
70 self.flushcopies() |
71 self.flushcopies() |
71 return self.ok |
72 return self.ok |
72 |
73 |
73 def flushcopies(self): |
74 def flushcopies(self): |
74 for source in self.files.keys(): |
75 for source in self.files.keys(): |
75 #print "<debug>self.files %s</debug>" % self.files[source] |
|
76 for dest in self.files[source]: |
76 for dest in self.files[source]: |
77 self.copyfile(source, dest) |
77 copyfile(source, dest) |
78 self.files = {} |
78 self.files = {} |
79 |
79 |
80 |
80 |
81 |
81 |
82 def close(self): |
82 def close(self): |
83 "nop" |
83 "nop" |
84 |
84 |
85 |
85 |
86 return self.ok |
86 return self.ok |
87 |
87 |
88 def copyfile(self, _source, _destination): |
|
89 """Copy the source file to the destination file (create a directory |
|
90 to copy into if it does not exist). Don't copy if the destination |
|
91 file exists and has an equal or newer modification time.""" |
|
92 source = generic_path.Path(str(_source).replace('%20',' ')) |
|
93 destination = generic_path.Path(str(_destination).replace('%20',' ')) |
|
94 dest_str = str(destination) |
|
95 source_str = str(source) |
|
96 |
|
97 try: |
|
98 |
|
99 |
|
100 destDir = destination.Dir() |
|
101 if not destDir.isDir(): |
|
102 os.makedirs(str(destDir)) |
|
103 shutil.copyfile(source_str, dest_str) |
|
104 return |
|
105 |
|
106 # Destination file exists so we have to think about updating it |
|
107 sourceMTime = 0 |
|
108 destMTime = 0 |
|
109 sourceStat = 0 |
|
110 try: |
|
111 sourceStat = os.stat(source_str) |
|
112 sourceMTime = sourceStat[stat.ST_MTIME] |
|
113 destMTime = os.stat(dest_str)[stat.ST_MTIME] |
|
114 except OSError, e: |
|
115 if sourceMTime == 0: |
|
116 message = "Source of copyfile does not exist: " + str(source) |
|
117 print message |
|
118 |
|
119 if destMTime == 0 or destMTime < sourceMTime: |
|
120 if os.path.exists(dest_str): |
|
121 os.chmod(dest_str,stat.S_IREAD | stat.S_IWRITE) |
|
122 shutil.copyfile(source_str, dest_str) |
|
123 |
|
124 # Ensure that the destination file remains executable if the source was also: |
|
125 os.chmod(dest_str,sourceStat[stat.ST_MODE] | stat.S_IREAD | stat.S_IWRITE | stat.S_IWGRP ) |
|
126 |
|
127 |
|
128 except Exception,e: |
|
129 message = "Could not export " + source_str + " to " + dest_str + " : " + str(e) |
|
130 |
|
131 return |
|
132 |
|
133 # the end |
88 # the end |
134 |
89 |