New tests.
[mono.git] / mcs / class / Microsoft.Build.Tasks / Microsoft.Build.Tasks / Copy.cs
index 95ff042fac599303867947cf0c2f45565541024b..a090e4716d46179eac1ac836c997a2500907297e 100644 (file)
@@ -29,6 +29,7 @@
 
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.IO;
 using Microsoft.Build.Framework;
 using Microsoft.Build.Utilities;
@@ -48,71 +49,78 @@ namespace Microsoft.Build.Tasks {
 
                public override bool Execute ()
                {
+                       if (sourceFiles.Length == 0)
+                               // nothing to copy!
+                               return true;
+
                        try {
-                               ArrayList temporaryCopiedFiles = new ArrayList ();
+                               List <ITaskItem> temporaryCopiedFiles = new List <ITaskItem> ();
                        
-                               if (sourceFiles.Length != destinationFiles.Length)
-                                       throw new Exception ("Number of source files is different than number of destination files.");
-                               if (destinationFiles != null && destinationFolder != null)
-                                       throw new Exception ("You must specify only one attribute from DestinationFiles and DestinationFolder");
-                               if (destinationFiles != null) {
-                                       IEnumerator source, destination;
-                                       source = sourceFiles.GetEnumerator ();
-                                       destination = destinationFiles.GetEnumerator ();
-                                       source.Reset ();
-                                       destination.Reset ();
-                                       while (source.MoveNext ()) {
-                                               destination.MoveNext ();
-                                               ITaskItem sourceItem = (ITaskItem) source.Current;
-                                               ITaskItem destinationItem = (ITaskItem) destination.Current;
+                               if (sourceFiles != null && destinationFiles != null &&
+                                       sourceFiles.Length != destinationFiles.Length) {
+                                       Log.LogError ("Number of source files is different than number of destination files.");
+                                       return false;
+                               }
+
+                               if (destinationFiles != null && destinationFolder != null) {
+                                       Log.LogError ("You must specify only one attribute from DestinationFiles and DestinationFolder");
+                                       return false;
+                               }
+
+                               if (destinationFiles != null && destinationFiles.Length > 0) {
+                                       for (int i = 0; i < sourceFiles.Length; i ++) {
+                                               ITaskItem sourceItem = sourceFiles [i];
+                                               ITaskItem destinationItem = destinationFiles [i];
                                                string sourceFile = sourceItem.GetMetadata ("FullPath");
                                                string destinationFile = destinationItem.GetMetadata ("FullPath");
 
-                                               if (skipUnchangedFiles == true) {
-                                                       FileInfo sourceInfo = new FileInfo (sourceFile);
-                                                       FileInfo destinationInfo = new FileInfo (destinationFile);
-                                                       if (sourceInfo.Length == destinationInfo.Length && File.GetLastWriteTime(sourceFile) <=
-                                                               File.GetLastWriteTime (destinationFile))
-                                                               continue;
+                                               if (!File.Exists (sourceFile)) {
+                                                       Log.LogError ("Cannot copy {0} to {1}, as the source file doesn't exist.", sourceFile, destinationFile);
+                                                       continue;
                                                }
-                                               File.Copy (sourceFile, destinationFile);
-                                               temporaryCopiedFiles.Add (source.Current);
+
+                                               if (!skipUnchangedFiles || HasFileChanged (sourceFile, destinationFile))
+                                                       CopyFile (sourceFile, destinationFile, true);
+
+                                               sourceItem.CopyMetadataTo (destinationItem);
+                                               temporaryCopiedFiles.Add (destinationItem);
                                        }
                                        
                                } else if (destinationFolder != null) {
-                                       bool directoryCreated = false;
+                                       List<ITaskItem> temporaryDestinationFiles = new List<ITaskItem> ();
                                        string destinationDirectory = destinationFolder.GetMetadata ("FullPath");
-                                       if (Directory.Exists (destinationDirectory) == false) {
-                                               Directory.CreateDirectory (destinationDirectory);
-                                               directoryCreated = true;
-                                       }
+                                       bool directoryCreated = CreateDirectoryIfRequired (destinationDirectory);
                                        
-                                       IEnumerator source;
-                                       source = sourceFiles.GetEnumerator ();
-                                       source.Reset ();
-                                       while (source.MoveNext ()) {
-                                               ITaskItem sourceItem = (ITaskItem) source.Current;
+                                       foreach (ITaskItem sourceItem in sourceFiles) {
                                                string sourceFile = sourceItem.GetMetadata ("FullPath");
                                                string filename = sourceItem.GetMetadata ("Filename") + sourceItem.GetMetadata ("Extension");
                                                string destinationFile = Path.Combine (destinationDirectory,filename);
 
-                                               if (skipUnchangedFiles == true && directoryCreated == false) {
-                                                       FileInfo sourceInfo = new FileInfo (sourceFile);
-                                                       FileInfo destinationInfo = new FileInfo (destinationFile);
-                                                       if (sourceInfo.Length == destinationInfo.Length && File.GetLastWriteTime(sourceFile) <=
-                                                               File.GetLastWriteTime (destinationFile))
-                                                               continue;
+                                               if (!File.Exists (sourceFile)) {
+                                                       Log.LogError ("Cannot copy {0} to {1}, as the source file doesn't exist.", sourceFile, destinationFile);
+                                                       continue;
                                                }
-                                               File.Copy (sourceFile, destinationFile);
-                                               temporaryCopiedFiles.Add (source.Current);
+
+                                               if (!skipUnchangedFiles || directoryCreated ||
+                                                       HasFileChanged (sourceFile, destinationFile))
+                                                       CopyFile (sourceFile, destinationFile, false);
+
+                                               temporaryCopiedFiles.Add (new TaskItem (
+                                                               Path.Combine (destinationFolder.GetMetadata ("Identity"), filename),
+                                                               sourceItem.CloneCustomMetadata ()));
+
+                                               temporaryDestinationFiles.Add (new TaskItem (
+                                                               Path.Combine (destinationFolder.GetMetadata ("Identity"), filename),
+                                                               sourceItem.CloneCustomMetadata ()));
                                        }
+                                       destinationFiles = temporaryDestinationFiles.ToArray ();
                                } else {
-                                       throw new Exception ("You must specify DestinationFolder or DestinationFiles attribute.");
+                                       Log.LogError ("You must specify DestinationFolder or DestinationFiles attribute.");
+                                       return false;
                                }
-                               copiedFiles = new ITaskItem [temporaryCopiedFiles.Count];
-                               int i  = 0;
-                               foreach (ITaskItem file in temporaryCopiedFiles)
-                                       copiedFiles [i++] = file;
+                               
+                               copiedFiles = temporaryCopiedFiles.ToArray ();
+
                                return true;
                        }
                        catch (Exception ex) {
@@ -128,6 +136,7 @@ namespace Microsoft.Build.Tasks {
                        }
                }
 
+               [Output]
                public ITaskItem[] DestinationFiles {
                        get {
                                return destinationFiles;
@@ -155,6 +164,7 @@ namespace Microsoft.Build.Tasks {
                        }
                }
 
+               [Required]
                public ITaskItem[] SourceFiles {
                        get {
                                return sourceFiles;
@@ -163,7 +173,40 @@ namespace Microsoft.Build.Tasks {
                                sourceFiles = value;
                        }
                }
+
+               // returns whether directory was created or not
+               bool CreateDirectoryIfRequired (string name)
+               {
+                       if (Directory.Exists (name))
+                               return false;
+
+                       Log.LogMessage ("Creating directory '{0}'", name);
+                       Directory.CreateDirectory (name);
+                       return true;
+               }
+
+               void CopyFile (string source, string dest, bool create_dir)
+               {
+                       if (create_dir)
+                               CreateDirectoryIfRequired (Path.GetDirectoryName (dest));
+                       Log.LogMessage ("Copying file from '{0}' to '{1}'", source, dest);
+                       if (String.Compare (source, dest) != 0)
+                               File.Copy (source, dest, true);
+               }
+
+               bool HasFileChanged (string source, string dest)
+               {
+                       if (!File.Exists (dest))
+                               return true;
+
+                       FileInfo sourceInfo = new FileInfo (source);
+                       FileInfo destinationInfo = new FileInfo (dest);
+
+                       return !(sourceInfo.Length == destinationInfo.Length &&
+                                       File.GetLastWriteTime(source) <= File.GetLastWriteTime (dest));
+               }
+
        }
 }
 
-#endif
\ No newline at end of file
+#endif