2005-06-05 Peter Bartok <pbartok@novell.com>
[mono.git] / mcs / nant / src / Tasks / CopyTask.cs
1 // NAnt - A .NET build tool\r
2 // Copyright (C) 2001 Gerry Shaw\r
3 //\r
4 // This program is free software; you can redistribute it and/or modify\r
5 // it under the terms of the GNU General Public License as published by\r
6 // the Free Software Foundation; either version 2 of the License, or\r
7 // (at your option) any later version.\r
8 //\r
9 // This program is distributed in the hope that it will be useful,\r
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
12 // GNU General Public License for more details.\r
13 //\r
14 // You should have received a copy of the GNU General Public License\r
15 // along with this program; if not, write to the Free Software\r
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
17 //\r
18 // Gerry Shaw (gerry_shaw@yahoo.com)\r
19 // Ian MacLean (ian_maclean@another.com)\r
20 \r
21 namespace SourceForge.NAnt {\r
22 \r
23     using System;\r
24     using System.IO;\r
25     using System.Xml;\r
26     using System.Text;\r
27     using System.Collections;\r
28     using System.Collections.Specialized;\r
29 \r
30     [TaskName("copy")]\r
31     public class CopyTask : Task {\r
32 \r
33         [TaskAttribute("file")]\r
34         string _sourceFile = null;\r
35 \r
36         [TaskAttribute("tofile")]\r
37         string _toFile = null;\r
38 \r
39         [TaskAttribute("todir")]\r
40         string _toDirectory = null;\r
41 \r
42         [TaskAttribute("filtering")]\r
43         [BooleanValidator()]\r
44         string _filtering = Boolean.FalseString;\r
45 \r
46         [TaskAttribute("flatten")]\r
47         [BooleanValidator()]\r
48         string _flatten = Boolean.FalseString;\r
49 \r
50         [TaskAttribute("includeEmptyDirs")]\r
51         [BooleanValidator()]\r
52         string _includeEmptyDirs = Boolean.FalseString;\r
53 \r
54         [TaskFileSet("fileset")]\r
55         FileSet _fileset = new FileSet(true); // include all by default\r
56 \r
57         [TaskAttribute("overwrite")]\r
58         [BooleanValidator()]\r
59         string _overwrite = Boolean.FalseString;\r
60 \r
61         [TaskAttribute("verbose")]\r
62         [BooleanValidator()]\r
63         string _verbose = Boolean.FalseString;\r
64 \r
65         [TaskAttribute("preserveLastModified")]\r
66         [BooleanValidator()]\r
67         string _preserveLastModified = Boolean.FalseString;\r
68 \r
69         Hashtable _fileCopyMap = new Hashtable();\r
70 \r
71         public string SourceFile        { get { return _sourceFile; } }\r
72         public string ToFile            { get { return _toFile; } }\r
73         public string ToDirectory       { get { return _toDirectory; } }\r
74         public bool Filtering           { get { return Convert.ToBoolean(_filtering); } }\r
75         public bool Flatten             { get { return Convert.ToBoolean(_flatten); } }\r
76         public bool IncludeEmptyDirs    { get { return Convert.ToBoolean(_includeEmptyDirs); } }\r
77         public bool Overwrite           { get { return Convert.ToBoolean(_overwrite); } }\r
78         public bool PreserveLastModified{ get { return Convert.ToBoolean(_preserveLastModified); } }\r
79         public FileSet CopyFileSet      { get { return _fileset; } }\r
80 \r
81         public bool Verbose { \r
82             get {\r
83                 return (Project.Verbose || Convert.ToBoolean(_verbose));\r
84             } \r
85         }\r
86 \r
87         protected Hashtable FileCopyMap {\r
88             get { return _fileCopyMap; }\r
89         }\r
90 \r
91         /// <summary>\r
92         /// Actually does the file (and possibly empty directory) copies.\r
93         /// </summary>\r
94         protected virtual void DoFileOperations() {\r
95             int fileCount = FileCopyMap.Keys.Count;\r
96             if (fileCount > 0) {\r
97                 if (ToDirectory != null) {\r
98                     Log.WriteLine(LogPrefix + "Copying {0} files to {1}", fileCount, Project.GetFullPath(ToDirectory));\r
99                 } else {\r
100                     Log.WriteLine(LogPrefix + "Copying {0} files", fileCount);\r
101                 }\r
102 \r
103                 // loop thru our file list\r
104                 foreach (string sourcePath in FileCopyMap.Keys) {\r
105                     string dstPath = (string)FileCopyMap[sourcePath];\r
106                     if (sourcePath == dstPath) {\r
107                         if (Verbose) {\r
108                             Log.WriteLine(LogPrefix + "Skipping self-copy of {0}" + sourcePath);\r
109                         }\r
110                         continue;\r
111                     }\r
112 \r
113                     try {\r
114                         if (Verbose) {\r
115                             Log.WriteLine(LogPrefix + "Copying {0} to {1}", sourcePath, dstPath);\r
116                         }\r
117 \r
118                         // create directory if not present\r
119                         string dstDirectory = Path.GetDirectoryName(dstPath);\r
120                         if (!Directory.Exists(dstDirectory)) {\r
121                             Directory.CreateDirectory(dstDirectory);\r
122                             if (Verbose) {\r
123                                 Log.WriteLine(LogPrefix + "Created directory {0}", dstDirectory);\r
124                             }\r
125                         }\r
126 \r
127                         File.Copy(sourcePath, dstPath, true);\r
128                     } catch (IOException ioe) {\r
129                         string msg = String.Format("Cannot copy {0} to {1}", sourcePath, dstPath);\r
130                         throw new BuildException(msg, Location, ioe);\r
131                     }\r
132                 }\r
133             }\r
134 \r
135             // TODO: handle empty directories in the fileset, refer to includeEmptyDirs attribute at\r
136             // http://jakarta.apache.org/ant/manual/CoreTasks/copy.html\r
137         }\r
138 \r
139         protected override void ExecuteTask() {\r
140 \r
141             string dstDirectoryPath = Project.GetFullPath(ToDirectory);\r
142             string srcFilePath = Project.GetFullPath(SourceFile);\r
143             FileInfo srcInfo = new FileInfo(srcFilePath);\r
144 \r
145             string dstFilePath;\r
146             if (ToFile == null) {\r
147                 dstFilePath = dstDirectoryPath + Path.DirectorySeparatorChar + srcInfo.Name;\r
148             } else {\r
149                 dstFilePath = Project.GetFullPath(ToFile);\r
150             }\r
151 \r
152             FileInfo dstInfo = new FileInfo(dstFilePath);\r
153             if (SourceFile != null) {\r
154                 if (srcInfo.Exists) {\r
155                     // do the outdated check\r
156                     bool outdated = (!dstInfo.Exists) || (srcInfo.LastWriteTime > dstInfo.LastWriteTime);\r
157 \r
158                     if (Overwrite || outdated) {\r
159                         // add to a copy map of absolute verified paths\r
160                         FileCopyMap.Add(srcFilePath, dstFilePath);\r
161                     }\r
162                 } else {\r
163                     Log.WriteLine(LogPrefix + "Could not find file {0} to copy.", srcFilePath);\r
164                 }\r
165             } else {\r
166                 // get the complete path of the base directory of the fileset, ie, c:\work\nant\src\r
167                 string srcBasePath = Project.GetFullPath(CopyFileSet.BaseDirectory);\r
168                 string dstBasePath = Project.GetFullPath(ToDirectory);\r
169 \r
170                 // if source file not specified use fileset\r
171                 foreach (string pathname in CopyFileSet.FileNames) {\r
172                     // replace the fileset path with the destination path\r
173                     // NOTE: big problems could occur if the file set base dir is rooted on a different drive\r
174                     string dstPath = pathname.Replace(srcBasePath, dstBasePath);\r
175 \r
176                     srcInfo = new FileInfo(pathname);\r
177                     dstInfo = new FileInfo(dstPath);\r
178 \r
179                     if (srcInfo.Exists) {\r
180                         // do the outdated check\r
181                         bool outdated = (!dstInfo.Exists) || (srcInfo.LastWriteTime > dstInfo.LastWriteTime);\r
182 \r
183                         if (Overwrite || outdated) {\r
184                             FileCopyMap.Add(pathname, dstPath);\r
185                         }\r
186                     } else {\r
187                         Log.WriteLine(LogPrefix + "Could not find file {0} to copy.", srcFilePath);\r
188                     }\r
189                 }\r
190             }\r
191 \r
192             // do all the actual copy operations now...\r
193             DoFileOperations();\r
194         }\r
195     }\r
196 }\r